Functions

Sampai dengan sekarang, semua kode Python yang kita tulis berupa potongan-potongan kode dan dijalankan secara sendiri-sendiri. Ini mungkin berguna dan dipakai untuk eksplorasi dan eksekusi singkat, tapi jika skrip kode sudah mulai kompleks, tidak mungkin kita menulis ulang semua kode tersebut. Oleh karena itu, diperlukan suatu cara untuk mengelompokkan dan mengorganisir kode menjadi bagian-bagian yang lebih mudah untuk di kelola.

Cara pertama yang bisa dilakukan adalah mengumpulkan kode-kode yang memiliki alur dan tujuan agar bisa digunakan kembali tanpa menulis ulang kodenya ke dalam sebuah fungsi (function). Kita bisa anggap sebuah fungsi sebagai kumpulan kode yang bekerja untuk suatu tugas tertentu yang bisa menerima input apapun jenisnya dan berapapun jumlahnya, serta mengembalikan output apapun jenisnya dan berapapun jumlahnya. [Lub19]

Mendefinisikan Fungsi dengan def

Untuk mendefinisikan fungsi, kita mulai dengan kata kunci def, diikuti oleh nama fungsi (aturan penamaan sama dengan variabel), tanda kurung (()) yang berisikan nol atau lebih parameter masukan yang diperlukan fungsi tersebut, dan diakhiri dengan :.

Mari kita coba definisikan fungsi yang paling sederhana terlebih dahulu yang tidak memerlukan parameter masukan apapun dan tidak melakukan apapun.

def do_nothing():
    pass

Note

Pernyataan pass pada Python digunakan sebagai penampung atau placeholder untuk kode nantinya. Ketika dieksekusi, pass tidak melakukan apa-apa, tapi kode tetap berjalan tanpa eror kekosongan kode, karena kode kosong (empty code) tidak diperbolehkan dalam sebuah perulangan, pendefinisian fungsi, pendefinisan kelas (class), atau pernyataan kondisional if.

def do_nothing():
    pass

Untuk menggunakan fungsi tersebut, kita bisa langsung panggil seperti ini.

do_nothing()

Sekarang, kita coba buat fungsi baru yang masih tidak memerlukan parameter masukan, tapi akan menampilkan suatu string dengan fungsi print.

def make_sound():
    print("moo..")
make_sound()
moo..

Fungsi make_sound yang sudah didefinisikan, jika dipanggil, akan menampilkan string "moo.." sesuai dengan blok kode di dalamnya.

Pernyataan return pada Fungsi

Sekarang, kita coba buat fungsi yang mengembalikan sebuah nilai True seperti di bawah ini.

def agree():
    return True
agree()
True

Suatu fungsi yang memiliki pernyataan return, akan mengembalikan sebuah nilai keluaran ke pernyataan yang memanggilnya. Pernyataan return terdiri dari kata kunci return yang kemudian diikuti oleh nilai balikan, dan dipisahkan dengan spasi. Jika kita ingin mengembalikan lebih dari satu nilai dari suatu fungsi, maka kita bisa tulis nilai-nilai tersebut dan dipisahkan dengan ,, seperti return value1, value2.

Note

Suatu fungsi yang tidak memiliki pernyataan return, seperti pada fungsi do_nothing ataupun make_sound, maka nilai balikannya adalah None.

Untuk membandingkan fungsi dengan return dan yang tidak, mari kita coba definisikan sebuah variabel sound dan is_agree dengan memanggil fungsi make_sound dan agree secara berturut-turut.

sound = make_sound()
is_agree = agree()
moo..

Setelah kita jalankan cell di atas, kita mendapatkan tampilan moo.. yang berasal dari fungsi make_sound. Sedangkan, variabel is_agree tidak menampilkan apa-apa. Ini sama halnya saat kita mendefinisikan variabel sebelumnya, kita hanya memberikan nilai pada variabel.

Jika kita coba tampilkan kedua variabel tersebut dengan print, maka sound tidak akan menampilkan apa-apa, sedangkan is_agree akan menampilkan nilai True. Ini terjadi karena fungsi make_sound tidak mengembalikan nilai apa-apa untuk disimpan dalam variabel sound, sedangkan agree mengembalikan nilai True yang kemudian disimpan dalam variabel is_agree.

print(sound)
None
print(is_agree)
True

Fungsi dengan Parameter Masukan

Misalkan kita ingin membuat sebuah fungsi, yang bisa gunakan berkali-kali, untuk menghitung volume sebuah silinder. Ada beberapa hal yang harus kita ketahui terlebih dahulu:

  1. Nilai \(\Pi\)

  2. Tinggi silinder

  3. Jari-jari silinder

Ingat bahwa persamaan volume silinder adalah

\[ V = \Pi \cdot r^2 \cdot h \]

di mana \(V\) adalah volume yang dihasilkan, \(r\) adalah jari-jari silinder, dan \(h\) adalah tinggi silinder.

