Di Python, fungsi adalah urutan pernyataan-pernyataan yang diberikan nama dan merupakan satu kesatuan. Tujuan utamanya adalah untuk membantu kita menyusun progam menjadi bilahan-bilahan yang cocok dengan bagaimana cara kita memikirkan masalahnya.
Syntax untuk mendefinisikan fungsi adalah:
def NAMA( PARAMETER ): PERNYATAAN
Kita bisa menggunakan nama apa saja yang kita mau untuk fungsi yang kita buat, kecuali kita tidak bisa menggunakan nama yang merupakan bagian dari keyword Python seperti yang telah dijelaskan dalam bab sebelumnya, dan namanya juga harus mengikuti aturan untuk legal identifier.
Bisa terdapat banyak pernyataan di dalam fungsi, dan penulisannya harus bertakuk ke dalam dari keyword def
. Pada contoh-contoh di buku ini, kita akan menggunakan indentasi standar sebanyak empat spasi. Definisi fungsi merupakan yang kedua dari beberapa pernyataan majemuk (compound statements) yang akan kita lihat, semuanya memiliki pola sama:
- Baris header yang dimulai dengan sebuah keyword dan diakhiri dengan titik dua.
- Body yang terdiri dari satu atau banyak pernyataan Python, masing-masing bertakuk dalam jumlah yang sama -- Python style guide merekomendasikan 4 spasi -- dari baris header.
Kita sudah melihat perulangan for
yang juga menggunakan pola ini.
Sekarang perhatikan lagi pada definisi fungsi, keyword yang digunakan pada header adalah def
, yang kemudian diikuti oleh nama fungsi dan beberapa parameter yang diapit dengan tanda kurung. List parameter
bisa saja dikosongkan, atau bisa berisi banyak parameter yang dipisahkan antara satu dengan yang lain menggunakan tanda koma. Dalam kedua kasus, baik dengan parameter atau tanpa parameter, tanda kurung tetap diperlukan. Parameter menentukan informasi apa, jika ada, yang kita harus sediakan untuk bisa menggunakan fungsi baru tersebut.
Anggap kita sedang bermain dengan turtle, dan operasi umum yang kita perlukan adalah untuk menggambar persegi. "Gambar sebuah persegi" adalah sebuah abstraksi (abstraction), atau mental pembilahan, beberapa jumlah dari langkah-langkah yang lebih kecil. Mari tulis sebuah fungsi untuk menangkap pola dari "blok bangunan" ini:
import turtle def draw_square(t, sz): """Suruh turtle t menggambar sebuah kotak dari sz.""" for i in range(4): t.forward(sz) t.left(90) wn = turtle.Screen() # Atur window dan atributnya wn.bgcolor("lightgreen") wn.title("Alex meets a function") alex = turtle.Turtle() # Buat alex draw_square(alex, 50) # Panggil fungsi untuk menggambar kotak wn.mainloop()
[[{"fid":"433","view_mode":"default","fields":{"format":"default","field_file_image_alt_text[und][0][value]":"alex04.png","field_file_image_title_text[und][0][value]":"alex04.png"},"type":"media","link_text":null,"attributes":{"alt":"alex04.png","title":"alex04.png","height":"243","width":"273","class":"media-element file-default"}}]]
Fungsi yang kita buat ini dinamakan draw_square
. Ia memiliki dua parameter: pertama untuk memberitahu fungsi, turtle yang mana yang harus digerakan, dan yang kedua untuk memberitahu ukuran dari persegi yang ingin kita gambar. Pastikan kamu tahu dimana body dari fungsinya berakhir -- yang mana bergantung pada indentasi, dan baris kosong tidak berarti dalam kasus ini!
Docstring untuk dokumentasi
Jika yang paling pertama setelah header fungsi adalah sebuah string, maka itu akan ditangani sebagai sebuah docstring dan mendapatkan penanganan spesial di Python dan dalam beberapa tools pemrograman. Contohnya, ketika kita mengetik nama fungsi built-in dengan tanda kurung yang belum di tutup di PySripter, sebuah tooltip akan muncul, memberitahu kita argumen apa yang diambil oleh fungsi itu, dan akan memperlihatkan kepada kita teks lain yang juga ada dalam docstring.
Docstring merupakan kunci utama untuk mendokumentasikan fungsi kita di Python dan bagian dokumentasi tentu sangat penting. Karena siapapun yang nantinya akan memanggil fungsi kita tidak lagi mesti tahu apa yang terjadi pada fungsi atau bagaimana ia bekerja; mereka hanya perlu tahu argumen apa yang diperlukan oleh fungsi kita, apa yang dilakukan, dan apa hasil yang diharapkan akan keluar. Cukup untuk bisa menggunakan fungsi tanpa harus mengobrak-abrik barisan kode fungsi hingga ke akar-akarnya. Ini kembali lagi ke konsep dari abstraksi yang akan kita bahas lebih dalam lagi.
Docstring biasanya dibentuk menggunakan petik tiga kali, tentu karena ini akan memungkinkan kita untuk mengembangkan docstring lagi nanti seperti halnya kita ingin menulis lebih dari satu baris dokumentasi.
Untuk membedakan dengan komentar, sebuah string yang dimulai di awal fungsi (sebuah docstring) adalah dapat diterima oleh Python tools saat runtime. Sebaliknya, komentar seluruhnya dihilangkan ketika program telah di-parse.
Mendefinisikan sebuah fungsi baru tidak membuatnya langsung dijalankan. Untuk menjalankan fungsi kita perlu memanggil fungsinya (function call). Kita sudah melihat bagaimana cara memanggil beberapa fungsi built-in seperti print, range dan int. Function call berisi nama dari fungsi yang akan dieksekusi dan diikuti oleh daftar (list) beberapa nilai, dinamakan sebagai argumen, yang kemudian diberikan nilainya ke parameter dalam definisi fungsi. Jadi pada baris kedua dari akhir program, kita memanggil fungsinya, dan memasukan alex
sebagai turtle yang akan dimanipulasi, dan 50 sebagai ukuran dari persegi yang kita inginkan. Sementara fungsinya dieksekusi, lalu, variabel sz
mengacu ke nilai 50, dan variabel t
mengacu ke instan turtle yang sama yang diacu oleh alex
.
Setelah kita mendefinisikan sebuah fungsi, kita bisa memanggilnya sesering yang kita mau, dan pernyataannya akan dieksekusi setiap kali kita memanggilnya. Dan kita bisa menggunakannya untuk menyuruh turtle kita untuk menggambar sebuah persegi. Pada contoh selanjutnya, kita merubah sedikit fungsi draw_square
, dan kita akan menyuruh si tess
untuk menggambar 15 persegi, dengan beberapa variasi.
import turtle def draw_multicolor_square(t, sz): """Suruh turtle t menggambar kotak warna-warni dari sz.""" for i in ["red", "purple", "hotpink", "blue"]: t.color(i) t.forward(sz) t.left(90) wn = turtle.Screen() # Atur window dan atributnya wn.bgcolor("lightgreen") tess = turtle.Turtle() # Buat tess dan atur beberapa atribut tess.pensize(3) size = 20 # Ukuran dari kotak terkecil for i in range(15): draw_multicolor_square(tess, size) size = size + 10 # Tambahkan ukuran selanjutnya tess.forward(10) # Gerakan tess tess.right(18) # Dan beri beberapa belokan wn.mainloop()
[[{"fid":"434","view_mode":"default","fields":{"format":"default","field_file_image_alt_text[und][0][value]":"tess05.png","field_file_image_title_text[und][0][value]":"tess05.png"},"type":"media","link_text":null,"attributes":{"alt":"tess05.png","title":"tess05.png","height":"169","width":"205","class":"media-element file-default"}}]]
4.2. Fungsi Bisa Memanggil Fungsi Lain
Mari asumsikan sekarang kita ingin sebuah fungsi untuk menggambar persegi panjang. Kita perlu memanggil fungsi dengan argumen berbeda untuk panjang dan lebar. Dan, tidak seperti kasus dari persegi, kita tidak bisa mengulang hal yang sama empat kali, karena keempat sisinya tidak sama.
Jadi akhirnya kita muncul dengan kode bagus ini yang bisa menggambar sebuah persegi panjang.
def draw_rectangle(t, w, h): """Buat turtle t menggambar sebuah persegi panjang dengan panjang w dan lebar h.""" for i in range(2): t.forward(w) t.left(90) t.forward(h) t.left(90)
Nama-nama parameter sengaja dipilih menggunakan huruf tunggal untuk memastikan mereka tidak dipahami dengan salah. Dalam program riil, ketika kita sudah punya pengalaman banyak, kita tentu akan bersikeras menggunakan nama variabel yang lebih baik dari ini. Tapi intinya adalah bahwa program tidak "mengerti" kalau kita menggambar sebuah persegi panjang, atau parameternya merepresentasikan panjang dan lebar. Konsep seperti persegi panjang, panjang, dan lebar merupakan arti yang dimiliki kita manusia, bukan konsep yang dimengerti oleh program atau komputer.
Berpikir layaknya ilmuan komputer melibatkan pencarian pola-pola dan hubungan-hubungan. Pada kode diatas, kita telah melakukan beberapa pengembangan. Kita tidak hanya menggambar empat sisi. Namun, kita menyadari kalau kita bisa menggambar persegi dalam dua bagian, dan menggnakan loop untuk mengulangi polanya dua kali.
Tapi sekarang kita mungkin menyadari kalau persegi adalah jenis spesial dari kotak. Kita sudah punya fungsi untuk menggambar sebuah persegi, jadi kita bisa menggunakannya untuk menggambar persegi kita.
def draw_square(tx, sz): # Versi baru dari draw_square draw_rectangle(tx, sz, sz)
Ada beberapa poin yang perlu diperhatikan disini:
- Fungsi bisa memanggil fungsi lainnya.
- Menulis ulang
draw_square
seperti ini, akan menangkap hubungan yang telah kita lihat antara persegi dan persegi panjang. - Pemanggil (caller) dari fungsi ini mungkin berkata
draw_square(tess, 50)
. Parameter dari fungsi ini,tx
dansz
, masing-masing diberikan nilai dari objek tess, dan juga int 50. - Pada body fungsi mereka juga sama seperti fungsi lainnya.
- Ketika dilakukan pemanggilan ke
draw_rectangle
, nilai dari variabeltx
dansz
diambil pertama kali, lalu pemanggilan berlangsung. Jadi saat kita memasuki bagian atas dari fungsidraw_rectangle
, variabelt
nya diberikan nilai objek tess, danw
danh
pada fungsi tersebut keduanya diberikan nilai 50.
Sejauh ini, mungkin terasa belum jelas kenapa kita mesti membuat semua fungsi baru itu. Sebenarnya asalannya ada banyak, tapi contoh ini cukup mendemonstrasikan dua diantaranya:
- Membuat fungsi baru memberikan kita kesempatan untuk menamai sekumpulan pernyataan. Fungsi bisa menyederhanakan program dengan menyelipkan perhitungan rumit dibalik satu perintah. Fungsi (termasuk namanya) bisa mengasah mental pembilahan kita, atau abstraksi, dari masalah.
- Membuat fungsi baru bisa membuat program menjadi lebih kecil dengan menghilangkan kode-kode yang berulang.
Seperti yang kita duga, kita harus membuat fungsi sebelum kita bisa mengeksekusinya. Dengan kata lain, definisi fungsi mesti dieksekusi sebelum fungsinya dipanggil.
4.3. Flow of Execution (alur eksekusi)
Untuk memastikan kalau fungsi sudah didefinisikan sebelum penggunaan pertamanya, kita mesti tahu urutan dari eksekusi pernyataan, yang dinamakan dengan flow of execution. Kita sudah sempat membahas ini sedikit pada bab sebelumnya.
Eksekusi selalu dimulai dari pernyataan pertama dari program. Pernyataan dieksekusi sekali dalam satu hentakan, dengan urutan dari atas ke bawah.
Definisi fungsi tidak mengubah alur eksekusi dari program, tapi ingat kalau pernyataan didalam fungsi tidak dieksekusi hingga fungsi itu dipanggil. Meskipun tidak umum, kita bisa mendefiniskan satu fungsi didalam fungsi lainnya. Dalam kasus ini, definisi yang berada di dalam tidak dieksekusi hingga fungsi luarnya dipanggil.
Pada alur eksekusi, pemanggilan fungsi (function call) adalah seperti jalan memutar. Daripada pergi ke pernyataan selanjutnya, flow atau alurnya akan melompat ke baris pertama dari fungsi yang dipanggil, mengeksekusi semua pernyataan yang ada disana, dan kembali lagi untuk mengambil pekerjaan selanjutnya dimana ia sebelumnya melompat.
Itu terdengar cukup sederhana, hingga kita ingat kalau satu fungsi bisa memanggil fungsi lainnya. Sementara dalam pertengahan satu fungsi, program mungkin harus melompat lagi dan mengeksekusi pernyataan dalam fungsi lainnya. Tapi sementara fungsi lain tersebut dieksekusi, program mungkin mesti mengeksekusi fungsi lainnya lagi dan lagi!
Syukurnya, Python mahir dalam hal lacak melacak, jadi setiap kali fungsi selesai dijalankan, program akan kembali ke titik dimana ia melompat ke fungsi yang memanggilnya. Ketika sampai pada akhir dari program, ia akan mengakhirinya.
Apa moral dari kisah rumit ini? Ketika kita membaca program, jangan membaca dari atas ke bawah. Tapi, ikuti alur dari eksekusinya.
Amati flow of execution in action
Pada PyScripter, kita bisa mengamati alur dari eksekusi "langkah-demi-langkah" pada program apa saja. PyScripter akan menandai setiap baris kode yang akan dieksekusi.
PyScripter juga memungkinkan kita mengarahkan mouse ke setiap variabel dalam program, dan akan memunculkan nilai yang dipegang variabel saat ini. Jadi ini akan memudahkan kita memeriksa "state of snapshot" dari program -- yaitu nilai sekarang yang diberikan ke variabel program.
Ini adalah mekanisme yang sangat powerful untuk membangun pemahaman yang dalam dari apa yang terjadi pada setiap langkah dari jalannya program. Belajarlah untuk menggunakan fitur single-stepping dengan baik, dan tanamkan mental proaktif: dalam mengerjakan kode-kode program, tantang diri mu sendiri langkah demi langkah: "Perubahan apa yang bisa diakibatkan oleh baris ini pada setiap variabel dalam program?" dan "Kemana alur eksekusi akan melanjutkan?"
Mari kita mundur kebelakang untuk melihat bagaimana ini bekerja pada program diatas yang menggambar 15 persegi warna-warni. Pertama, kita akan menambahkan satu baris ajaib dibawah pernyataan import -- tidak terlalu penting, tapi ini akan membuat hidup kita jauh lebih mudah, karena ini akan mencegah stepping ke modul yang berisi kode turtle.
import turtle __import__("turtle").__traceable__ = False
Sekarang kita siap untuk mulai. Letakan kursor mouse pada baris dari program dimana kita membuat screen turtle, dan tekan tombol F4. Ini akan menjalankan program Python hingga ke, tapi tidak termasuk, baris dimana kita meletakan kursornya. Program kita akan "berhenti" sekarang, dan membuat tanda pada baris berikutnya yang akan dieksekusi, yang terlihat seperti ini:
[[{"fid":"435","view_mode":"wysiwyg","fields":{"format":"wysiwyg","field_file_image_alt_text[und][0][value]":"python_PyScripter_breakpoint.png","field_file_image_title_text[und][0][value]":"python_PyScripter_breakpoint.png"},"type":"media","link_text":null,"attributes":{"alt":"python_PyScripter_breakpoint.png","title":"python_PyScripter_breakpoint.png","height":"305","width":"400","class":"media-element file-wysiwyg"}}]]
Pada poin ini kita bisa menekan tombol F7 (melangkah ke) berulangkali untuk bergerak satu langkah eksekusi. Amati ketika kita mengeksekusi baris 10, 11, 12, ... bagaimana window dari turtle dibuat, bagaimana canvasnya berubah warna, bagaimana judulnya berganti, bagaimana turtle dibuat pada canvas, dan kemudian bagaimana flow of execution bergerak memasuki loop, dan dari sana masuk ke fungsi, dan masuk lagi ke loop fungsi, dan berulang kali mengeksekusi body dari loop.
Sementara kita melakukan ini, kita bisa juga mengarahkan mousenya ke beberapa variabel pada program, dan memastikan nilai mereka cocok dengan model konseptual dan bayangan kita mengenai apa yang terjadi.
Setelah beberapa loop, ketika kita akan mengeksekusi baris 20 dan kita mulai merasa bosan mengulang-ngulang, kita bisa menggunakan tombol F8 untuk "step over / menjalankan tanpa stepping" fungsi yang kita panggil. Ini akan mengeksekusi semua pernyataan dalam fungsi, tapi tanpa melakukannya langkah demi langkah. Kita selalu punya pilihan untuk "melihat dengan detil", atau "melihat secara garis besar" dan mengeksekusi fungsi sebagai satu bilahan.
Terdapat pula beberapa pilihan lain, termasuk satu yang memungkinkan kita untuk melanjutkan eksekusi tanpa harus melakukan stepping lagi. Temukan opsi ini pada menu Run dari PyScripter.
4.4. Fungsi yang Memerlukan Argument
Kebanyakan fungsi akan memerlukan argumen: argumen-argumen menyediakan generalisasi. Contohnya, jika kita ingin mencari nilai absolut dari sebuah bilangan, kita harus menunjukan apa bilangan tersebut. Python memiliki fungsi built-in untuk menghitung nilai absolut:
>>> abs(5) 5 >>> abs(-5) 5
Dalam contoh ini, argmen untuk fungsi abs
adalah 5 dan - 5.
Beberapa fungsi mengambil lebih dari satu argument. Contohnya fungsi built-in pow
yang mengambil dua argumen, bilangan basis dan eksponennya. Di dalam fungsi, nilai yang dimasukan akan diberikan ke variabel yang dinamakan parameter.
>>> pow(2, 3) 8 >>> pow(7, 4) 2401
Fungsi built-in yang juga mengambil lebih dari satu argumen adalah max
.
>>> max(7, 11) 11 >>> max(4, 1, 17, 2, 12) 17 >>> max(3 * 11, 5**3, 512 - 9, 1024**0) 503
max
bisa dimasukan argumen bilangan apa saja, dipisahkan dengan koma, dan akan mengembalikan nilai yang paling besar. Argumennya juga bisa berbentuk nilai ekspresi sederhana. Pada contoh sebelumnya, 503 dikembalikan, karena nilainya lebih besar dari 33, 125, dan 1.
4.5. Fungsi yang Mengembalikan Nilai (return)
Semua fungsi pada sesi sebelumnya mengembalikan nilai. Lebih jauh lagi, fungsi seperti range
, int
, abs
semua mengembalikan nilai yang bisa digunakan untuk membangun ekspresi yang jauh lebih rumit.
Jadi perbedaan terpenting antara fungsi tersebut dengan fungsi seperti draw_square
adalah bahwa draw_square
dieksekusi karena kita tidak menginginkan dia untuk menghitung dan mengembalikan sebuah nilai -- namun sebaliknya, kita menulis draw_square
karena kita ingin mengeksekusi urutan langkah-langkah yang menyebabkan turtle menggambar.
Fungsi yang me-return / mengembalikan sebuah nilai dalam buku ini dinamakan dengan fruitful function. Lawan dari fruitful function adalah void function -- fungsi yang dieksekusi bukan untuk mendapatkan nilai, tapi dieksekusi karena ia melakukan sesuatu yang berguna. (Bahasa seperti Java, C#, C dan C++ menggunakan istilah "void function", bahasa lain seperti Pascal menamainya procedure.) Meskipun void function tidak dieksekusi untuk menghasilkan sebuah nilai, Python selalu ingin mengembalikan sesuatu, jadi jika programmer tidak menyusun sebuah nilai return, Python akan dengan otomatis mereturn dengan nilai None
.
Bagaimana kita menyusun fruitful function kita sendiri? Pada latihan diakhir bab 2 kita melihat rumus standar untuk bunga berganda, yang sekarang kita akan coba tulis sebagai fruitful function:
[[{"fid":"436","view_mode":"default","fields":{"format":"default","field_file_image_alt_text[und][0][value]":"compoundInterest.png","field_file_image_title_text[und][0][value]":"compoundInterest.png"},"type":"media","link_text":null,"attributes":{"alt":"compoundInterest.png","title":"compoundInterest.png","height":"166","width":"396","class":"media-element file-default"}}]]
def final_amt(p, r, n, t): """ Masukan rumus bunga berganda ke p untuk mendapatkan jumlah akhir. """ a = p * (1 + r/n) ** (n*t) return a # Ini tambahan baru, yang membuat fungsi menjadi fruitful # sekarang kita sudah punya fungsi diatas, coba kita panggil toInvest = float(input("How much do you want to invest?")) fnl = final_amt(toInvest, 0.08, 12, 5) print("At the end of the period you'll have", fnl)
- Pernyataan return diikuti dengan sebuah ekspresi (dalam kasus ini
a
). Ekspresi ini akan dinilai dan dikembalikan ke pemanggil sebagai "fruit/buah" dari pemanggilan fungsi ini. - Kita menanyakan pengguna berapa principal amount-nya (jumlah pokok). Tipe dari
toInvest
adalah string, tapi kita perlu tipe angka sebelum bisa menggunakannya. Karena ini adalah uang, dan bisa memiliki angka dibelakang koma, kita menggunakan konverter tipefloat
untuk mem-parse string dan mengembalikan sebuah float. - Perhatikan bagaimana kita memasukan argumen untuk interest 8%, dicicil 12 kali setahun, untuk 5 tahun.
- Ketika kita menjalankannya, kita mendapatkan output:
At the end of the period you’ll have 14898.457083
Terlihat cukup kotor dengan semua angka dibelakang komanya, tapi ingat kalau Python tidak mengerti kalau kita bekerja dengan uang: ia hanya melakukan perhitungan dengan kemampuan terbaiknya tanpa pembulatan. Nanti kita akan tahu bagaimana mem-format string sehingga bisa melakukan pembulatan dua angka sebelum mencetaknya ke layar.
- Baris
toInvest = float(input("How much do you want to invest?"))
juga memperlihatkan contoh lainnya dari komposisi -- kita bisa memanggil fungsi seperti float, dan argumennya bisa merupakan hasil dari pemanggilan fungsi lainnya (sepertiinput
) yang telah sering kita panggil.
Perhatikan hal lain yang juga sangat penting disini. Nama dari variabel yang kita masukan sebagai argumen -- toInvest
-- tidak ada kaitannya dengan nama dari parameternya -- p
. Artinya sama dengan p = toInvest
dieksekusi ketika final_amt
dipanggil. Tidak penting apa nama yang dipakai pada pemanggil (caller), pada final_amt
namanya tetaplah p
.
Nama singkat variabel menjadi sedikit menyulitkan, jadi mungkin kita lebih memilih menggunakan versi ini:
def final_amt_v2(principalAmount, nominalPercentageRate, numTimesPerYear, years): a = principalAmount * (1 + nominalPercentageRate / numTimesPerYear) ** (numTimesPerYear*years) return a def final_amt_v3(amt, rate, compounded, years): a = amt * (1 + rate/compounded) ** (componded*years) return a
Keduanya melakukan hal yang sama. Gunakan penilaian mu untuk menulis kode yang bisa dimengerti dengan baik oleh orang lain! Variabel dengan nama singkat lebih ekonomis dan kadang membuat kode lebih mudah untuk dibaca: E = mc2 akan sangat sulit dimengeri jika Einstein menggunakan nama variabel yang lebih panjang! Jika kamu lebih suka nama singkat, maka pastikan kamu juga punya beberapa komentar untuk menjelaskan pada pembaca mengenai apa guna dari variabel tersebut.
4.6. Variabel dan Parameter Lokal
Ketika kita membuat variabel lokal di dalam sebuah fungsi, maka ia hanya akan ada di dalam fungsi tersebut, dan kita tidak bisa menggunakannya diluar. Contoh, pertimbangkan lagi fungsi berikut:
def final_amt(p, r, n, t): a = p * (1 + r/n) ** (n*t) return a
Jika kita mencoba menggunakan a
, diluar fungsi, kita akan mendapatkan error seperti ini:
>>> a NameError: name 'a' is not defined
Variabel a
bersifat lokal dan berada dalam fungsi final_amt
, dan tidak terlihat diluar fungsi.
Tambahan lagi, a
hanya ada ketika fungsi dieksekusi -- kita menamai ini sebagai lifetime (waktu hidup / umur). Ketika eksekusi dari fungsi telah selesai, maka variabel lokal akan dihancurkan.
Parameter juga sifatnya lokal, dan berprilaku juga seperti variabel lokal. Sebagai contoh, lifetime dari p
, r
, n
, t
dimulai ketika final_amt
dipanggil, dan lifetimenya berakhir ketika fungsinya selesai dieksekusi.
Jadi tidak dimungkinkan untuk sebuah fungsi mengatur beberapa variabel lokal ke sebuah nilai, menyelesaikan eksekusi, lalu kemudian ketika ia dipanggil dan dieksekusi lagi dilain waktu, ia masih menyimpan dan mengembalikan nilai dari variabel lokalnya. Setiap pemanggilan fungsi akan membuat variabel lokal baru, dan lifetimenya habis ketika fungsinya berakhir dan kembali ke pemanggil.
4.7. Turtle Revisited
Sekarang kita telah mengetahui fruitful function, kita bisa fokuskan perhatian kita untuk mengatur kode kita sehingga akan masuk lebih baik ke dalam mental pembilahan kita. Proses dari pengaturan ulang ini dinamakan dengan refactoring the code.
Dua hal yang selalu kita ingin lakukan ketika bekerja dengan turtle adalah untuk membuat window untuk turtle, dan membuat satu atau lebih turtle. Kita bisa menulis beberapa fungsi untuk membuat tugas tersebut lebih mudah nanti:
def make_window(colr, ttle): """ Set up the window with the given background color and title. Returns the new window. """ w = turtle.Screen() w.bgcolor(colr) w.title(ttle) return w def make_turtle(colr, sz): """ Set up a turtle with the given color and pensize. Returns the new turtle. """ t = turtle.Turtle() t.color(colr) t.pensize(sz) return t wn = make_window("lightgreen", "Tess and Alex dancing") tess = make_turtle("hotpink", 5) alex = make_turtle("black", 1) dave = make_turtle("yellow", 2)
Trik dari refactoring code adalah mengantisipasi bagian mana yang perlu kita ganti setiap kali kita memanggil fungsinya: bagian-bagian itu umumnya adalah parameter, atau bagian yang bisa diganti, dari fungsi yang kita tulis.
4.8. Glosarium
argumen
Nilai yang disediakan untuk fungsi ketika fungsi dipanggil. Nilai ini diberikan ke parameter yang terkait di dalam fungsi. Argumen bisa merupakan hasil dari sebuah ekspresi yang melibatkan operator, operand dan pemanggilan ke fungsi fruitful lainnya.
body
Bagian kedua dari pernyataan manjemuk (compound statements). Body terdiri dari urutan statement / pernyataan yang semua bertakuk dengan jumlah takukan yang sama yang dimulai dari header. Jumlah indentasi / takukan standar dalam komunitas Python adalah 4 spasi.
compound statement (penyataan majemuk)
Pernyataan yang terdiri dari dua bagian:
1. header - yang dimulai dengan sebuah keyword yang menentukan tipe pernyataan, dan diakhiri dengan sebuah tanda titik dua.
2. body - berisi satu atau lebih pernyataan yang bertakuk (indented) dengan jumlah takukan yang sama dimulai dari header.
Syntax dari compound statement terlihat seperti berikut:
statement
statement ...
docstring
String spesial yang dikaitkan ke sebuah fungsi sebagai atribut dokumentasi __doc___
. Tool seperti PyScripter bisa menggunakan docstring untuk menyediakan dokumentasi atau petunjuk untuk programmer. Ketika kita menggunakan modul, kelas, dan metode, kita juga akan tahu kalau docstring juga digunakan disana.
flow of execution
Urutan dari statement yang dieksekusi selama program berjalan.
frame
Sebuah kotak dalam diagram stack yang merepresentasikan pemanggilan fungsi. Ia berisi variabel lokal dan parameter dari fungsi.
function (fungsi)
Urutan pernyataan yang diberikan nama dan melakukan operasi yang berguna. Fungsi bisa memerlukan atau tidak memerlukan parameter dan menghasilkan atau tidak menghasilkan sebuah hasil.
function call (pemanggilan fungsi)
Pernyataan yang mengeksekusi sebuah fungsi. Ia terdiri dari nama fungsi diikuti dengan daftar argumen yang diapit oleh tanda kurung.
function composition
Menggunakan output dari satu pemanggilan fungsi sebagai input untuk fungsi lainnya.
function definition
Pernyataan yang membuat fungsi baru, menentukan namanya, parameter, dan pernyataan yang dieksekusinya.
fruitful function
Fungsi yang me-return / mengembalikan sebuah nilai ketika ia dipanggil.
header line (baris header)
Bagian pertama dari compound statement. Baris header dimulai dengan sebuah keyword dan diakhiri dengan sebuah tanda titik dua (:).
import statement
Pernyataan yang mengijinkan fungsi dan variabel yang didefinisikan dalam modul Python lain agar masuk ke lingkungan dari script lain. Untuk menggunakan fitur dari turtle, kita pertama-tama mesti mengimport modul turtle.
lifetime (waktu hidup / umur)
Variabel dan objek memiliki lifetime -- mereka dibuat pada suatu titik selama eksekusi program, dan akan dihancurkan pada suatu waktu atau ketika eksekusi berakhir.
local variable (variabel lokal)
Variabel yang didefinisikan didalam sebuah fungsi. Variabel lokal hanya bisa digunakan didalam fungsinya sendiri. Parameter dari sebuah fungsi adalah jenis spesial dari variabel lokal.
parameter
Nama yang digunakan didalam sebuah fungsi untuk mengacu pada nilai yang dimasukan kedalamnya sebagai sebuah argumen.
refactor
Istilah keren untuk menjelaskan penyusunan ulang kode program kita, biasanya digunakan untuk membuatnya lebih mudah dimengerti. Khususnya, kita memiliki program yang sudah bekerja, lalu kita mengopreknya kembali untuk "mengencangkannya". Proses ini umumnya melibatkan pemilihan nama variabel yang lebih bagus, atau pencarian pola-pola berulang dan memindahkan kode tersebut ke sebuah fungsi.
stack diagram
Representasi grafis dari tumpukan fungsi-fungsi, variabel mereka, dan nilai yang mereka acu.
traceback
Daftar fungsi yang dieksekusi, dan akan tercetak pada saat terjadi runtime error. Traceback umumnya juga dikaitkan dengan stack trace, karena ia mencatat urutan fungsi yang disimpan di runtime stack.
void function
Lawan dari fruitful function: jenis fungsi yang tidak me-return atau mengembalikan nilai. Ia dieksekusi untuk pekerjaan yang dilakukannya, ketimbang untuk nilai yang ia kembalikan.
4.9. Latihan
1. Tulis void function (non-fruitful) untuk menggambar sebuah persegi. Gunakan untuk menggambar gambar dibawah. Asumsikan setiap sisinya adalah 20 unit. (Petunjuk: perhatikan bahwa turtle sudah bergerak menjauh dari titik akhir dari persegi terkahir ketika programnya berakhir.)
[[{"fid":"437","view_mode":"default","fields":{"format":"default","field_file_image_alt_text[und][0][value]":"five_squares.png","field_file_image_title_text[und][0][value]":"five_squares.png"},"type":"media","link_text":null,"attributes":{"alt":"five_squares.png","title":"five_squares.png","height":"106","width":"285","class":"media-element file-default"}}]]
2. Buat program untuk menggambar ini. Asumsikan kotak yang paling dalam 20 unit per sisi, dan setiap persegi baru 20 unit lebih besar, per sisi, dari persegi didalamnya.
[[{"fid":"438","view_mode":"default","fields":{"format":"default","field_file_image_alt_text[und][0][value]":"nested_squares.png","field_file_image_title_text[und][0][value]":"nested_squares.png"},"type":"media","link_text":null,"attributes":{"alt":"nested_squares.png","title":"nested_squares.png","height":"150","width":"190","class":"media-element file-default"}}]]
3. Buat fungsi void draw_poly(t, n, sz)
yang akan membuat turtle menggambar poligon reguler (sama sisi). Ketika dipanggil dengan draw_poly(tess, 8, 50)
, ia akan menggambar bentuk seperti ini:
[[{"fid":"439","view_mode":"default","fields":{"format":"default","field_file_image_alt_text[und][0][value]":"regularpolygon.png","field_file_image_title_text[und][0][value]":"regularpolygon.png"},"type":"media","link_text":null,"attributes":{"alt":"regularpolygon.png","title":"regularpolygon.png","height":"154","width":"164","class":"media-element file-default"}}]]
4. Gambar pola yang cantik ini:
[[{"fid":"440","view_mode":"default","fields":{"format":"default","field_file_image_alt_text[und][0][value]":"tess08.png","field_file_image_title_text[und][0][value]":"tess08.png"},"type":"media","link_text":null,"attributes":{"alt":"tess08.png","title":"tess08.png","height":"318","width":"302","class":"media-element file-default"}}]]
5. Dua spiral pada gambar berikut hanya berbeda karena sudut putarnya. Coba gambar keduanya.
[[{"fid":"441","view_mode":"wysiwyg","fields":{"format":"wysiwyg","field_file_image_alt_text[und][0][value]":"tess_spirals.png","field_file_image_title_text[und][0][value]":"tess_spirals.png"},"type":"media","link_text":null,"attributes":{"alt":"tess_spirals.png","title":"tess_spirals.png","height":"179","width":"400","class":"media-element file-wysiwyg"}}]]
6. Tulis sebuah fungsi void draw_equitriangle(t, sz)
yang memanggil draw_poly
dari pertanyaan sebelumnya untuk membuat turtle menggambar segitiga sama sisi.
7. Tulis fungsi fruitful sum_to(n)
yang mengembalikan sum dari semua integer hingga dan termasuk n
. Jadi sum_to(10)
akan menjadi 1+2+3...+10 yang akan mengembalikan / me-return nilai 55.
8. Tulis sebuah fungsi area_of_circle(r)
yang me-return luas lingkaran dari radius r
.
9. Buat fungsi void untuk menggambar sebuah bintang, dimana panjang dari setiap sisinya adalah 100 unit. (Petunjuk: Kamu mesti memutar turtle 144 derajat pada setiap titiknya.)
[[{"fid":"419","view_mode":"default","fields":{"format":"default","field_file_image_alt_text[und][0][value]":"Star Bintang","field_file_image_title_text[und][0][value]":"Star Bintang"},"type":"media","link_text":null,"attributes":{"alt":"Star Bintang","title":"Star Bintang","height":"105","width":"115","class":"media-element file-default"}}]]
10. Kembangkan program yang kamu buat tadi. Gambar 5 bintang, tapi untuk mebuat jarak, angkat pensilnya, gerakan maju 350 unit, putar kanan 144 derajat, turunkan lagi pensilnya, dan gambar bintang selanjutnya. Kamu akan mendapatkan hasil seperti ini:
[[{"fid":"442","view_mode":"wysiwyg","fields":{"format":"wysiwyg","field_file_image_alt_text[und][0][value]":"five_stars.png","field_file_image_title_text[und][0][value]":"five_stars.png"},"type":"media","link_text":null,"attributes":{"alt":"five_stars.png","title":"five_stars.png","height":"360","width":"400","class":"media-element file-wysiwyg"}}]]
Apa yang akan terjadi jika kamu tidak mengangkat pensilnya ?
Komentar Terbaru