Modul 6: Fungsi

  • Decomposition and Abstraction

  • Function, Parameter, Argument

  • Variable Scope

  • Python Built-in Functions

Decomposition dan Abstraction

Apa yang sudah kita pelajari sejauh ini, yaitu dari output sampai looping, membuat kita mampu membuat program-program dengan skala kecil, anggaplah program yang hanya membutuhkan 10 baris atau 20 baris kode. Sekarang bayangkan jika kita ingin membangun sebuah website e-commerce, sebuah game, atau membangun sebuah operating system sendiri, maka tentu dibutuhkan banyak sekali baris kode, mungkin ribuan, puluhan ribu, atau ratusan ribu baris kode. Sebagai gambaran, Windows Operating sistem memiliki sekitar 50 juta baris kode.

Sebagai ilustrasi, anggaplah kita ingin membangun aplikasi untuk pencatatan transaksi di kasir sebuah toko atau minimarket, aplikasi ini biasa disebut dengan Point of Sales (POS). Aplikasi ini akan menangani pencatatan inventory yang terdiri dari penambahan dan pengurangan stok, termasuk mencatat detil tiap produk misalnya kode, nama, kategori, harga. Lalu aplikasi juga melakukan pencatatan transaksi jual beli yang terdiri dari perhitungan total bayar, perhitungan diskon jika ada, dan pengurangan stok barang. Kemudian biasanya diperlukan laporan mingguan, bulanan, atau tahunan untuk melihat laba rugi, barang yang paling laris, barang yang sering dibeli bersamaan, dan sebagainya. Belum lagi manajemen pengguna, yang minimal terdiri dari kasir dan manager/pemilik toko, di mana tiap jenis pengguna punya akses atau fitur yang berbeda. Sebagai tambahan, aplikasi juga mungkin bisa digunakan untuk membayar pembelian dari website e-commerce, tiket kereta, voucher game, dan lain-lain. Kita bisa terus menambah fitur dari aplikasi tersebut, tetapi kita cukupkan dulu ilustrasinya.

Pertanyaannya, bagaimana anda memulai meng-coding program besar di atas?

Decomposition

Secara natural, jika kita melihat sesuatu yang kompleks maka kita akan bertanya, bagaimana menyederhanakannya, atau membagi-bagi permasalahan tersebut ke dalam bagian-bagian kecil yang lebih sederhana? Konsep tersebut biasa disebut dengan decomposition.

Dalam pemrograman, decomposition adalah memecah-mecah kode program menjadi beberapa sub-program yang lebih kecil, salah satunya melalui penggunaan function. Kode program yang besar dipisah dan dikelompokkan berdasarkan fungsi spesifik yang dikerjakan bagian kode tersebut. Misalnya dengan contoh di atas, kita mungkin akan membuat beberapa function, misalnya:

  • function login

  • function input_stock

  • function hitung_diskon

  • function total_bayar

  • function beli

  • function urut_produk dan lain sebagainya..

Tak jarang di dalam satu bagian kecil terdapat beberapa sub-bagian yang lebih kecil lagi, atau function di dalam function. Hal ini semuanya bertujuan agar kode lebih mudah dikelola. Setelah membagi-bagi program berdasarkan fungsi-fungsi tersebut, maka selanjutnya programmer bisa mulai membuat dan mengetes satu per satu fungsi tersebut, lalu baru kemudian digabungkan menjadi satu program yang utuh.

Abstraction

Sebagai ilustrasi, anggaplah kita ingin membangun sebuah PC/komputer, maka kita tau bahwa kita memerlukan beberapa perangkat dengan fungsi-fungsi khusus seperti processor, motherboard, power supply, monitor, RAM, Harddisk, monitor, keyboard, dan mouse. Meskipun kita tidak tau persis detail hardware dan software yang ada dalam tiap perangkat tersebut, tetapi kita bisa berhasil menyatukan perangkat-perangkat tersebut hanya dengan mengetahui hal-hal sederhana yang membuat perangkat tersebut dapat bekerja dengan baik seperti tipe processor yang cocok dengan motherboard atau port monitor yang sesuai.