Untuk membuat fungsi tersebut dengan 3 nilai yang harus diketahui terlebih dahulu, ini berarti kita bisa membuat fungsi yang membutuhkan parameter masukan, dalam hal ini yaitu r dan h. Nilai \(Pi\) tidak perlu kita anggap sebagai parameter karena nilainya yang selalu konstan. Sehingga, kita definisikan fungsi cylinder_volume seperti di bawah ini.

def cylinder_volume(radius, height):
    pi = 3.14159
    return pi * height * radius**2
volume = cylinder_volume(10, 3)
print("Cylinder volume:", volume)
Cylinder volume: 942.4769999999999

Eksplorasi

Buatlah sebuah fungsi commentary yang menerima masukan dalam parameter color dan mengembalikan string tertentu sesuai dengan nilai color pada tabel di bawah ini.

color

comment

red

It’s a tomato

green

It’s a green pepper

bees

I don’t know what it is, but looks like a bee

Jika nilai color tidak tersedia dalam tabel di atas, kembalikan string dengan pola di bawah ini

"I've never heard of the color yellow before"
def commentary(color):
    # KETIK DI SINI
    pass
green = commentary("green")
red = commentary("red")
yellow = commentary("yellow")

print("Have you heard color green?", green)
print("Have you heard color red?", red)
print("Have you heard color yellow?", yellow)
Have you heard color green? None
Have you heard color red? None
Have you heard color yellow? None

Argumen dan Parameter

Argumen dan parameter beberapa kali disebut pada penjelasan di atas. Kedua istilah ini seringkali disebut untuk mengacu pada hal yang sama, meskipun argumen berbeda dengan parameter. Fungsi cylinder_volume sebelumnya memiliki 2 parameter, height dan radius. Saat cylinder_volume dipanggil, kita menyediakkan 2 argumen, 10 dan 3 untuk radius dan height secara berturut-turut.

Note

Saying it another way: they’re called arguments ouside of the function, but parameters inside. [Lub19]

Kita bisa anggap parameter adalah variabel khusus dalam sebuah fungsi yang nilainya diambil dari argumen yang dimasukkan saat pemanggilan. Pada fungsi echo yang didefinisikan di bawah ini, nilai bitlabs yang kita masukkan saat memanggil fungsi echo akan “diganti” dengan parameter anything dalam fungsi tersebut. Nilai bitlabs disebut sebagai argumen, sedangkan anything adalah parameter dalam fungsi.

def echo(anything):
    return anything + " " + anything
echo("bitlabs")
'bitlabs bitlabs'

Jika kita memasukkan sejumlah argumen yang kurang atau lebih dari jumlah parameter yang seharusnya fungsi tersebut butuhkan, maka kita akan mendapatkan eror TypeError yang memberi tahu kita bahwa ada kesalahan dalam memasukkan argumen. Perhatikan contoh kode di bawah ini.

cylinder_volume(10)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/var/folders/gn/lh5142px2tb1x8mbqzsf3ckh0000gn/T/ipykernel_46164/1510587952.py in <module>
----> 1 cylinder_volume(10)

TypeError: cylinder_volume() missing 1 required positional argument: 'height'
echo(100, 200)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/var/folders/gn/lh5142px2tb1x8mbqzsf3ckh0000gn/T/ipykernel_46164/2668369315.py in <module>
----> 1 echo(100, 200)

TypeError: echo() takes 1 positional argument but 2 were given

Kita bisa memasukkan input langsung sesuai dengan posisi parameter dalam fungsi atau secara tidak berurutan dengan menyediakan nama parameternya.

def is_bounded(x, lower, upper):
    return lower <= x <= upper
is_bounded(2, 3, 4)
False
is_bounded(lower=2, x=3, upper=4)
True

Pemanggilan fungsi yang pertama, is_bounded(2, 3, 4), menghasilkan nilai False karena x=2, lower=3, dan upper=4, sehingga 3 <= 2 <= 4 sama dengan False. Sedangkan, pada pemanggilan fungsi yang kedua, karena kita memasukkan argumen dengan berdasarkan dan menyediakan parameternya, maka meskipun urutan nilai masukannya sama dengan pemanggilan fungsi pertama, tapi kita memberi tahu is_bounded bahwa argumen pertama ditujukan untuk lower dengan menuliskan lower=2. Urutan parameter tidak berlaku di sini dan yang terpenting adalah semua parameter yang dibutuhkan fungsi ditentukan.

# pernyataan di bawah ini semuanya ekuivalen
print(is_bounded(3, 2, 4))
print(is_bounded(upper=4, lower=2, x=3))
print(is_bounded(upper=4, x=3, lower=2))
True
True
True

Pemberian argumen dengan cara seperti ini disebut dengan keyword argument, yaitu pemberian argumen dengan keyword parameter yang dituju.

Note

Keyword argument adalah sebuah argumen yang didahului oleh pengindentifikasi (misal name=) dalam sebuah pemanggilan fungsi. [Fou21c]

Tidak semua argumen harus disediakan dengan keyword argument. Kita juga bisa menggabungkan positional argument dengan keyword argment seperti di bawah ini.

is_bounded(3, lower=2, upper=4)

Potongan kode di atas berarti kita menyediakan argumen 3 sebagai positional argument sehingga akan ditempatkan sesuai dengan posisi pertama parameter fungsi, yaitu x. Sedangkan, argumen 2 dan 3 sebagai keyword argument yang tidak dipengaruhi oleh posisi parameter.

Warning

Jika kita sudah memberikan argumen dalam bentuk keyword argument, maka argumen-argumen setelahnya juga harus dalam keyword argument. Jika setelah keyword argument kita memberikan argumen sebagai positional argument, maka akan memunculkan eror SyntaxError.

is_bounded(3, lower=2, upper=4)
True
is_bounded(3, upper=3, 4)
  File "/var/folders/gn/lh5142px2tb1x8mbqzsf3ckh0000gn/T/ipykernel_46164/2158825987.py", line 1
    is_bounded(3, upper=3, 4)
                           ^
SyntaxError: positional argument follows keyword argument

Kita bisa menyediakan nilai default parameter saat pendefinisian fungsi. Nilai default ini akan dipakai jika fungsi dipanggil tanpa menyediakan argumen untuk parameter tersebut atau memang ingin menggunakan nilai default. Coba kita lihat fungsi is_bounded sebelumnya. Andaikan fungsi tersebut dipanggil untuk menentukan apakah x berada pada interval \([0, 10]\) dan sangat jarang untuk interval yang lain. Jika demikian, kita bisa menyediakan parameter lower dan upper dengan nilai default seperti di bawah ini.

def is_bounded(x, lower=0, upper=10):
    return lower <= x <= upper

Sekarang, kita bisa memanggil is_bounded hanya dengan menyediakan nilai x saja karena parameter yang lain sudah memiliki argumen default.

is_bounded(2)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/var/folders/gn/lh5142px2tb1x8mbqzsf3ckh0000gn/T/ipykernel_46164/350797906.py in <module>
----> 1 is_bounded(2)

TypeError: is_bounded() missing 2 required positional arguments: 'lower' and 'upper'

Tentu saja, jika kita ingin menggunakan interval yang berbeda, kita bisa memberikan argumen sendiri yang akan mengganti argumen default fungsi.

is_bounded(2, lower=5)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/var/folders/gn/lh5142px2tb1x8mbqzsf3ckh0000gn/T/ipykernel_46164/4126019150.py in <module>
----> 1 is_bounded(2, lower=5)

TypeError: is_bounded() missing 1 required positional argument: 'upper'

Warning

Pendefinisian fungsi dengan argumen default pada parameter tidak boleh diikuti oleh positional argument, seperti di bawah ini.

def is_bounded(x, lower=0, upper):
    return lower <= x <= upper

Definisi fungsi di atas akan memunculkan eror SyntaxError, sama dengan saat kita menyediakan keyword argument dan diikuti oleh positional argument sebelumya.

Eksplorasi Mandiri

Python mengutamakan readability yang berarti kode yang ditulis haruslah mudah dibaca dan dipahami, baik bagi pengembang, pengguna, ataupun pembaca. Oleh karena itu, coba baca, eksplor, dan terapkan bagaimana kita membuat dokumentasi fungsi yang sudah kita buat melalui link berikut: PEP-257 Docstring Convention

Cakupan Variabel

Cakupan variabel merujuk pada bagaimana suatu variabel dapat diakses oleh interpreter [Sok21]. Variabel-variabel atau parameter dalam sebuah fungsi hanya bisa diakses dan berlaku di dalam fungsi tersebut. Andaikan kita mendefinisikan variabel dengan nama yang sama diluar fungsi tersebut, maka fungsi tersebut tetap menggunakan variabel yang didefinisikan di dalamnya. Akan tetapi, jika kita mendefinisikan variabel di luar fungsi, lalu mengaksesnya di dalam fungsi, di mana tidak ada variabel dengan nama yang sama, maka fungsi tersebut akan menggunakan variabel dari luar fungsi.

Untuk lebih jelasnya, kita gunakan fungsi func terakhir kita yang mengombinasikan positional argument dan variable-length positional/keyword argument

x = 10
y = 100

func(5, 50)

print("x outside function:", x)
print("y outside function:", y)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
/var/folders/gn/lh5142px2tb1x8mbqzsf3ckh0000gn/T/ipykernel_46164/555556745.py in <module>
      2 y = 100
      3 
----> 4 func(5, 50)
      5 
      6 print("x outside function:", x)

NameError: name 'func' is not defined

Good practice

It is best to define variables in the smallest scope they will be needed in. While functions can refer to variables defined in a larger scope, this is very rarely a good idea since you may not know what variables you have defined if your program has a lot of variables. [Uda21]