Mirip dengan hal di atas, dalam pemrograman sudah menjadi hal yang biasa bahwa kita biasanya menggunakan kode atau fungsi yang dibuat oleh orang lain untuk membangun suatu program yang lebih besar secara lebih cepat dan lebih mudah. Begitu juga fungsi yang anda buat, bukan tidak mungkin bisa digunakan oleh orang lain, misalnya karena anda bekerja di dalam tim dimana setiap orang bertugas terhadap fitur yang berbeda, namun saling berkaitan, sehingga beberapa fungsi anda akan digunakan oleh orang lain begitu juga sebaliknya.

Untuk bisa menggunakan fungsi orang lain, yang anda perlu tau adalah:

  • bagaimana cara menggunakan fungsi tersebut,

  • bagaimana efek dari penggunaan fungsi tersebut.

Sedangkan bagaimana detil susunan kode (implementasi) di dalam fungsi tersebut tidak perlu anda ketahui.

Sebagai contoh, saat kita menggunakan fungsi print(), kita tidak tau detail implementasi dari fungsi tersebut, bagaimana susunan kodenya, tetapi kita bisa menggunakannya dengan tepat hanya dengan mengetahui apa input yang dibutuhkan dan bagaimana hasil atau efek fungsi print tersebut.

Mekanisme atau cara-cara untuk menyembunyikan detail yang kompleks dan hanya menunjukkan informasi sederhana yang perlu diketahui pengguna disebut dengan abstraction.

Di dalam pemrograman, abstraction didapatkan salah satunya melalui function, dimana saat menggunakan function yang telah dibuat, programmer hanya perlu memberikan input saja, tanpa perlu mengetahui bagaimana proses di dalam function tersebut.

Melanjutkan contoh POS di atas, seandainya anda bekerja di dalam tim dimana tiap fungsi dikerjakan oleh programmer yang berbeda, maka perlu didefinisikan hal-hal yang menjadi input dan output fungsi agar dapat digunakan dengan tepat oleh orang lain, misalnya:

  • function login membutuhkan input berupa username dan password, dan outputnya adalah True jika berhasil dan False jika username dan password tidak tepat.

Functions

Function adalah satu group statement yang melakukan tugas spesifik tertentu. Function bertujuan men-decompose program menjadi bagian-bagian yang lebih kecil. Function membuat kode program yang besar menjadi lebih terorganisir sehingga lebih mudah dikelola. Selain itu, function dapat menghindari repetisi penulisan kode yang sama berulang kali.

Secara umum terdapat dua jenis function:

  • User-defined function: yaitu function yang dibuat oleh programmer untuk mendukung program yang sedang dikerjakannya.

  • Built-in function: yaitu function yang sudah tersedia dan siap digunakan setelah kita menginstall python.

Pendefinisian Function

Kapanpun kita merasa bahwa ada bagian kode tertentu akan digunakan kembali, maka itu adalah tanda bahwa mungkin kita perlu membuatnya ke dalam function. Atau ketika kita kesulitan untuk mengingat apa yang bagian kode tertentu lakukan, atau mencari bagian kode yang melakukan suatu tugas tertentu, maka itu juga sinyal bahwa kita perlu membuat fungsi.

Berikut ini adalah cara untuk mendefinisikan sebuah fungsi di python.

def <nama_function>(<parameter1>, <parameter2>, ...):
    """docstring"""
    <body function>
    return <expression>
  • keyword def adalah penanda mulainya header sebuah fungsi.

  • <nama_function> mengikuti aturan seperti penamaan variable, sebaiknya dipilih nama yang intuitif sesuai isi fungsi tersebut

  • <parameter1>, <parameter2>, dst disebut dengan parameter fungsi, dan sifatnya adalah opsional. Parameter adalah variable yang digunakan untuk memberikan nilai yang dibutuhkan oleh fungsi.

  • (), walaupun parameter adalah opsional, namun buka dan tutup kurung bersifat wajib

  • """docstring""" bersifat opsional, merupakan documentation string yang menjelaskan tentang fungsi tersebut, apa yang dilakukan oleh fungsi, parameter yang dibutuhkan dan nilai yang dikembalikan oleh fungsi.

  • <body function> seperti halnya body while, if, dan body program secara umum

  • return <expression> bersifat opsional. Jika ada, maka begitu baris return dieksekusi, maka fungsi akan selesai (walaupun masih ada statement di bawahnya) dan nilai setelah return akan menjadi nilai hasil fungsi tersebut. Jika tidak ada return, nilai default fungsi adalah None.

Perhatikan beberapa contoh fungsi sederhana berikut ini:

# fungsi menampilkan menu makanan
def tampil_menu():
    print('Menu 1: Udang Bakar')
    print('Menu 2: Ayam Goreng')
    print('Menu 3: Cumi Rebus')
  • tampil_menu adalah nama fungsi

  • tidak ada parameter fungsi, namun () tetap harus ditulis

  • body fungsi terdiri dari 3 buah statement print

# fungsi untuk menghitung luas lingkaran
def hitung_luas_lingkaran(r):
    luas =  3.14 * r**2
    return luas
  • hitung_luas_lingkaran adalah nama fungsi

  • r adalah sebuah parameter, yang dalam hal ini adalah radius lingkaran, dibutuhkan fungsi agar bisa menghitung luas lingkaran

  • return luas, maka nilai fungsi adalah nilai yang tersimpan dalam variable luas

# fungsi untuk memprint dengan tambahan dekorasi tertentu
def my_print(jlh, kata):
    """
    Fungsi untuk memprint kata dengan jumlah tertentu.

    Parameters:
    jlh (integer) : kata akan di print sebanyak jlh kali
    kata (string) : kata yang akan diprintkan
    """
    print("Kita akan print sebanyak", jlh, "kali")
    print("-"*30)
    for i in range(jlh):
        print("Cinta", kata)
    print("-"*30)
  • terdapat 2 buah parameter

  • terdapat docstring yang menjelaskan parameter fungsi

  • tidak terdapat return, karena my_print tidak menghitung suatu nilai, melainkan melakukan print berdasarkan format tertentu

Pemanggilan function

Pada dasarnya pemanggilan function cukup dengan menuliskan:

nama_function(argument)

dimana argument adalah nilai yang diberikan ke parameter fungsi.

Dalam bahasa pemrograman lain atau referensi lain, ada juga yang menyebutkan parameter sebagai formal parameter, dan argument sebagai actual parameter.

Namun jika fungsi memiliki return, maka biasanya nilai fungsi akan digunakan lebih lanjut, sehingga pemanggilan fungsi dikombinasikan misalnya dengan print, assignment ke variable lain, atau dalam expression.

x = nama_function(argument) # nilai function di-assign ke variable
print(nama_function(argument)) # nilai function di-print
z = 100 + nama_function(argument) # nilai function digunakan dalam expression 

Pemanggilan fungsi tanpa return value

Perhatikan contoh pemanggilan fungsi sederhana berikut ini:

tampil_menu()
Menu 1: Udang Bakar
Menu 2: Ayam Goreng
Menu 3: Cumi Rebus

Terlihat bahwa daftar menu terprint di console. Hal ini tentunya akan memudahkan jika di dalam program kita harus menampilkan menu beberapa kali di bagian kode yang berbeda-beda.

Pemanggilan fungsi dengan return value

Mari kita lihat pemanggilan fungsi yang memiliki return value berikut ini:

luas = hitung_luas_lingkaran(10)
print(luas)
314.0
print(hitung_luas_lingkaran(10) + hitung_luas_lingkaran(20))
1570.0

Nilai default fungsi

Fungsi tampil_menu() tidak memiliki return value, kira-kira jika fungsinya di print, apa yang akan tertampil?

x = tampil_menu()
print("Nilai fungsi :", x)
Menu 1: Udang Bakar
Menu 2: Ayam Goreng
Menu 3: Cumi Rebus
Nilai fungsi : None

Hal ini membuktikan bahwa jika fungsi tidak memiliki return value, maka nilai defaultnya adalah None.

Kesesuaian jumlah dan urutan antara argumen dengan parameter

Jika fungsi memiliki parameter, maka saat pemanggilannya fungsi harus diberikan argumen sesuai dengan jumlah parameter tersebut. Jika kurang atau lebih, maka akan terjadi error. Perhatikan contoh berikut ini:

my_print(10, "halo")
Kita akan print sebanyak 10 kali
------------------------------
Cinta halo
Cinta halo
Cinta halo
Cinta halo
Cinta halo
Cinta halo
Cinta halo
Cinta halo
Cinta halo
Cinta halo
------------------------------

Sekarang perhatikan apa yang terjadi jika jumlah argumen yang diberikan tidak sesuai, atau urutan argumen berbeda:

my_print("satu", 10)
Kita akan print sebanyak satu kali
------------------------------
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-90-52b8b79eceeb> in <module>()
----> 1 my_print("satu", 10)

<ipython-input-84-aa2285fd6e41> in my_print(jlh, kata)
     10     print("Kita akan print sebanyak", jlh, "kali")
     11     print("-"*30)
---> 12     for i in range(jlh):
     13         print("Cinta", kata)
     14     print("-"*30)

TypeError: 'str' object cannot be interpreted as an integer

Urutan argumen harus sesuai dengan urutan parameter, jika urutan tidak sesuai bisa menyebabkan error karena perbedaan tipe data, atau jika tipe data sama dapat menyebabkan logic error.

my_print(10)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-91-1e0f5a2bddd6> in <module>()
----> 1 my_print(10)

TypeError: my_print() missing 1 required positional argument: 'kata'

Di contoh argumen kurang di atas, error yang muncul adalah: TypeError: my_print() missing 1 required positional argument: 'kata', artinya python memberitahu kita bahwa ada 1 argument wajib yang kurang. Perhatikan bahwa terdapat kata required/wajib, karena memang python juga menyediakan argumen yang sifatnya opsional. Pembahasan detail tentang argumen dapat dilihat di bagian khusus tentang jenis-jenis parameter.

Lokasi pemanggilan fungsi

Fungsi dapat dipanggil di dalam program, di dalam fungsi lain, atau pun di dalam python console.

Perhatikan contoh berikut ini dimana fungsi dipanggil dari dalam fungsi lainnya:

def hitung_volume_tabung(r, t):
    return hitung_luas_lingkaran(r) * t
print(hitung_volume_tabung(10, 10))
3140.0

Docstring

Dokumentasi tentang parameter dan return value dari fungsi sangat penting sebagai bagian dari konsep abstraction, yaitu pengguna fungsi tidak perlu tau bagaimana implementasi/kode fungsi secara detail, namun cukup mengetahui apa maksud fungsi tersebut, dan bagaimana cara menggunakannya. Hal ini akan sangat bermanfaat ketika kita bekerja di dalam tim, di mana tiap orang mengerjakan fungsi yang berbeda-beda namun saling menggunakan fungsi yang dikerjakan orang lain. Bahkan, bisa juga fungsi yang kita buat di-share ke public dan bisa digunakan oleh siapa saja.

Di python, cara untuk membuat dokumentasi fungsi adalah melalui document string atau docstring. Sementara di bahasa lain juga tersedia dengan sebutan yang berbeda, misalnya di java disebut document comments.

Untuk memahami docstring, mari kita perhatikan lagi fungsi my_print berikut ini:

# fungsi untuk memprint dengan tambahan dekorasi tertentu
def my_print(jlh, kata):
    """
    Fungsi untuk memprint kata dengan jumlah tertentu.

    Parameters:
    jlh (integer) : kata akan di print sebanyak jlh kali
    kata (string) : kata yang akan diprintkan
    """
    print("Kita akan print sebanyak", jlh, "kali")
    print("-"*30)
    """
    ini bukan docstring
    namun tetap tidak dianggap sebagai kode yang harus dieksekusi
    """
    for i in range(jlh):
        print("Cinta", kata)
    print("-"*30)
  • # fungsi untuk memprint ... adalah komentar, namun bukan docstring

  • docstring dimulai dan ditutup dengan tanda """ (triple double quote) dan harus berada tepat di bawah header fungsi.

  • tidak seperti komentar, docstring menjadi sebuah properti/bagian yang melekat pada fungsi tersebut, dan bisa diakses melalui nama_fungsi.__doc__ atau help(nama_fungsi).

Perhatikan penggunaan docstring di bawah ini:

print(my_print.__doc__)
    Fungsi untuk memprint kata dengan jumlah tertentu.

    Parameters:
    jlh (integer) : kata akan di print sebanyak jlh kali
    kata (string) : kata yang akan diprintkan
    
help(my_print)
Help on function my_print in module __main__:

my_print(jlh, kata)
    Fungsi untuk memprint kata dengan jumlah tertentu.
    
    Parameters:
    jlh (integer) : kata akan di print sebanyak jlh kali
    kata (string) : kata yang akan diprintkan

Terlihat bahwa docstring bisa sangat membantu bagi orang yang ingin menggunakan fungsi, tanpa harus membuka source code fungsi tersebut. Untuk itu, ada baiknya kita membiasakan diri untuk menuliskan docstring untuk fungsi-fungsi yang kita buat.

Variable Scope

Scope pada pemrograman (tidak hanya Python) adalah tentang lokasi di mana saja suatu entitas (e.g., variable) bisa diakses. Istilah local variable dan global variable adalah contoh yang terkait dengan scope variable. Pemahaman tentang scope sangat penting untuk memastikan tidak ada conflict antar variable dan menghindari terjadinya bug pada program.

Global Variable

Variable global adalah variable yang dideklarasikan di luar fungsi atau di program utama. Variable yang memiliki scope global bisa diakses di luar dan di dalam fungsi.

Perhatikan contoh berikut ini:

x = 10

def cetak():
    print("dalam fungsi:", x)

cetak()
dalam fungsi: 10

Variable x memiliki scope global karena didefinisikan di dalam program utama, sehingga x bisa diakses dari dalam fungsi cetak.

Assignment variable global

Namun jika variable global di-assign dengan suatu nilai di dalam fungsi, maka variable tersebut akan berubah menjadi variable local.

x = 10

def tambah():
    y = x + 1 # meskipun x di assignment setelah baris ini, tetap x saat ini dianggap variable lokal
    x = y

tambah()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-98-a48a0dd9d6f0> in <module>()
      5     x = y
      6 
----> 7 tambah()

<ipython-input-98-a48a0dd9d6f0> in tambah()
      2 
      3 def tambah():
----> 4     y = x + 1 # meskipun x di assignment setelah baris ini, tetap x saat ini dianggap variable lokal
      5     x = y
      6 

UnboundLocalError: local variable 'x' referenced before assignment

kode di atas jika dieksekusi akan menghasilkan error UnboundLocalError: local variable 'x' referenced before assignment, artinya variable x dianggap variable local, sehingga x belum memiliki nilai ketika digunakan pada x + 1.

Keyword global

Jika kita memang ingin mengubah variable global dari dalam fungsi, maka perlu menambahkan keyword global seperti contoh di bawah ini:

x = 10

def tambah():
    global x # maka x yang dimaksud dalam fungsi ini adalah x global, meskipun ada x di-assign nilai baru
    y = x + 1
    x = y

tambah()
print("setelah fungsi:", x)
setelah fungsi: 11

Local Variable

Variable yang dideklerasikan di dalam fungsi akan memiliki scope local, sehingga tidak bisa diakses dari luar fungsi tersebut.

def foo():
    z = 10 # variable lokal, tidak bisa diakses dari luar fungsi foo()

foo()
print("setelah fungsi:", z) # z tidak bisa diakses dari luar fungsi
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-1-1e039e1178d6> in <module>()
      3 
      4 foo()
----> 5 print("setelah fungsi:", z) # z tidak bisa diakses dari luar fungsi

NameError: name 'z' is not defined

Namun, variable local fungsi bisa diakses fungsi lain yang didefinisikan di dalam fungsi tersebut. Perhatikan contoh di bawah ini:

def foo():
    local_foo = 10
    def bar():
        print("variable local_foo dari dalam bar:", local_foo)
    
    bar()

foo()
variable local_foo dari dalam bar: 10

Pass by Value vs Pass by Reference

Konsep berikutnya yang perlu dipahami tentang fungsi adalah bagaimana nilai dari argument diberikan ke parameter saat fungsi dipanggil. 2 konsep yang populer adalah pass by value dan pass by reference.

Jika kita menyimpan sebuah data di memori, misalnya melalui assign sebuah variable a = 10, maka ada 2 hal yang perlu kita ketahui:

  • Value: adalah data atau nilai yang disimpan di memory

  • Reference: adalah alamat memori yang menyimpan data tersebut

Sedangkan variable a seperti nama alias untuk memudahkan kita dalam memprogram sehingga tidak perlu mengingat alamat memori. 2 variable selain bisa menyimpan value yang sama, juga bisa menyimpan alamat yang sama. Hal ini diatur oleh bahasa pemrograman masing-masing.

Setelah mengetahui tentang value dan reference, sekarang kita lihat apa perbedaan pass by value dan pass by reference:

  • Pass by Value: data di-copy dari yang memanggil ke fungsi yang dipanggil. Sehingga meskipun datanya sama, namun di memori letaknya berbeda. Akibatnya, ketika data diubah di dalam fungsi, data di yang memanggil tetap tidak berubah.

  • Pass by Reference: yang diberikan oleh pemanggil ke fungsi yang dipanggil adalah alamat memori data, sehingga alamat memori yang ditunjuk oleh fungsi dan yang memanggil adalah sama. Akibatnya, jika data dirubah di dalam fungsi, maka data tersebut juga berubah di yang memanggil fungsi.

Setiap bahasa pemrograman punya aturan sendiri dan mungkin berbeda tentang bagaimana data diberikan ke fungsi, di bahasa tertentu, misalnya C++, secara default yang digunakan adalah pass by value, namun bisa diatur agar suatu parameter menggunakan pass by reference.

Bagaimana dengan python?

Sedikit berbeda, Python tidak memiliki pengaturan agar suatu parameter pass by value atau pass by reference. Python hanya menganut aturan pass by object reference atau ada juga yang menyebutnya pass by assignment. Untuk memahaminya, mari kita lihat lebih dalam cara kerja assignment pada Python melalui contoh berikut ini:

a = 10
print('id a:',id(a))
b = a
print('id b:',id(b))
b = 20
print('id b:',id(b))
b = a
print('id b:',id(b))
id a: 10914784
id b: 10914784
id b: 10915104
id b: 10914784

id() adalah built-in function yang akan mengembalikan identitas unik suatu objek. Terlihat b = a menyebabkan kedua variable menyimpan identitas yang sama. Identitas di python bisa dianggap seperti reference atau alamat suatu objek di memory. Sehingga bisa dipahami bahwa assignment di python adalah pemberian reference suatu objek ke sebuah variable.

Ketika b di-assign kembali dengan nilai yang lain, maka identitasnya berubah.

Sekarang kita lihat contoh menggunakan list berikut ini:

list_a = [10]
print('id list_a:',id(list_a))
list_b = list_a
print('id list_b:',id(list_b))
list_b = [20]
print('id list_b:',id(list_b))
list_b = list_a
print('id list_b:',id(list_b))
id list_a: 139815337496136
id list_b: 139815337496136
id list_b: 139815327721800
id list_b: 139815337496136

Terlihat bahwa hasilnya konsisten seperti contoh sebelumnya, yaitu assignment memberikan reference objek, serta identitas variable list_b akan berubah ketika di-assign kembali dengan data yang lain, karena data baru tersebut memiliki alamat memori yang berbeda.

Namun, terdapat perbedaan pada kedua jenis data tersebut, antara int dan list. Perhatikan contoh berikut ini:

list_a = [10]
list_b = list_a
print('list_b sebelum modifikasi :', list_b)
list_b[0] = 20
print('list_b setelah modifikasi :', list_b)
print('list_a setelah modifikasi list_b :', list_a)
list_b sebelum modifikasi : [10]
list_b setelah modifikasi : [20]
list_a setelah modifikasi list_b : [20]

Terlihat bahwa data pada list_b dapat diubah tanpa harus meng-assign kembali list_b dengan data baru, melainkan perubahan tersebut dilakukan melalui update element list.

Perhatikan:

  • list_b = [20] : ini adalah assignment kembali variable list_b

  • list_b[0] = 20 : variable list_b tidak di-assign kembali, yang di-assign kembali adalah elemen list_b di index 0.

Sedangkan pada variable int, tidak ada cara untuk bisa mengubah data tersebut selain dengan assign kembali, yang artinya mengubah referensi variable sehingga berbeda dari sebelumnya.

Prinsip assignment tersebut digunakan pada pemanggilan fungsi sehingga seolah-olah terjadi proses assignment berikut:

parameter = argument

Berdasarkan penjelasan cara kerja assignment pada list dan int, maka bisa dipahami jika parameter memiliki tipe int, efeknya akan seperti pass by value. Artinya, jika parameter tersebut diubah nilainya di dalam fungsi, maka pasti hanya dapat dilakukan dengan assignment kembali, yang mengakibatkan berbedanya referensi parameter dengan referensi argument yang pada akhirnya perubahan tersebut tidak akan berdampak pada yang memanggil fungsi.

Sedangkan jika parameter bertipe list, maka akan seperti pass by reference selama perubahan data pada list tidak dilakukan dengan assignment kembali.

Berikut contoh penggunaannya pada fungsi:

def func_update_list(list_x):
    list_x[0] = list_x[0] + 1
    print('dalam fungsi :', list_x)

list_1 = [10, 20]
func_update_list(list_1)
print('setelah panggil fungsi :', list_1)
dalam fungsi : [11, 20]
setelah panggil fungsi : [11, 20]
def func_update_list(list_x):
    list_x = [11, 20]
    print('dalam fungsi :', list_x)

list_1 = [10, 20]
func_update_list(list_1)
print('setelah panggil fungsi :', list_1)
dalam fungsi : [11, 20]
setelah panggil fungsi : [10, 20]

Mutable dan Immutable Object

Berdasarkan kemampuan mengubah data, maka suatu object di python dapat digolongkan ke dalam mutable object dan immutable object.

Mutable objek adalah objek yang bisa diubah setelah dibuat, dengan kata lain value yang disimpan di suatu variable bisa diubah tanpa melakukan reassignment variable.

Berdasarkan tipe data yang sudah kita pelajari sejauh ini, berikut pembagiannya:

  • immutable object: int, float, str, bool

  • mutable object: list

Untuk penjelasan lengkap dapat melihat python docs: https://docs.python.org/3/reference/datamodel.html

Python Built-in Functions

Python Module

Kita telah melihat bahwa function pada programming membantu kita untuk mengorganisasi kode kita agar lebih efisien dan mudah digunakan, atau yang biasa disebut dengan modularisasi program. Berikutnya ada lagi cara lain untuk memodularisasi program yang levelnya lebih tinggi dari function, yaitu module.

Module di Python sederhananya adalah sebuah file .py yang berisi variable, fungsi, dan lainnya untuk tugas tertentu. Misalnya jika kita punya program kasir, semua fungsi yang terkait dengan perhitungan diskon kita buat ke dalam satu file misalnya diskon.py, maka kita telah memiliki sebuah module bernama diskon. Hal ini akan memudahkan seandainya suatu waktu kita ingin mengubah formula diskon atau sekedar persentasenya saja, maka kita cukup menuju file spesifik tersebut dan mengubahnya. Perubahan pada module akan berefek ke semua program yang menggunakan module diskon tersebut.

Perhatikan contoh berikut ini:

Import module (import)

Dari contoh di atas kita punya file diskon.py dan main.py. Pada main.py kita meload module diskon dengan keyword import. Saat kita load sebuah module, maka isi file tersebut akan dieksekusi. Misalnya kita lihat tulisan ‘Loading module diskon’ (yang merupakan perintah dari module diskon) tertampil di layar.

Selanjutnya kita bisa menggunakan semua nama variable dan nama fungsi pada module yang diimport dengan format <nama_module>.<nama variable/fungsi>, misalnya diskon.hitung_diskon_member.

Import objek tertentu (from)

Selain mengimport module secara satu kesatuan, kita bisa juga mengimport objek (variable/function) tertentu yang ada di dalam sebuah module. Keyword yang digunakan adalah from <nama_module> import <spesifik_objek>. Dengan begini maka variable atau fungsi yang diimport tersebut seolah-olah menjadi bagian dari file yang mengimportnya (untuk lebih detail, baca tentang namespace). Hal ini terlihat ketika kita ingin menggunakan variable atau fungsi tersebut, kita tidak perlu lagi menuliskan nama module di depannya.

Perhatikan contoh berikut:

Kelebihan dari cara import ini adalah penggunaannya yang lebih singkat karena tidak perlu menuliskan nama module setiap kali kita menggunakan fungsi atau variable yang diimport. Namun kekurangannya adalah jika ada nama objek (variable/fungsi) yang sama, maka objek yang baru diimport akan menimpa objek yang lama. Kemudian jika ada banyak objek yang ingin diimport, maka kita perlu menuliskan satu per satu objek tersebut saat mengimport (lihat baris 1 pada file main.py di bawah ini).

Import semua objek (import *)

Untuk mempermudah mengimport objek spesifik tanpa menuliskan satu per satu, kita bisa menggunakan import * yang artinya mengimport semua objek yang ada di suatu module. Cara ini efektif, namun kita harus berhati-hati, karena jika kita tidak hapal semua objek yang ada di module tersebut, bisa jadi ada nama objek yang sama sehingga ada yang akan tertimpa. Akibatnya kita bisa salah menggunakan fungsi atau variable.

Berikut contoh penggunaan import *.

Alias nama module (as)

Kita bisa mengganti nama module yang diimport agar lebih singkat misalnya, atau alasan lainnya.

Perhatikan contoh berikut ini dimana kita mengubah nama module diskon menjadi disk saja.

Reload module

Perlu diketahui bahwa sebuah module hanya bisa diimport satu kali. Jika sebuah module sudah diimport, dan di bagian lain kode anda ada perintah import module yang sama, maka module tersebut tidak akan diimport kembali. Perhatikan contoh berikut ini, meskipun import diskon dipanggil dua kali, namun tulisan Loading module diskon hanya tertampil satu kali.

Python Package

Jika module pada Python adalah sebuah file, maka package mirip seperti directory. Merupakan hal yang wajar ketika kita mengumpulkan file yang mirip ke dalam satu folder, dan file yang berbeda di folder yang berbeda pula. Konsep yang sama juga diterapkan pada pembuatan software. Misalnya jika kita ingin membangun software kasir mungkin kita bisa memiliki struktur directory seperti berikut ini:

  • Kasir (Package)

Load package

Untuk load module dari sebuah package mirip seperti me-load objek dari module yaitu dengan import dan from ... import .... Perhatikan contoh berikut, misalnya kita punya sebuah package lain, dan ingin mengimport sebuah fungsi enroll_user bagian dari module registrasi.

import Kasir.Member.registrasi

Kasir.Member.registrasi.enroll_user(user)

#atau
from Kasir.Member import  registrasi

registrasi.enroll_user(user)

#atau
from Kasir.Member.registrasi import enroll_user

enroll_user(user)

Pendalaman: Jenis-jenis parameter fungsi

Positional, Named, Required

Selamat anda telah menyelesaikan Modul 6!!

Mohon berkenan memberikan Rating dan Feedback agar kami dapat meningkatkan kualitas modul ini!