itulis terlebih dahulu,
kemudian diikuti *args, lalu **kwargs.
Contoh penerapannya:
Python secara cerdas mengidentifikasi argument mana yang akan disimpan
pada positional parameter, *args, dan **kwargs. Pada kode di atas, mapping
antara arguments dengan parameter yaitu seperti ini:
• Argument hello world ditampung parameter message .
• Argument 1 , True ,dan ("yesn't", "nope") ditampung parameter
params .
• Keyword argument name="nokia 3310" , discontinued=True , dan
year_released=2000 ditampung parameter others .
â—‰ Kombinasi positional argument, args, keyword
def print_all(message, *params, **others):
print(f"message: {message}")
print(f"params: {params}")
print(f"others: {others}")
print_all("hello world", 1, True, ("yesn't", "nope"), name="nokia 3310",
discontinued=True, year_released=2000)
# output ↓
#
# message: hello world
# params: (1, True, ("yesn't", 'nope'))
# others: {'name': 'nokia 3310', 'discontinued': True, 'year_released':
2000}
argument, dan kwargs
Keyword argument bisa dituliskan diantara *args, dan **kwargs, diluar itu
menghasilkan error.
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../args-
kwargs
â—‰ Chapter relevan lainnya
• Function
def print_all(message, *params, say_something, **others):
print(f"message: {message}")
print(f"params: {params}")
print(f"say_something: {say_something}")
print(f"others: {others}")
print_all("hello world", 1, True, ("yesn't", "nope"), say_something="how
are you", name="nokia 3310", discontinued=True, year_released=2000)
# output ↓
#
# message: hello world
# params: (1, True, ("yesn't", 'nope'))
# say_something: how are you
# others: {'name': 'nokia 3310', 'discontinued': True, 'year_released':
2000}
• Function ➜ Positional, Optional, Keyword Arguments
• Function ➜ Closure
• Function ➜ Lambda
â—‰ Referensi
• https://docs.python.org/3/tutorial/controlflow.html#arbitrary-argument-lists
A.25. Python Closure
Closure yaitu istilah umum dalam programming untuk deklarasi fungsi yang
berada di dalam fungsi (nested function). Pada chapter ini kita akan
mempelajari cara implementasinya.
A.25.1. Pengenalan Closure
Di Python, fungsi bisa dideklarasikan di-dalam suatu fungsi. Penerapannya
cukup berguna pada kasus dimana ada blok kode yang perlu di-eksekusi lebih
dari satu kali tetapi eksekusinya hanya di dalam fungsi tertentu, atau
eksekusinya setelah pemanggilan fungsi tertentu.
Permisalan ada fungsi inner() yang dideklarasikan di dalam fungsi
outer() , maka:
• Fungsi inner() bisa diakses dari dalam fungsi outer()
• Fungsi inner() juga bisa diakses dari luar fungsi outer() asalkan fungsi
inner() tersebut dijadikan sebagai nilai balik fungsi outer() (untuk
kemudian ditampung ke dalam variabel lalu dieksekusi)
Program berikut berisi contoh praktis tentang fungsi inner() dan outer() .
Silakan pelajari dan praktekan.
def outer_func(numbers = []):
print(f"numbers: {numbers}")
def inner_func():
print(f"max: {max(numbers)}")
print(f"min: {min(numbers)}")
Output program:
Program di atas jika di-breakdown sesuai urutan eksekusi statement-nya
kurang lebih seperti ini:
• Tahap 1: eksekusi statement print("call outer_func()")
• Tahap 2: eksekusi statement print(f"numbers: {numbers}")
• Tahap 3: eksekusi statement print("call inner_func() within
outer_func()")
• Tahap 4: eksekusi statement inner_func()
â—¦ Tahap 4.A. eksekusi statement print(f"max: {max(numbers)}")
â—¦ Tahap 4.B. eksekusi statement print(f"min: {min(numbers)}")
• Tahap 5: eksekusi statement print("call inner_func() outside of
outer_func()")
• Tahap 6: eksekusi statement inner_func() via f() dari luar fungsi
outer_func()
â—¦ Tahap 6.A. eksekusi statement print(f"max: {max(numbers)}")
â—¦ Tahap 6.B. eksekusi statement print(f"min: {min(numbers)}")
Jika di-flatten semua statement-nya maka programnya menjadi seperti ini:
â—‰ Fungsi min() & max()
Kedua fungsi ini digunakan untuk menghitung agregasi data numerik.
• Fungsi min() untuk pencarian nilai minimum dari data list yang berisi
elemen data numerik.
Contoh min([3, 4, 1, 2, 3, 4]) menghasilkan data 1 .
• Fungsi max() untuk pencarian nilai maksimum dari data list yang berisi
elemen data numerik.
Contoh max([3, 4, 1, 2, 3, 4]) menghasilkan data 4 .
A.25.2. Menampung fungsi dalam
variabel
Pada contoh sebelumnya, fungsi inner_func() ditampung ke variabel
bernama f via nilai balik pemanggilan fungsi outer_func() . Dari sini terlihat
bahwa closure bisa disimpan ke variabel.
Tidak hanya closure, fungsi biasa-pun juga bisa disimpan dalam variabel,
print("call outer_func()")
numbers = [1, 2, 3, 4]
print(f"numbers: {numbers}")
print("call inner_func() within outer_func()")
print(f"max: {max(numbers)}")
print(f"min: {min(numbers)}")
print("call inner_func() outside of outer_func()")
print(f"max: {max(numbers)}")
print(f"min: {min(numbers)}")
contohnya ada pada fungsi print_all() berikut yang disimpan pada variabel
display untuk kemudian di-eksekusi.
A.25.3. Fungsi sebagai argument
parameter
Selain disimpan dalam variabel, fungsi/closure bisa juga dijadikan sebagai nilai
argument suatu parameter fungsi. Metode seperti ini cukup sering digunakan
terutama pada operasi data sequence atau agregasi data numerik.
Contoh penerapan fungsi/closure sebagai argument pemanggilan fungsi bisa
dilihat pada kode berikut ini. Silakan coba dan pelajari, penjelasannya ada
dibawah kode.
def print_all(message, *numbers, **others):
print(f"message: {message}")
print(f"numbers: {numbers}")
print(f"others: {others}")
display = print_all
display("hello world", 1, 2, 3, 4, name="nokia 3310", discontinued=True,
year_released=2000)
# output ↓
#
# message: hello world
# numbers: (1, 2, 3, 4)
# others: {'name': 'nokia 3310', 'discontinued': True, 'year_released':
2000}
def aggregate(message, numbers, f):
res = f(numbers)
print(f"{message} is {res}")
Fungsi aggregate() dideklarasikan memiliki 3 buah parameter yaitu
message , numbers , dan f dimana f yaitu akan diisi dengan fungsi/
closure. Di dalam fungsi aggregate() , fungsi f dipanggil dengan disisipkan
argument yaitu numbers dalam pemanggilannya.
Ada juga fungsi sum() dideklarasikan dengan tugas untuk menghitung total
dari data list numerik numbers . Dan fungsi avg() untuk nilai rata-rata dari
data numbers .
Kemudian di bawahnya ada 4 buah statement pemanggilan fungsi
aggregate() :
• Pemanggilan ke-1 yaitu perhitungan nilai total numbers . Fungsi sum
yang telah dideklarasikan sebelumnya dijadikan sebagai argument
pemanggilan fungsi aggregate() untuk ditampung di parameter f .
• Pemanggilan ke-2 yaitu perhitungan nilai rata-rata dimana fungsi avg
yang telah dideklarasikan dijadikan sebagai argument pemanggilan fungsi
aggregate() ..
• Pemanggilan ke-3 yaitu perhitungan nilai maksimum. Fungsi max yang
merupakan fungsi bawaan Python digunakan sebagai argument
pemanggilan fungsi aggregate() .
• Pemanggilan ke-1 yaitu perhitungan nilai minimum. Fungsi min yang
merupakan fungsi bawaan Python digunakan sebagai argument
pemanggilan fungsi aggregate() .
Dari contoh terlihat bagaimana contoh penerapan closure sebagai nilai
argument parameter fungsi. Fungsi atau closure bisa digunakan sebagai nilai
argument, dengan catatan skema parameter-nya harus disesuaikan dengan
kebutuhan.
Di dalam fungsi aggregate() , closure f diharapkan untuk memiliki
parameter yang bisa menampung data list numbers . Selama fungsi/closure
memenuhi kriteria ini maka penggunaannya tidak menghasilkan error.
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../args-
kwargs
â—‰ Chapter relevan lainnya
• Function
• Function ➜ Positional, Optional, Keyword Arguments
• Function ➜ Args & Kwargs
• Function ➜ Lambda
â—‰ Referensi
• https://docs.python.org/3/library/stdtypes.html#functions
A.26. Python Lambda
Pada chapter ini kita akan belajar tentang anonymous function atau fungsi
tanpa nama yang biasa disebut dengan lambda.
A.26.1. Pengenalan Lambda
Lambda yaitu fungsi yang tidak memiliki nama. Lambda umumnya disimpan
ke suatu variabel atau dieksekusi langsung. Lambda bisa memiliki parameter
dan mengembalikan nilai balik, seperti fungsi pada umumnya.
Perbedaan signifikan antara lambda dengan fungsi/closure yaitu pada
lambda isinya hanya boleh 1 baris satement. Jika ada lebih dari 1 baris silakan
gunakan fungsi saja.
Untuk mempermudah pemahaman kita tentang lambda, silakan pelajari kode
berikut. Ada dua blok fungsi dibuat, satu berbentuk fungsi biasa dan satunya
lagi yaitu lambda. Keduanya memiliki tugas sama persis yaitu menampilkan
pesan hello python .
Bisa dilihat bagaimana perbedaan penulisan syntax fungsi menggunakan
def say_hello1():
print("hello python")
say_hello1()
# output ➜ hello python
say_hello2 = lambda : print("hello python")
say_hello2()
# output ➜ hello python
lambda dibandingkan dengan fungsi biasa. Lambda ditulis menggunakan
keyword lambda , diikuti tanda titik 2 : lalu statement satu baris. Lambda
perlu ditampung ke sebuah variabel (misalnya say_hello2() ), setelahnya
variabel tersebut digunakan untuk mengeksekusi lambda dengan cara
memanggilnya seperti fungsi.
A.26.2. lambda return value
Lambda selalu mengembalikan nilai balik atau return value. Jika isi lambda
yaitu suatu data atau operasi yang menghasilkan data, maka data tersebut
otomatis jadi nilai balik. Contoh:
Pada kode di atas lambda get_hello_message2() mengembalikan nilai balik
bertipe string.
Lalu bagaimana dengan lambda say_hello2() yang telah dipraktekan di
atas, apakah juga mengembalikan nilai balik? Iya, lambda tersebut juga ada
return value-nya. Namun, karena isi lambda say_hello2() yaitu
pemanggilan fungsi print() maka nilai balik lambda yaitu data None .
def get_hello_message1():
return "hello python"
res = get_hello_message1()
print(res)
# output ➜ hello python
get_hello_message2 = lambda : "hello python"
res = get_hello_message2()
print(res)
# output ➜ hello python
Pembahasan detail mengenai tipe data None ada di chapter None
A.26.3. Lambda argument/parameter
Sama seperti fungsi, lambda bisa memiliki parameter baik itu jenisnya
parameter positional, optional, ataupun keyword argument.
Sebagai contoh, lihat perbandingan fungsi get_full_name1() dengan lambda
get_full_name2() pada kode berikut. Parameter di lambda dituliskan
diantara keyword lambda dan tanda titik 2 : . Jika ada lebih dari 1
parameter, gunakan tanda koma , sebagai separator.
Untuk penerapan optional argument dan keyword argument, contohnya bisa
dilihat pada kode berikut:
def get_full_name1(first_name, last_name):
return f"{first_name} {last_name}"
get_full_name2 = lambda first_name, last_name : f"{first_name}
{last_name}"
res = get_full_name1("Darion", "Mograine")
print(res)
# output ➜ Darion Mograine
res = get_full_name2("Sally", "Whitemane")
print(res)
# output ➜ Sally Whitemane
get_full_name3 = lambda first_name, last_name = "" : f"{first_name}
{last_name}".strip()
A.26.4. Lambda dengan parameter *args
& **kwargs
Penerapan *args dan **kwargs pada parameter lambda tidak berbeda
dengan penerapannya di fungsi biasa. Sebagai perbandingan Silakan pelajari 2
contoh berikut yang masing-masing berisi contoh penulisan lambda vs versi
fungsi biasa.
• Contoh lambda dengan parameter *args:
• Contoh lambda dengan parameter **kwargs:
# %% A.26.4. Lambda *args dan **kwargs
def debug1(separator, *params):
res = []
for i in range(len(params)):
res.append(f"param {i}: {params[i]}")
return separator.join(res)
debug2 = lambda separator, *params : separator.join([f"param {i}:
{params[i]}" for i in range(len(params))])
res = debug1(", ", "Darion Mograine", ["Highlord", "Horseman of the
Ebon Blade", "Ashbringer"], True)
print(res)
# output ➜ param 0: Darion Mograine, param 1: ['Highlord', 'Horseman
of the Ebon Blade', 'Ashbringer'], param 2: True
res = debug2(", ", "Darion Mograine", ["Highlord", "Horseman of the
Ebon Blade", "Ashbringer"], True)
print(res)
# output ➜ param 0: Darion Mograine, param 1: ['Highlord', 'Horseman
of the Ebon Blade', 'Ashbringer'], param 2: True
A.26.5. Isi lambda: statement 1 baris
Lambda secara penulisan bisa dibilang lebih praktis dibanding fungsi, namun
limitasinya yang hanya bisa berisi statement 1 baris saja terkadang menjadi
masalah, terutama untuk mengakomodir operasi komplex yang umumnya
def debug3(separator, **params):
res = []
for key in params:
res.append(f"{key}: {params[key]}")
return separator.join(res)
debug4 = lambda separator, **params : separator.join([f"{key}:
{params[key]}" for key in params])
res = debug3(
", ",
name="Darion Mograine",
occupations=["Highlord", "Horseman of the Ebon Blade",
"Ashbringer"],
active=True
)
print(res)
# output ➜ name: Darion Mograine, occupations: ['Highlord', 'Horseman
of the Ebon Blade', 'Ashbringer'], active: True
res = debug4(
", ",
name="Darion Mograine",
occupations=["Highlord", "Horseman of the Ebon Blade",
"Ashbringer"],
active=True
)
print(res)
# output ➜ name: Darion Mograine, occupations: ['Highlord', 'Horseman
of the Ebon Blade', 'Ashbringer'], active: True
membutuhkan lebih dari 1 baris kode.
Namun Python dari segi bahasa yaitu cukup flexibel, banyak API yang
memungkinkan kita selaku programmer untuk bisa menuliskan kode yang
cukup kompleks tapi dalam 1 baris saja. Pada contoh berikut, operasi
transpose matrix bisa dilakukan hanya dalam 1 baris dengan menerapkan list
comprehension.
Pembahasan detail mengenai list comprehension ada di chapter List
Comprehension
A.26.6. Lambda dengan parameter
def transpose_matrix1(m):
tm = []
for i in range(len(m[0])):
tr = []
for row in m:
tr.append(row[i])
tm.append(tr)
return tm
transpose_matrix2 = lambda m : [[row[i] for row in matrix] for i in
range(len(m[0]))]
matrix = [[1, 2], [3, 4], [5, 6]]
res = transpose_matrix1(matrix)
print(res)
# output ➜ [[1, 3, 5], [2, 4, 6]]
res = transpose_matrix2(matrix)
print(res)
# output ➜ [[1, 3, 5], [2, 4, 6]]
fungsi/lambda
Lambda, closure, fungsi, ketiganya bisa digunakan sebagai argument suatu
pemanggilan fungsi dengan cara implementasi juga sama, yaitu cukup tulis
saja lambda sebagai argument baik secara langsung maupun lewat variabel
terlebih dahulu.
Contoh penerapannya bisa dilihat pada kode berikut. Lambda aggregate()
dibuat dengan desain parameter ke-3 yaitu f bisa menampung nilai berupa
fungsi/closure/lambda.
Lambda aggregate() dipanggil 3x yang pada pemanggilan ke-2 dan
ke-3-nya, argument parameter ke-3 diisi dengan lambda.
aggregate = lambda message, numbers, f: print(f"{message} is
{f(numbers)}")
numbers = [24, 67, 22, 98, 3, 50]
def average1(numbers):
return sum(numbers) / len(numbers)
aggregate("average", numbers, average1)
# output ➜ average is 44.0
average2 = lambda numbers : sum(numbers) / len(numbers)
aggregate("average", numbers, average2)
# output ➜ average is 44.0
aggregate("average", numbers, lambda numbers : sum(numbers) /
len(numbers))
# output ➜ average is 44.0
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../lambda
â—‰ Chapter relevan lainnya
• Function
• Function ➜ Positional, Optional, Keyword Arguments
• Function ➜ Args & Kwargs
• Function ➜ Closure
â—‰ Referensi
• https://docs.python.org/3/reference/expressions.html#lambda
A.27. Python Modules
Pada chapter ini, kita akan menjelajahi konsep module beserta
implementasinya di Python.
A.27.1. Pengenalan Modules
Module di Python merupakan istilah untuk file yang berisi kode-kode python
(seperti deklarasi variabel, fungsi, class, dan lainnya). Kode-kode tersebut
diisolasi sesuai dengan tugasnya. Contoh:
• Module numbers berisi fungsi-fungsi untuk keperluan operasi angka
• Module random yang isinya kode untuk generate data random
Dengan adanya module kode menjadi lebih modular, rapi, dan mudah dikelola.
Pembuatan module di Python sangat mudah karena dilakukan dengan cukup
membuat file. Nama file yang digunakan yaitu menjadi nama module.
Misalnya, file calculate.py , maka nama module yaitu calculate .
Module dapat di-import di module lain, atau digunakan sebagai entry point
eksekusi program (sebutannya main module). Misalnya di praktek-praktek
pada chapter sebelumnya kita sering menggunakan command python.exe
main.py untuk menjalankan program Python. Command tersebut menjadikan
module main (file main.py ) sebagai entrypoint eksekusi program.
Ok, sekarang mari kita coba praktekan penerapan module sebagai dependency
(module yang di-import di module lain).
Buat program baru dengan isi kode di bawah ini. File my_program.py kita
fungsikan sebagai entrypoint program, sedangkan module calculate sebagai
dependency yang di-import di my_program .
Project structure
Selanjutnya tulis isi kode file calculate :
File calculate.py
Module calculate berisi 1 buah variabel dan 3 buah fungsi:
• Variabel note berisi string
• Fungsi calc_hypotenuse() untuk menghitung nilai hipotenusa dari a
dan b
• Fungsi pow() untuk meperingkas operasi pangkat
• Fungsi sqrt() untuk mencari akar kuadrat
belajar-module/
│─── calculate.py
└─── my_program.py
note = "module calculate contains mathematic functions"
def calc_hypotenuse(a, b):
return sqrt(pow(a) + pow(b))
def pow(n, p = 2):
return n ** p
def sqrt(x):
n = 1
for _ in range(10):
n = (n + x/n) * 0.5
return n
Kesemua unit di atas di-import ke my_program untuk kemudian digunakan
dalam perhitungan pencarian nilai hipotenusa.
File my_program.py
Coba jalankan program menggunakan command berikut agar module
my_program menjadi entrypoint eksekusi program.
Output:
a = 10
b = 15
import calculate
print(calculate.note)
res = calculate.calc_hypotenuse(a, b)
print("hypotenuse:", res)
res = calculate.sqrt(a**2 + b**2)
print("hypotenuse:", res)
res = calculate.sqrt(calculate.pow(a) + calculate.pow(b))
print("hypotenuse:", res)
python my_program.py
Implementasi module di Python cukup mudah bukan?
Keyword import digunakan untuk meng-import suatu module atau class.
Pada contoh di atas module calculate di-import ke my_program.py untuk
kemudian digunakan fungsi-fungsi didalamnya.
Pengaksesan variabel/konstanta dari suatu module menggunakan notasi
<module>.<variable/constant> , contohnya calculate.note .
Sedangkan pengaksesan fungsi menggunakan notasi
<module>.<function>() , contohnya seperti calculate.calc_hypotenuse() ,
calculate.sqrt() , dan calculate.pow() .
A.27.2. Behaviour import module
Ketika suatu module di-import, semua unit di dalamnya dapat diakses dari file
peng-import. Contohnya bisa dilihat pada kode yang sudah ditulis, variabel
note dan fungsi calc_hypotenuse() yang berada di module calculate ,
keduanya bisa langsung digunakan.
Jika dalam module ada statement yang sifatnya bukan deklarasi variabel atau
fungsi, misalnya seperti statement print, maka statement tersebut akan
langsung dieksekusi saat module ter-import.
Mari coba praktekan. Tambahkan statement berikut di file calculate.py :
File calculate.py
print("hello from calculate")
note = "module calculate contains mathematic functions"
Jalankan program, lihat hasilnya:
A.27.3. Naming convention module
Mengacu ke dokumentasi PEP 8 – Style Guide for Python Code, nama module
dianjurkan untuk ditulis dalam huruf kecil (lowercase) dengan underscode
sebagai pembatas antar kata.
A.27.4. Keyword from dan import
Ada dua bentuk penerapan keyword import . Pertama, yaitu untuk meng-
import module, contohya seperti pada praktek di atas ( import calculate ).
Kedua, yaitu mengkombinasikan keyword tersebut dengan keyword from
untuk meng-import langsung fungsi atau item lainnya dari suatu module.
Contoh:
File my_program.py
a = 10
b = 15
from calculate import note
from calculate import calc_hypotenuse
from calculate import sqrt
Dua versi berbeda my_program.py di atas yaitu ekuivalen, keduanya
melakukan operasi yang sama persis dan menghasilkan output yang sama
pula.
Pada contoh ke-2 (program yang baru saja ditulis), variabel note , fungsi
calc_hypotenuse() dan sqrt() di-import secara langsung via statement
from calculate import <function> .
Untuk penulisannya bisa dituliskan satu per satu statement import-nya, atau
bisa cukup sebaris saja (cara ini hanya berlaku untuk import item yang
bersumber dari module yang sama).
â—‰ Fungsi pow()
Fungsi pow() merupakan fungsi bawaan Python Standard Library yang bisa
langsung digunakan tanpa perlu meng-import apapun.
Cara penggunaan fungsi pow() yaitu dengan langsung menulisnya dalam
skema pow(a, b) . Fungsi ini menghasilkan operasi matematika a pangkat
b .
Pada kode di atas, fungsi pow() milik module calculate sengaja tidak di-
import agar tidak meng-override atau menimpa fungsi pow() bawaan Python.
from calculate import note
from calculate import calc_hypotenuse
from calculate import sqrt
# vs
from calculate import note, calc_hypotenuse, sqrt
A.27.5. Statement from <module> import
*
Statement from <module> import * digunakan untuk meng-import semua
unit yang ada dalam module <module> . Contoh penerapannya:
File my_program.py
A.27.6. Keyword as
Module maupun fungsi bisa di-import dengan diberi nama alias. Biasanya
teknik ini digunakan pada situasi dimana module yang di-import namanya
cukup panjang, maka digunakan alias agar lebih pendek. Pembuatan alias
sendiri dilakukan via keyword as .
a = 10
b = 15
from calculate import *
print(note)
res = calc_hypotenuse(a, b)
print("hypotenuse:", res)
res = sqrt(a**2 + b**2)
print("hypotenuse:", res)
res = sqrt(pow(a, 2) + pow(b, 2))
print("hypotenuse:", res)
Penerapannya bisa dilihat pada contoh berikut:
File my_program.py
Penjelasan:
• Statement import calculate as calc meng-import module calculate
dengan alias calc . Nantinya fungsi-fungsi dalam module tersebut bisa
diakses via calc.<function>() .
• Statement from calculate import calc_hypotenuse as hptns, sqrt
meng-import:
â—¦ Fungsi calc_hypotenuse() dari module calculate dengan alias
hptns() .
â—¦ Fungsi sqrt() dari module calculate .
a = 10
b = 15
import calculate as calc
from calculate import calc_hypotenuse as hptns, sqrt
print(calc.note)
res = hptns(a, b)
print("hypotenuse:", res)
res = sqrt(a**2 + b**2)
print("hypotenuse:", res)
res = sqrt(calc.pow(a) + calc.pow(b))
print("hypotenuse:", res)
A.27.7. Urutan pencarian module
Ketika suatu module di-import, Python akan melakukan pencarian file module
di beberapa tempat berikut secara berurutan:
1. Pertama, Python akan mencari module di folder yang sama dimana
statement import digunakan.
2. Jika pencarian pertama tidak menemukan hasil, maka Python lanjut
mencari file module ke folder dimana environment variable PYTHONPATH
di-set.
3. Jika pencarian kedua juga tidak menemukan hasil, Python melanjutkan
pencarian di folder dimana Python di-install.
4. Jika pencarian ketiga juga tidak sukses (file module tidak ditemukan), maka
eksekusi program menghasilkan error.
A.27.8. File module dalam folder
Bagaimana jika suatu file module (misalnya calculate.py ) berada di dalam
suatu sub-folder dalam folder program, apakah cara import-nya sama?
Sebenarnya sama namun ada sedikit perbedaan yang harus diketahui.
Selengkapnya akan kita bahas pada chapter selanjutnya, yaitu Packages.
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../modules
â—‰ Chapter relevan lainnya
• Packages
• Special Names
â—‰ Referensi
• https://docs.python.org/3/tutorial/modules.html
A.28. Python Packages
Pada chapter ini, kita akan membahas cara Python mengelola module melalui
packages. Dengan package, module bisa diakses menggunakan notasi
pengaksesan module, contohnya seperti calculate.calc_hypotenuse() .
A.28.1. Pengenalan Packages
Mari kita mulai dengan sedikit mengulang pembahasan yang ada di chapter
sebelumnya. Di Python, module direpresentasikan oleh file, dan agar bisa
mengakses item yang ada dalam module tersebut kita perlu meng-import-nya
terlebih dahulu.
Package yaitu cara mengelola module dengan menempatkannya dalam
suatu folder. Sederhananya: module yaitu file, dan package yaitu
folder.
Untuk mendemonstrasikan konsep ini, mari kita praktekan. Buat project baru
dengan struktur seperti berikut:
Project structure
Program yang dibuat masih sama seperti yang ada di praktek sebelumnya.
belajar-package/
│─── libs/
| │─── calculate.py
| └─── common/
| │─── message.py
| └─── number.py
└─── my_program.py
Perbedaannya, kali ini fungsi sqrt() dan pow() ditempatkan dalam path
libs/common/number.py , dan ada juga satu fungsi baru dibuat di libs/
common/message.py .
File: libs/common/number.py
File: libs/common/message.py
Selanjutnya, isi file calculate.py dengan deklarasi variabel note dan fungsi
calc_hypotenuse() .
File: libs/calculate.py
note = "module libs.common.number contains numerical functions"
def pow(n, p = 2):
return n ** p
def sqrt(x):
n = 1
for _ in range(10):
n = (n + x/n) * 0.5
return n
note = "module libs.common.message contains messaging/printing functions"
def print_hypotenuse(v):
print("hypotenuse:", v)
import libs.common.number
note = "module libs.calculate contains mathematic functions"
Terakhir, di file my_program.py (file entrypoint eksekusi program), import
module libs/common/number.py , libs/common/message.py , dan libs/
calculate.py lalu panggil fungsi yang ada di masing-masing module. Contoh:
File: my_program.py
Bisa dilihat bagaimana peran package dalam operasi import module dan
pengaksesan unit dalam module.
• Module yang berada dalam package di import menggunakan notasi
<package>.<module> . Contoh:
â—¦ import libs.calculate di file my_program.py
• Jika ada package di dalam package, maka ditulis semua subfoldernya,
a = 10
b = 15
import libs.calculate
import libs.common.number
import libs.common.message
print(libs.calculate.note)
print(libs.common.number.note)
print(libs.common.message.note)
res = libs.calculate.calc_hypotenuse(a, b)
libs.common.message.print_hypotenuse(res)
res = libs.common.number.sqrt(a**2 + b**2)
libs.common.message.print_hypotenuse(res)
res = libs.common.number.sqrt(libs.common.number.pow(a) +
libs.common.number.pow(b))
libs.common.message.print_hypotenuse(res)
seperti: <package>.<package>.<module> . Contoh:
â—¦ import libs.common.number di file libs/calculate.py
â—¦ import libs.common.number di file my_program.py
â—¦ import libs.common.message di file my_program.py
• Pengaksesan unit dalam module diwajibkan dengan ditulis namespace nya
secara utuh, jadi nama package juga ditulis. Contohnya bisa dilihat pada
beberapa statement seperti:
â—¦ libs.common.number.sqrt() di file libs/calculate.py
â—¦ libs.common.number.pow() di file libs/calculate.py
â—¦ libs.calculate.calc_hypotenuse() di file my_program.py
â—¦ libs.common.message.print_hypotenuse() di file my_program.py
Ok, selanjutnya coba jalankan program dan lihat hasilnya:
A.28.2. Naming convention package
Berdasarkan dokumentasi PEP 8 – Style Guide for Python Code, disarankan
untuk menulis nama package dengan huruf kecil (lowercase) dan dianjurkan
untuk menghindari penggunaan underscore.
A.28.3. Metode import module package
Seperti halnya module biasa, module dalam package bisa di-import dengan
beberapa cara:
â—‰ Alias module via keyword as
Alias cukup berguna untuk mempersingkat penulisan module saat memanggil
item didalamnya. Keyword as digunakan untuk pemberian nama alias
module.
File: libs/calculate.py
File: my_program.py
import libs.common.number as num
note = "module libs.calculate contains mathematic functions"
def calc_hypotenuse(a, b):
return num.sqrt(num.pow(a) + num.pow(b))
a = 10
b = 15
import libs.calculate as calc
import libs.common.number as num
import libs.common.message as msg
print(calc.note)
print(num.note)
print(msg.note)
Dengan menggunakan alias, namespace tidak perlu lagi dituliskan secara
penuh, contohnya libs.common.number.note cukup ditulis dengan
num.note .
â—‰ Import package via from & import
Kombinasi keyword from dan import dapat digunakan dengan ketentuan:
setelah keyword from yang ditulis yaitu namespace package, lalu diikuti
oleh keyword import dan nama module. Contoh:
File: libs/calculate.py
File: my_program.py
import libs.common.number
print(libs.common.number.note)
# vs
import libs.common.number as num
print(num.note)
from libs.common import number
note = "module libs.calculate contains mathematic functions"
def calc_hypotenuse(a, b):
return number.sqrt(number.pow(a) + number.pow(b))
a = 10
b = 15
â—‰ Penggunaan import *
Ada beberapa hal yang perlu diketahui dalam penggunaan import * , namun
sebelum membahasnya, silakan coba terlebih dahulu kode berikut. Silakan
buka my_program.py lalu ubah statement import menjadi seperti ini:
Hasilnya yaitu error:
from libs import calculate as calc
from libs.common import *
A.28.4. File __init__.py
Melanjutkan pembahasan sebelumnya dimana import * menghasilkan error,
hal tersebut terjadi karena Python tidak bisa mendeteksi module apa saja yang
bisa direpresentasikan dengan * saat meng-import suatu package.
Untuk mengatasi error, tambahkan file bernama ___init___.py di setiap
package/folder. Dengan ini maka struktur file program menjadi seperti ini:
Project structure
Isi file __init__.py dengan sebuah statement deklarasi variabel bernama
__all__ , dengan nilai yaitu list nama module yang ada di dalam folder
tersebut.
File: libs/common/__init__.py
File: libs/__init__.py
belajar-package/
│─── libs/
| │─── __init__.py
| │─── calculate.py
| └─── common/
| │─── __init__.py
| │─── message.py
| └─── number.py
└─── my_program.py
__all__ = ["message", "number"]
Setelah penambahan di atas dilakukan, maka module yang berada dalam
package bisa di-import menggunakan import * .
Coba sekarang test dengan mengaplikasikannya di program:
File: my_program.py
â—‰ Best practice file __init__.py
Sesuai penjelasan di dokumentasi Package, dianjurkan untuk selalu membuat
file __init__.py di setiap package/folder untuk menghindari masalah saat
pencarian module.
__all__ = ["calculate"]
a = 10
b = 15
from libs import *
from libs.common import *
print(calculate.note)
print(number.note)
print(message.note)
res = calculate.calc_hypotenuse(a, b)
message.print_hypotenuse(res)
res = number.sqrt(a**2 + b**2)
message.print_hypotenuse(res)
res = number.sqrt(number.pow(a) + number.pow(b))
message.print_hypotenuse(res)
Meskipun module dalam package tidak digunakan via statement import * ,
dianjurkan untuk tetap membuat file tersebut. Isinya biarkan kosong saja tidak
apa-apa.
â—‰ Special name __all__
Variabel yang diawali dan diakhir dengan karakter double underscore seperti
__all__ disebut sebagai variabel special name. Pembahasan lebih lanjut
tentang special names ada di chapter Special Names.
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../packages
â—‰ Chapter relevan lainnya
• Modules
• Special names
â—‰ Referensi
• https://docs.python.org/3/tutorial/modules.html#packages
A.29. Python Variables
Scope (Local vs. Global)
Pada chapter ini kita akan membahas tentang variable scope, yaitu kapan
suatu variabel valid dan bisa digunakan di dalam block serta beberapa fungsi
yang masih relevan dengan topik variabel scope.
A.29.1. Local vs. global variable
Global variable yaitu variabel yang dideklarasikan di root (tidak di dalam
suatu block fungsi). Sedangkan local variable yaitu yang dideklarasikan di
dalam suatu block dan hanya valid di block tersebut saja.
Contoh, sebuah file program Python bernama main.py di isi dengan kode
berikut:
File main.py
name = "Cleaver Bmurglbrm"
print("greetings", name)
def greet():
today = "Saturday"
print("happy", today, name)
if name:
greet()
greet_message = "have a good day"
print("hello", name, greet_message)
# output ↓
Variabel name disitu merupakan variabel global. Variabel jenis ini bisa diakses
dari block manapun. Di contoh, variabel name diakses di dalam block fungsi
greet() dan di block seleksi kondisi if name: .
Berbeda dengan variabel today yang tempat deklarasinya ada di block fungsi
greet() , membuatnya hanya valid untuk digunakan di block itu saja. Variabel
today dikategorikan sebagai variabel local dengan scope yaitu block fungsi
greet() .
Selain itu ada juga variabel lain bernama greet_message yang dideklarasikan
di block seleksi kondisi if name: .
Sekarang coba akses variabel today dari luar block, hasilnya pasti error.
Keterangan errornya: variabel today tidak dikenali.
Bagaimana jika variabel greet_message diakses dari luar block seleksi
kondisi, apakah juga error? Jawabannya, tidak!
Di editor terlihat variabel greet_message digaris-bawahi merah, menandakan
ada error namun hanya di level linter saja. Error tersebut tidak membuat
eksekusi program menjadi gagal.
Sampai sini bisa ditarik kesimpulan bahwa variabel global bisa diakses dari
mana saja, sedangkan variabel local bisa diakses di dalam block dimana ia
dideklarasikan. Pengaksesan variabel local diluar block-nya memiliki efek
samping berikut:
• Jika variabel local dideklarasikan di dalam block fungsi/lambda/closure,
maka pengaksesannya dari luar block menghasilkan error.
• Jika variabel local dideklarasikan di block seleksi kondisi atau lainnya, maka
pengaksesaannya dari luar block diperbolehkan dan tidak membuat
eksekusi program menjadi error. Namun warning atau error di level linter
muncul.
A.29.2. Local dan global variable dengan
nama sama
Katakanlah ada variabel global dan variabel local yang namanya sama persis,
di situasi seperti ini maka nilai variabel local pada block-nya yaitu sesuai
dengan saat deklarasinya dalam block. Di luar block, variabel tersebut nilainya
kembali berisi nilai variabel global.
Agar lebih jelas coba praktekan kode berikut:
Bisa dilihat dari output bahwa variabel name nilainya yaitu Keymaster
Urmgrgl , sesuai dengan isi variabel saat deklarasi di block fungsi greet() .
Namun di luar block fungsi, nilainya kembali menjadi Cleaver Bmurglbrm .
Dari sini bisa diambil kesimpulan bahwa di luar block, perubahan nilai variabel
local tidak berefek ke variabel global, meskipun namanya sama persis.
name = "Cleaver Bmurglbrm"
def greet():
name = "Keymaster Urmgrgl"
print("hello", name)
greet()
print("greetings", name)
# output ↓
#
# hello Keymaster Urmgrgl
# greetings Cleaver Bmurglbrm
A.29.3. Keyword global
Untuk mengubah nilai suatu variabel global dari block, maka perlu adanya
penggunaan keyword global . Keyword ini menandai variabel dalam block
bahwa reference yang digunakan yaitu variabel global. Efeknya, perubahan
nilai pada variabel juga berpengaruh ke variabel global.
Contoh penerapan:
Cara penggunaan keyword global yaitu dengan cukup menuliskannya di
dalam block kemudian diikuti nama variabel. Dari output terlihat bahwa di luar
block fungsi greet() nilai variabel name berubah.
A.29.4. Fungsi globals()
Fungsi globals() mengembalikan informasi semua variabel global yang bisa
name = "Cleaver Bmurglbrm"
def greet():
global name
name = "Keymaster Urmgrgl"
print("hello", name)
greet()
print("greetings", name)
# output ↓
#
# hello Keymaster Urmgrgl
# greetings Keymaster Urmgrgl
diakses dari tempat dimana fungsi dipanggil. Nilai balik berbentuk dictionary
dengan key yaitu nama variabel dan value yaitu nilai variabel.
Contoh penerapannya bisa dilihat pada kode berikut. Ada variabel bernama
my_var yang nilainya diakses via nilai balik pemanggilan fungsi globals()
A.29.5. Fungsi locals()
Fungsi locals() mengembalikan informasi variabel yang dideklarasikan di
block dimana fungsi tersebut dipanggil dengan nilai balik berbentuk dictionary.
Pada contoh berikut, variabel my_var dideklarasikan di luar block fungsi
task_two() , sedangkan another_var didalamnya.
Di dalam task_two() , variabel another_var bisa diakses via nilai balik
fungsi locals() karena masih satu block. Tidak seperti my_var ,
pengaksesannya via nilai balik fungsi locals() akan menghasilkan error
karena variabel tersebut tidak dikenali.
my_var = 12
def task_one():
all_global_vars = globals()
print(all_global_vars['my_var'])
task_one()
# output ➜ 12
my_var = 12
def task_two():
another_var = "Hello Python"
Di contoh, ditambahkan block try except untuk menangkap error yang
muncul saat statement all_locals_vars['my_var'] dieksekusi.
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../local-
global-var
â—‰ TBA
• Variabel global pada module
â—‰ Referensi
• https://docs.python.org/3/faq/programming.html
• https://docs.python.org/3/library/functions.html#locals
• https://docs.python.org/3/library/functions.html#globals
A.30. Python Special
Names
Chapter ini membahas tentang variabel spesial yang ada di Python (umumnya
disebut special names).
Python memiliki variabel spesial yang bisa diakses secara global. Ciri khas
special names yaitu penulisannya diawali dan diakhiri dengan karakter __ .
Salah satunya yaitu variabel __all__ yang telah diulas di chapter
sebelumnya.
Setiap special names memiliki kegunaan yang unik dan berbeda satu sama
lain.
A.30.1. Variabel __name__
Variabel __name__ yaitu salah satu special names di Python. Isinya
mencakup informasi nama modul atau string __main__ , tergantung apakah
variabel tersebut di-print dari file entrypoint eksekusi program atau di-import.
File entrypoint yang dimaksud disini yaitu file yang digunakan pada
argument command python <nama_file_program> .
Agar lebih jelas, mari kita langsung praktekan. Silakan siapkan folder project
baru dengan struktur file seperti ini:
Project structure example-1
example-1/
Folder project example-1 ini berisi hanya 2 file, yaitu calculate.py dan
my_program.py .
Selanjutnya, buka calculate.py dan tulis kode untuk mencari bilangan
prima:
File: calculate.py
File calculate.py difungsikan sebagai module bernama calculate , yang
nantinya di-import pada file my_program.py . Statement print("from
calculate.py:", __name__) akan otomatis dieksekusi saat ter-import. Selain
itu, ada juga fungsi is_prime() yang berisi kode pencarian bilangan prima.
Penjelasan detail mengenai module ada di chapter Modules
print("from calculate.py:", __name__)
def is_prime(num):
print("from calculate.py is_prime(num):", __name__)
flag = False
if num == 1:
print(num, "is not a prime number")
elif num > 1:
for i in range(2, num):
if (num % i) == 0:
flag = True
break
if flag:
print(num, "is not a prime number")
else:
print(num, "is a prime number")
Lanjut, buka file my_program.py dan isi dengan kode berikut:
File: my_program.py
File my_program.py nantinya kita gunakan sebagai entrypoint eksekusi
program via perintah python.exe my_program.py . Isi file tersebut yaitu 5
buah statement yang masing-masing penjelasannya bisa dilihat di bawah ini:
1. Statement print("from my_program.py:", __name__) dieksekusi
2. Module calculate di-import
3. Module random di-import
4. Fungsi randint() dalam module random dieksekusi
5. Fungsi is_prime() milik module calculate dieksekusi
Jalankan program menggunakan command python my_program.py , lalu lihat
outputnya:
Dari contoh, dapat dilihat bahwa special names __name__ jika di-print dari
print("from my_program.py:", __name__)
import calculate
import random
num = random.randint(0, 999)
calculate.is_prime(num)
my_program.py memiliki value string "__main__" . Hal ini karena file
my_program.py yaitu entrypoint program. Sedangkan pada module
calculate , variabel yang sama menghasilkan output berbeda, yaitu
calculate yang merupakan nama module file calculate.py .
Untuk mengetahui file mana yang merupakan file entrypoint eksekusi
program, selain dengan mengecek nilai variabel __name__ bisa juga
dengan melihat argument eksekusi program. Misalnya python
my_program.py , maka file entrypoint yaitu my_program.py
Variabel __name__ biasanya dimanfaatkan sebagai kontrol entrypoint
program, misalnya untuk membedakan statement yang akan dieksekusi ketika
module digunakan sebagai entrypoint atau digunakan sebagai dependency
atau module yang di-import di module lain.
Contoh pengaplikasian skenario yang disebutkan dapat ditemukan pada
contoh program ke-2 berikut:
Project structure example-2
File: calculate.py
example-2/
│─── calculate.py
└─── main.py
def is_prime(num):
flag = False
if num == 1:
print(num, "is not a prime number")
File: main.py
Penjelasan:
• Module calculate jika di-run sebagai entrypoint, maka statement dalam
blok seleksi kondisi if __name__ == '__main__' otomatis tereksekusi.
Jika tidak digunakan sebagai entrypoint, maka tidak ada statement yang
dieksekusi.
• Module main jika di-run sebagai entrypoint, maka module tersebut akan
meng-import module calculate lalu memanggil fungsi is_prime() yang
dideklarasikan didalamnya.
A.30.2. Variabel __file__
Variabel special name __file__ berisi informasi path file di mana variabel
tersebut ditulis atau digunakan. Ada dua cara untuk menggunakan variabel ini:
• Dengan mengaksesnya secara langsung
import calculate
import random
num = random.randint(0, 999)
calculate.is_prime(num)
• Dengan mempergunakannya sebagai property dari module, misalnya:
random.__file__
Contoh penerapannya bisa dilihat pada program berikut:
Project structure example-3
File: calculate.py
File: main.py
example-3/
│─── calculate.py
└─── main.py
def is_prime(num):
flag = False
if num == 1:
print(num, "is not a prime number")
elif num > 1:
for i in range(2, num):
if (num % i) == 0:
flag = True
break
if flag:
print(num, "is not a prime number")
else:
print(num, "is a prime number")
print("module main", __file__)
import calculate
Bisa dilihat pada gambar berikut bahwa output program yaitu memunculkan
nama module beserta lokasi di mana file module tersebut berada:
Penggunaan __file__ akan menampilkan path file dimana variabel tersebut
ditulis, sedangkan penggunaannya sebagai property module (misalnya
calculate.__file__ ) menghasilkan informasi path module.
A.30.3. Variabel __all__ & file
__init__.py
Variabel __all__ digunakan untuk menentukan module apa saja yang ter-
import ketika statement import * digunakan. Variabel __all__ wajib ditulis
di file __init__.py yang ditempatkan dalam package.
Penjelasan detail mengenai import * ada pada chapter Packages.
A.30.4. Attribute __name__ milik class
type
Kita telah menggunakan fungsi type() beberapa kali pada banyak chapter
sebelum ini. Fungsi type() yaitu fungsi yang mengembalikan data dengan
tipe yaitu class type .
Class type memiliki attribute bernama __name__ isinya informasi nama
class. Contoh penerapan pengaksesan attribute ini:
A.30.5. Attribute __class__ milik semua
class / tipe data
Setiap tipe data memiliki akses ke attribute bernama __class__ . Isi dari
attribute ini yaitu data yang sama hasil pemanggilan fungsi type() yaitu
informasi tipe data atau class.
Pada kode sebelumnya, statement type(data1) menghasilkan nilai balik yang
sama dengan statement data1.__class__ . Dari nilai balik (yang bertipe
type ) tersebut bisa langsung dilakukan pengaksesan attribute __name__ .
A.30.6. Attribute __mro__ milik semua
data1 = "Noval Agung"
print(f"var: data1, data: {data1}, type: {type(data1).__name__}")
# output ➜ var: data1, data: Noval Agung, type: str
data2 = 24 * 7
print(f"var: data2, data: {data2}, type: {type(data2).__name__}")
# output ➜ var: data2, data: 168, type: int
data1 = "Noval Agung"
print(f"var: data1, data: {data1}, type: {data1.__class__.__name__}")
# output ➜ var: data1, data: Noval Agung, type: str
data2 = 24 * 7
print(f"var: data2, data: {data2}, type: {data2.__class__.__name__}")
# output ➜ var: data2, data: 168, type: int
class / tipe data
Class attribute __mro__ berisi informasi hirarki class dalam tipe data tuple.
Penjelasan lebih lanjut mengenai __mro__ ada di chapter OOP ➜ Class
Inheritance.
A.30.7. Package __future__
Package __future__ berisi modules yang hanya tersedia di Python versi
terbaru. Package ini biasa di-import pada program yang dijalankan
menggunakan Python versi lama (misalnya 2.5), yang didalamnya ada
penerapan kode yang hanya ada di versi Python terbaru.
Salah satu contoh yaitu penggunaan operator // untuk operasi floor
division atau pembagian dengan hasil dibulatkan. Operator tersebut hanya
tersedia di Python 3.0+.
Agar bisa menggunakan operator tersebut di Python versi lama harus ada,
perlu untuk meng-import module division dari package __future__ . Tulis
statement import di file program baris paling atas sendiri.
from __future__ import division
print(8 / 7)
# output ➜ 1.1428571428571428
print(8 // 7)
# output ➜ 1
A.30.8. Fungsi __init__()
Fungsi __init__() digunakan untuk membuat konstruktor pada suatu class.
Penjelasan lebih lanjut mengenai __init__() ada di chapter OOP ➜ Class &
Object.
A.30.9. Attribute __doc__ milik semua
class dan fungsi
Attribute __doc__ digunakan untuk melihat informasi komentar docstring.
Penjelasan lebih lanjut mengenai __doc__ ada di chapter DocString.
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../special-
names
â—‰ Chapter relevan lainnya
• Modules
• Packages
• OOP ➜ Class & Object
• OOP ➜ Class Inheritance
â—‰ Referensi
• https://docs.python.org/3/tutorial/modules.html
• https://docs.python.org/3/tutorial/special-names.html
• https://stackoverflow.com/questions/7075082/what-is-future-in-python-
used-for-and-how-when-to-use-it-and-how-it-works
A.31. Python None
Pada chapter ini kita akan belajar tentang object special bernama None .
A.31.1. Pengenalan None
None merupakan object bawaan Python yang umumnya digunakan untuk
merepresentasikan nilai kosong atau null.
Ketika suatu variabel berisi data yang nilainya bisa kosong, umumnya sebelum
variabel tersebut digunakan, dilakukan pengecekan terlebih dahulu
menggunakan seleksi kondisi untuk memastikan apakah nilainya benar-benar
kosong atau tidak.
Sebagai contoh, pada kode berikut, dipersiapkan sebuah fungsi bernama
inspect_data() , tugasnya mengecek apakah variabel memiliki nilai atau
tidak.
def inspect_data(data):
if data is None:
print("data is empty. like very empty")
else:
print(f"data: {data}, type: {type(data).__name__}")
data = 0
inspect_data(data)
# output ➜ data: 0, type: int
data = ""
inspect_data(data)
# output ➜ data: , type: str
Bisa dilihat pada program di atas output tiap statement yaitu berbeda-beda
sesuai tipe datanya.
• Ketika variabel data berisi 0 maka variabel tersebut tidak benar-benar
kosong, melainkan berisi angka 0 .
• Karakteristik yang sama juga berlaku ketika variabel berisi string kosong
"" , meskipun ketika di-print tidak muncul apa-apa, variabel tersebut
sebenarnya berisi tipe data string namun tanpa isi (string dengan panjang
nol). Maka variabel tersebut sebenarnya tidak benar-benar kosong.
• Barulah ketika variabel isinya data None maka dianggap benar-benar
kosong.
Kode di atas berisi penerapan salah satu special name, yaitu attribute
__name__ milik class type .
Pembahasan detail mengenai special name ada di chapter Special
Names ➜ Attribute name milik class type
A.31.2. Penggunaan operator is
terhadap None
Ketika memeriksa apakah sebuah objek bernilai None atau tidak, disarankan
untuk menggunakan operator is dibanding == , karena sifat dari operator
== memanggil special method __eq__() dari objek yang diperiksa dan pada
praktiknya tidak semua class menggunakan implementasi default method
__eq__() . Dari sini maka potensi penggunaan operator == menghasilkan
nilai yg berbeda dibanding yang diharapkan yaitu ada (meskipun sangat
kecil).
Serta, operator is lebih cepat dibanding == untuk pengecekan data None .
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../none
â—‰ Chapter relevan lainnya
• Tipe Data
• Special Names
â—‰ Referensi
• https://docs.python.org/3/c-api/none.html
• https://stackoverflow.com/questions/3257919/what-is-the-difference-
between-is-none-and-none
• https://stackoverflow.com/questions/26595/is-there-any-difference-
between-foo-is-none-and-foo-none/26611#26611
A.32. Python Pack Unpack
tuple, list, set, dict
Python mengenal teknik packing dan unpacking, dimana teknik ini umum
diterapkan sesuai kebutuhan pada beberapa jenis tipe data kolektif seperti
tuple, list, set, dan dictionary. Pada chapter ini kita akan mempelajari cara
penggunaannya, beserta peran penggunaan tanda * dan ** pada operasi
packing dan unpacking.
A.32.1. Unpacking element tuple, list, set
Unpacking (yang dalam Bahasa Indonesia berarti bongkar muatan) yaitu
teknik pendistribusian elemen tipe data kolektif ke banyak variabel.
Distribusinya sendiri bisa 1 on 1 yang berarti setiap elemen ditampung 1
variabel, atau hanya beberapa elemen saja yang didistribusikan ke variabel
baru, sisanya tetap ditampung dalam bentuk data kolektif.
â—‰ Unpack 1 element = 1 variable
Pada program berikut ada sebuah tuple bernama names yang setiap element-
nya perlu untuk didistribusikan ke variabel independen. Karena ada 6 buah
elemen dalam tuple tersebut, maka perlu disiapkan 6 buah variabel untuk
menampung data masing-masing element.
names = (
'Mikasa Ackerman',
'Armin Arlert',
'Eren Yeager',
Jika jumlah variabel penampung tidak sama dengan jumlah element data
kolektif, misalnya jumlah variabel lebih sedikit, maka error pasti muncul saat
eksekusi program.
â—‰ Unpack hanya N elements pertama
Ada alternatif cara lain untuk kasus lainnya dimana element yang perlu
ditampung ke variabel baru hanya beberapa element pertama saja. Misalnya,
dari 6 element tuple, hanya 3 yang perlu disimpan ke variabel baru. Hal seperti
ini bisa dilakukan dengan konsekuensi: sisa element lainnya ditampung dalam
bentuk kolektif di satu variabel lain.
Contoh penerapannya bisa dilihat di kode berikut. Tuple yang sama, 3 element
pertamanya saja yang ditampung ke variabel baru. Untuk element sisanya,
tetap harus ditampung juga tapi cukup di 1 variabel saja, tersimpan dalam
tiple data list .
Variabel penampung sisa element selalu dalam bentuk list meskipun
sumber datanya bertipe data lain.
Bisa dilihat dari output, bahwa 3 element pertama berhasil ditampung di 3
variabel baru. Sisanya tetap disimpan ke variabel lain yang pada contoh di
atas yaitu variabel warriors .
Penulisan variabel penampung sisa element diawali dengan karakter * dan
pasti tipe datanya yaitu list.
Penulisan karakter * di awal variabel ini wajib. Jika tidak ditulis, maka
Python menganggap ada 4 buah variabel mencoba menampung element
tuple.
names = (
'Mikasa Ackerman',
'Armin Arlert',
'Eren Yeager',
'Zeke Yeager',
'Reiner Braun',
'Annie Leonhart'
)
soldier1, soldier2, deceiver1, *warriors = names
print(soldier1) # output ➜ Mikasa Ackerman
print(soldier2) # output ➜ Armin Arlert
print(deceiver1) # output ➜ Eren Yeager
print(warriors) # output ➜ ['Zeke Yeager', 'Reiner Braun', 'Annie
Leonhart']
Jika diterapkan pada kasus di atas, statement tersebut pasti
menghasilkan error, karena data names berisi 6 element.
Katakanlah data element yang dibutuhkan hanya 3 pertama, sisanya bisa
dibuang, maka bisa gunakan variabel _ sebagai tempat pembuangan
element yang tidak terpakai.
â—‰ Unpack hanya N elements terakhir
teknik ini mirip seperti sebelumnya, perbedaannya: variabel penampung
element berada di sebelah kanan dan sisa element ditampung di variabel
paling kiri.
Jadi variabel bertanda * harus ditulis di paling kiri.
Pada contoh berikut, element yang sama disimpan namun dalam bentuk tipe
data berbeda, yaitu set.
soldier1, soldier2, deceiver1, *_ = names
print(soldier1) # output ➜ Mikasa Ackerman
print(soldier2) # output ➜ Armin Arlert
print(deceiver1) # output ➜ Eren Yeager
names = {
'Mikasa Ackerman',
'Armin Arlert',
'Eren Yeager',
'Zeke Yeager',
'Reiner Braun',
'Annie Leonhart'
}
Variabel penampung sisa element (yaitu soldiers ) tipe datanya list .
â—‰ Unpack hanya N elements pertama dan terakhir
Bagaimana jika elements yang di-unpack yaitu yang posisinya ada di
samping? Bisa juga, caranya dengan menampung sisanya di tengah.
Pada contoh berikut, ada sebuah list yang 2 element pertamanya ditampung
ke variabel independen, 2 terakhir juga ditampung ke variabel independen,
dan sisanya (yang posisinya di tengah) ditampung ke variabel lain.
Tanda * dituliskan pada variabel yang ditengah dengan penulisan bebas di
posisi mana saja, asalkan tidak di awal dan tidak di akhir. Python secara cerdas
tahu element mana yang dianggap sisa dengan melihat statementnya.
names = [
'Mikasa Ackerman',
'Armin Arlert',
'Eren Yeager',
'Zeke Yeager',
'Reiner Braun',
'Annie Leonhart'
]
soldier1, soldier2, *deceivers, warrior1, warrior2 = names
print(soldier1) # output ➜ Mikasa Ackerman
print(soldier2) # output ➜ Armin Arlert
print(deceivers) # output ➜ ['Eren Yeager', 'Zeke Yeager']
print(warrior1) # output ➜ Reiner Braun
print(warrior2) # output ➜ Annie Leonhart
A.32.2. Packing element tuple, list, set
Packing element yaitu operasi pemuatan banyak data ke sebuah data
kolektif. Cara penerapannya sangat mudah, cukup tulis saja variabel yang ingin
di-pack sebagai element data kolektif. Untuk tipenya bisa berupa tuple, list,
maupun set.
soldier1 = 'Mikasa Ackerman'
soldier2 = 'Armin Arlert'
soldier3 = 'Eren Yeager'
warrior1 = 'Zeke Yeager'
warrior2 = 'Reiner Braun'
warrior3 = 'Annie Leonhart'
tuple1 = (soldier1, soldier2, soldier3, warrior1, warrior2, warrior3)
print(tuple1)
# output ↓
#
# ('Mikasa Ackerman',
# 'Armin Arlert',
# 'Eren Yeager',
# 'Zeke Yeager',
# 'Reiner Braun',
# 'Annie Leonhart')
list1 = [soldier1, soldier2, soldier3, warrior1, warrior2, warrior3]
print(list1)
# output ↓
#
# ['Mikasa Ackerman',
# 'Armin Arlert',
# 'Eren Yeager',
# 'Zeke Yeager',
# 'Reiner Braun',
# 'Annie Leonhart']
Perlu diingat, bahwa tipe data set tidak menjamin elemennya tersimpan
secara urut. Jadinya sewaktu diakses atau di-print bisa saja urutan
elemen berubah.
Pembahasan detail mengenai set ada di chapter Set
â—‰ Prepend element
Operasi prepend bisa dilakukan dengan mudah menggunakan syntax
(newElement, *oldData) . Contohnya pada kode berikut, tuple names
ditambahi element baru dengan posisi di awal.
Operasi ('Jean Kirstein', *names) menghasilkan data tuple karena disitu
names = [
'Mikasa Ackerman',
'Armin Arlert',
'Eren Yeager',
'Zeke Yeager',
'Reiner Braun',
'Annie Leonhart'
]
names = ('Jean Kirstein', *names)
print(names)
# output ↓
#
# ('Jean Kirstein',
# 'Mikasa Ackerman',
# 'Armin Arlert',
# 'Eren Yeager',
# 'Zeke Yeager',
# 'Reiner Braun',
# 'Annie Leonhart')
literal tuple digunakan ( ( ) ). Selain tuple, operasi ini bisa didesain untuk
ditampung ke tipe data kolektif lainnya, misalnya list dan set .
â—‰ Append element
Append yaitu operasi penambahan element baru di posisi akhir data.
Penulisan syntax-nya mirip seperti prepend element namun dituliskan terbalik,
seperti ini (*oldData, newElement) .
names = ('Jean Kirstein', *names)
print(f"type: {type(names).__name__}")
# output ➜ type: tuple
names2 = ['Jean Kirstein', *names]
print(f"type: {type(names2).__name__}")
# output ➜ type: list
names3 = {'Jean Kirstein', *names}
print(f"type: {type(names3).__name__}")
# output ➜ type: set
names = [
'Mikasa Ackerman',
'Armin Arlert',
'Eren Yeager',
'Zeke Yeager',
'Reiner Braun',
'Annie Leonhart'
]
names = ('Jean Kirstein', *names)
print(names)
# output ↓
#
# ('Jean Kirstein',
â—‰ Append dan prepend element bersamaan
Operasi append dan prepend bisa dilakukan secara bersamaan.
names = [
'Mikasa Ackerman',
'Armin Arlert',
'Eren Yeager',
'Zeke Yeager',
'Reiner Braun',
'Annie Leonhart'
]
names = ('Jean Kirstein', *names)
print(names)
# output ↓
#
# ('Jean Kirstein',
# 'Mikasa Ackerman',
# 'Armin Arlert',
# 'Eren Yeager',
# 'Zeke Yeager',
# 'Reiner Braun',
# 'Annie Leonhart')
names = [*names, 'Connie Springer']
print(names)
# output ↓
#
# ['Jean Kirstein',
# 'Mikasa Ackerman',
# 'Armin Arlert',
# 'Eren Yeager',
# 'Zeke Yeager',
# 'Reiner Braun',
# 'Annie Leonhart',
# 'Connie Springer']
Perlu diingat, bahwa tipe data set tidak menjamin elemennya tersimpan
secara urut. Jadinya sewaktu diakses atau di-print bisa saja urutan
elemen berubah.
Pembahasan detail mengenai set ada di chapter Set
A.32.3. Pemanfaatan teknik unpacking
pada argument parameter
Tenik unpacking umum dimanfaatkan pada penyisipan data argument
parameter pemanggilan fungsi/method. Contoh aplikasinya bisa dilihat pada
kode berikut, dimana ada fungsi bernama show_biography() yang akan
dipanggil beberapa kali dengan cara pemanggilan berbeda satu sama lain.
• Pemanggilan ke-1: Argument parameter disisipkan menggunakan cara
normal.
• Pemanggilan ke-2: Argument pertama diisi secara normal, sedangkan
def show_biography(id, name, occupation, gender):
print(f"id: {id}")
print(f"name: {name}")
print(f"occupation: {occupation}")
print(f"gender: {gender}")
id = 'U0001'
name = 'Mikasa Ackerman'
occupation = 'Paradise Survey Corps'
gender = 'female'
show_biography(id, name, occupation, gender)
parameter kedua dan seterusnya disisipkan menggunakan metode
unpacking.
• Pemanggilan ke-3: metode unpacking juga digunakan tetapi untuk
argument ke-1 hingga ke-3 (sesuai dengan jumlah element user3_data ).
• Pemanggilan ke-4: Metode unpacking digunakan pada penyisipan
argument parameter ke-2 dan ke-3 saja.
A.32.4. Packing-unpacking item
dictionary
â—‰ Operasi unpack pada dictionary
Operasi unpack pada tipe data dictionary mengembalikan hanya nilai key-nya
saja dalam bentuk list . Nilai value-nya tidak ikut didistribusikan.
user2_id = 'U0002'
user2_data = ('Annie Leonhart', 'Marley Warrior', 'female')
show_biography(user2_id, *user2_data)
user3_data = ('U0003', 'Levi Ackerman', 'Paradise Survey Corps')
show_biography(*user3_data, 'male')
user4_data = ('Hange Zoë', 'Paradise Survey Corps')
show_biography('U0004', *user4_data, 'male')
user_id, *user_data = data
â—‰ Operasi append & prepend pada dictionary
Di atas telah dicontohkan kalau tanda * bisa digunakan untuk menampung
sisa pendistribusian keys dictionary (ingat, hanya keys-nya saja!), maka berarti
tidak bisa digunakan untuk operasi append dan prepend dictionary.
Cara append/prepend dictionary yaitu dengan memanfaatkan tanda ** .
Contoh penerapannya bisa dilihat pada kode berikut:
data = {
'name': 'Mikasa Ackerman',
}
print(data)
# output ➜ { 'name': 'Mikasa Ackerman' }
data = {
**data,
'occupation': 'Paradise Survey Corps',
}
print(data)
# output ➜ { 'name': 'Mikasa Ackerman', 'occupation': 'Paradise Survey
Corps' }
data = {
'id': 'U0001',
**data,
'gender': 'female',
}
print(data)
# output ↓
#
# {
# 'id': 'U0001',
# 'name': 'Mikasa Ackerman',
# 'occupation': 'Paradise Survey Corps',
# 'gender': 'female'
â—‰ Pemanfaatan teknik unpacking dictionary pada
argument parameter
Tanda ** bisa digunakan untuk operasi unpack dictionary sebagai argument
pemanggilan fungsi. Key dictionary menjadi nama parameter, dan value
dictionary menjadi nilai argument parameter.
Teknik ini bisa dilakukan dengan ketentuan nama parameter fungsi yaitu
sama dengan key dictionary.
def show_biography(id, name, occupation, gender):
print(f"id: {id}")
print(f"name: {name}")
print(f"occupation: {occupation}")
print(f"gender: {gender}")
data1 = {
'id': 'U0001',
'gender': 'female',
'name': 'Mikasa Ackerman',
'occupation': 'Paradise Survey Corps',
}
show_biography(**data1)
# output ↓
#
# id: U0001
# name: Mikasa Ackerman
# occupation: Paradise Survey Corps
# gender: female
data2 = {
'gender': 'female',
'name': 'Mikasa Ackerman',
'occupation': 'Paradise Survey Corps',
}
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../pack-
unpack-elements
â—‰ Chapter relevan lainnya
• List
• Tuple
• Set
â—‰ Referensi
• https://peps.python.org/pep-0448/
A.33. Python OOP ➜ Class
& Object
Python mendukung paradigma pemrograman berbasis objek (OOP) melalui
implementasi Class dan Object API. Pada bab ini, kita akan mempelajari konsep
dasar beserta penerapannya.
Pembahasan OOP pada ebook ini lebih fokus pada pengaplikasiannya di
Python. Jadi pembahasan teorinya tidak terlalu banyak.
A.33.1. Pengenalan Class
Class yaitu blueprint untuk membuat variabel, class bisa diartikan juga
sebagai tipe data. Di Python, setiap data pasti memiliki tipe data yang tipe
tersebut merupakan yaitu class. Sebagai contoh:
• Data string "noval" tipe datanya yaitu class str
• Data numerik 24 tipe datanya yaitu class int
• Data floating point 3.1567 tipe datanya yaitu class float
• ... dan lainnya
Selain menggunakan class-class yang tersedia di Python Standard Library, kita
bisa membuat custom class via keyword class . Topik custom class ini
merupakan inti pembahasan chapter ini.
Custom class (atau cukup class) digunakan untuk membuat variabel object.
Cara termudah memahami hubungan antara class dan objek yaitu melalui
analogi berikut: dimisalkan ada sebuah class bernama Car , class tersebut
kemudian digunakan untuk mendeklarasikan tiga buah variabel bernama
bmw_m3_gtr , mazda_rx8 , dan audi_le_mans . Ketiga object tipe datanya
yaitu class Car .
Deklarasi class dilakukan dengan menggunakan keyword class diikuti oleh
nama class yang diinginkan. Lalu di dalam block class tersebut perlu
dideklarasikan suatu fungsi dengan skema __init__(self) dengan isi body
fungsi yaitu deklarasi attribute. Contohnya:
Pada contoh di atas, class Car memiliki tiga attribute: name , manufacturer ,
dan year . Nantinya, variabel objek yang dibuat dari class tersebut akan
memiliki tiga atribut sesuai dengan yang dideklarasikan.
class Car:
def __init__(self):
self.name = ""
self.manufacturer = ""
self.year = 0
Fungsi __init__(self) disebut dengan method konstruktor.
Pembahasan detail mengenai konstruktor ada di chapter Class ➜
Constructor
â—‰ Deklarasi class tanpa attribute
Dengan menggunakan keyword pass , suatu class bisa dideklarasikan tanpa
memiliki attribute. Contoh penerapannya:
Atau dapat juga ditulis seperti ini:
Pembahasan detail mengenai keyword pass ada di chapter Function
section Keyword pass
A.33.2. Naming convention class
Berdasarkan dokumentasi PEP 8 – Style Guide for Python Code, disarankan
untuk menulis nama class dalam bentuk TitleCase, contoh: FavoriteFood .
class Car:
def __init__(self):
pass
class Car:
pass
A.33.3. Pembuatan Instance object
Object (atau instance object) yaitu variabel yang dibuat dari class. Cara
pembuatan object yaitu dengan memanggil nama class diikuti oleh tanda
kurung fungsi () (seperti pemanggilan fungsi). Statement tersebut
mengembalikan nilai balik berupa object baru yang bertipe data sesuai dengan
class yang digunakan.
Ada banyak istilah lain yang merujuk pada variabel objek, seperti
instance, instance variable, instance object, dan lainnya. Namun tidak
usah bingung, karena semua istilah tersebut memiliki makna yang sama.
Contoh deklarasi class Person beserta pembuatan variabel object bernama
person1 :
Penjelasan:
• Class Person dideklarasikan dengan dua atribut, yaitu first_name dan
last_name .
• Class Person dipanggil seperti pemanggilan fungsi (menggunakan sintaks
Person() ) dan menghasilkan variabel objek baru bertipe Person , yang
class Person:
def __init__(self):
self.first_name = ""
self.last_name = ""
person1 = Person()
print(f"instance object: {person1}")
print(f"type: {type(person1)}")
kemudian ditampung dalam variabel person1 .
Output program:
Dari output program, terlihat bahwa tipe data variabel person1 yaitu class
__main__.Person . Syntax tersebut artinya yaitu tipe data class Person
yang deklarasinya ada di file __main__ atau file entrypoint eksekusi program.
Contoh lainnya pembuatan instance object dari class class Car :
A.33.4. Instance Attribute
Salah satu property class yaitu attribute. Attribute yaitu variabel yang
terasosiasi dengan class, jadi dalam pengaksesannya harus dilakukan melalui
class dan/atau instance object.
Sebelumnya, kita telah membuat class bernama Car yang memiliki 3
attribute:
class Car:
def __init__(self):
self.name = ""
self.manufacturer = ""
self.year = 0
car1 = Car()
car2 = Car()
car3 = Car()
• name untuk menyimpan informasi nama/seri mobil
• manufacturer untuk menyimpan informasi manufaktur atau pembuat
mobil
• year untuk menyimpan informasi tahun rilis mobil
Attribute sebenarnya ada 2 jenis, yaitu instance attribute dan class attribute.
Yang sedang kita pelajari di chapter ini yaitu instance attribute.
Perbedaan mendetail antara instance attribute vs class attribute ada di
chapter Class ➜ Class Attribute & Method
Cara deklarasi instance attribute mirip dengan deklarasi variabel,
perbedaannya pada penulisannya diawali dengan self. . Selain itu
deklarasinya harus berada di dalam body fungsi __init__(self) .
Untuk mengakses instance attribute, kita dapat melakukannya melalui variabel
objek yang dibuat dari class dengan notasi pengaksesan:
<object>.<attribute> .
Contoh:
class Car:
def __init__(self):
self.name = ""
self.manufacturer = ""
self.year = 0
car1 = Car()
print(f"car1 name: {car1.name}")
print(f"car1 manufacturer: {car1.manufacturer}")
print(f"car1 year: {car1.year}")
Saat di-print, dapat dilihat bahwa semua nilai instance attribute milik car1
sesuai dengan nilai default yang ditentukan saat deklarasi attribute dalam
fungsi __init__(self) , yaitu: string kosong "" untuk attribute name &
manufacturer , dan 0 untuk attribute year .
Langkah berikutnya, mari buat tiga buah variabel object dari class Car dan isi
instance attribute-nya dengan suatu nilai. Tiga variabel yang perlu dibuat
yaitu bmw_m3_gtr , mazda_rx8 , dan audi_le_mans .
Bentuk penerapannya dalam kode Python kurang lebih seperti ini:
Jalankan program untuk melihat outputnya:
Class jika dilihat dari strukturnya memiliki kesamaan dengan dictionary.
Class mempunyai attribute name dan value, sementara dictionary
car1 = Car()
car1.name = "M3 GTR"
car1.manufacturer = "BMW"
car1.year = 2001
print(f"Car name: {car1.manufacturer} {car1.name}\nYear released:
{car1.year}\n")
car2 = Car()
car2.name = "RX-8"
car2.manufacturer = "Mazda"
car2.year = 2002
print(f"Car name: {car2.manufacturer} {car2.name}\nYear released:
{car2.year}\n")
car3 = Car()
car3.name = "Le Mans Quattro"
car3.manufacturer = "Audi"
car3.year = 2003
print(f"Car name: {car3.manufacturer} {car3.name}\nYear released:
{car3.year}\n")
memiliki key dan value.
Perbedaan utama dari keduanya yaitu pada dictionary key-nya bisa
dikelola secara dinamis, sedangkan pada class nama attribute-nya
yaitu fixed.
A.33.5. Pengecekan instance object
Fungsi isinstance() cukup berguna untuk mengecek apakah suatu instance
object tipe datanya yaitu class tertentu atau class yang meng-inherit class
tertentu.
Misalnya, variabel car1 di atas kita cek apakah tipe data nya yaitu class
Car . Cara penggunaannya cukup panggil fungsi isinstance() lalu sertakan
variabel object yang ingin dicek sebagai argument pertama dan tipe data class
sebagai argument ke-dua.
A.33.6. Class turunan object
Setiap class yang ada di Python baik itu class bawaan Python Standard Library
ataupun custom class, secara otomatis yaitu turunan dari class bernama
car1 = Car()
car1.name = "M3 GTR"
car1.manufacturer = "BMW"
car1.year = 2001
if isinstance(car1, Car):
print(f"car1 class is Car")
# output ➜ car1 class is Car
object .
Jadi, class str , float , custom class Car yang telah dibuat, dan lainnya,
kesemua class-nya yaitu turunan dari class object .
Silakan cek menggunakan fungsi isinstance() untuk membuktikannya:
Pembahasan detail mengenai class inheritance ada di chapter OOP ➜
Class Inheritance
data1 = Car()
if isinstance(data1, Car):
print(f"data1 class inherit from Car")
if isinstance(data1, object):
print(f"data1 class inherit from object")
data2 = "Noval Agung"
if isinstance(data2, str):
print(f"data2 class inherit from str")
if isinstance(data2, object):
print(f"data2 class inherit from object")
# output ↓
#
# data1 class inherit from Car
# data1 class inherit from object
# data2 class inherit from str
# data2 class inherit from object
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../class-
object
â—‰ Chapter relevan lainnya
• OOP ➜ Instance Method
• OOP ➜ Constructor
• OOP ➜ Property Visibility
• OOP ➜ Instance Attribute & Class Attribute
• OOP ➜ Class Method
• OOP ➜ Static Method
• OOP ➜ Class Inheritance
• OOP ➜ Abstract Method
• OOP ➜ Data Class
â—‰ Referensi
• https://docs.python.org/3/tutorial/classes.html
A.34. Python OOP ➜
Instance Method
Jika attribute yaitu variabel yang berasosiasi dengan class, maka method
yaitu fungsi yang berasosiasi dengan class.
Python mengenal 3 jenis method yaitu instance method, class method, dan
static method. Chapter ini fokus ke pembahasan tentang instance method saja.
• Pembahasan detail mengenai class method ada di chapter OOP ➜
Class Method
• Pembahasan detail mengenai static method ada di chapter OOP ➜
Static Method
A.34.1. Pengenalan Instance Method
Instance method memiliki beberapa karakteristik jika dilihat dari syntax-nya:
1. Deklarasinya di dalam block class
2. Parameter pertamanya yaitu self
3. Method diakses menggunakan notasi <object>.<method>()
Dalam praktik kali ini, kita akan melanjutkan praktek class Car yang telah
dibuat di chapter sebelumnya.
Ok, pertama-tama siapkan deklarasi class Car dengan 4 buah property yaitu
name , manufacturer , year , dan description . Kemudian dari class
tersebut, buat 3 buah instance object baru, lalu print data attribute tiap
variabel.
class Car:
def __init__(self):
self.name = ""
self.manufacturer = ""
self.year = 0
self.description = ""
all_cars = []
car1 = Car()
car1.name = "M3 GTR"
car1.manufacturer = "BMW"
car1.year = 2001
car1.description = "Best car in NFS Most Wanted"
all_cars.append(car1)
car2 = Car()
car2.name = "RX-8"
car2.manufacturer = "Mazda"
car2.year = 2002
car2.description = "Best car in NFS Underground 2"
all_cars.append(car2)
car3 = Car()
car3.name = "Le Mans Quattro"
car3.manufacturer = "Audi"
car3.year = 2003
car3.description = "Best car in NFS Carbon"
all_cars.append(car3)
for c in all_cars:
print(f"Car name: {c.manufacturer} {c.name}")
print(f"Description: {c.description}")
print(f"Year released: {c.year}")
print()
Output program:
Setelah itu, modifikasi class Car dengan menambahkan instance method
baru bernama info() . Melalui method ini, value attribute di-print.
Pada bagian blok kode perulangan, ganti tiga baris statement print dengan
pemanggilan method info() .
• Before:
class Car:
def __init__(self):
self.name = ""
self.manufacturer = ""
self.year = 0
self.description = ""
def info(self):
print(f"Car name: {self.manufacturer} {self.name}")
print(f"Description: {self.description}")
print(f"Year released: {self.year}")
• After:
Jalankan program dan lihat outputnya, pasti sama persis dengan program
sebelumnya.
A.34.2. Variabel self
Salah satu aturan pada instance method yaitu fungsi harus memiliki
parameter pertama bernama self . Parameter tersebut wajib ada saat
deklarasi, dan tidak boleh diisi argument saat pemanggilan. Jika dipaksa diisi
dengan argument, maka pasti muncul error.
for c in all_cars:
print(f"Car name: {c.manufacturer} {c.name}")
print(f"Description: {c.description}")
print(f"Year released: {c.year}")
print()
for c in all_cars:
c.info()
print()
Parameter self bisa disebut dengan parameter implicit atau implisit
karena kita tidak berinteraksi secara langsung saat pengisian nilai. Nilai
self otomatis terisi saat pemanggilan instance method via instance
object.
Dimisalkan lagi, parameter self tidak ditulis saat deklarasi instance method,
hasilnya juga error.
Parameter self merupakan variabel yang merepresentasikan suatu object
atau instance. Melalui variabel ini, kita dapat mengakses instance attribute
maupun instance method (selama property tersebut masih dalam satu class).
Pada contoh sebelumnya, terlihat bagaimana aplikasi dari variabel self
untuk mengakses attribute:
class Car:
def __init__(self):
self.name = ""
self.manufacturer = ""
self.year = 0
Selain untuk mengakses nilainya, dari variabel self suatu attribute juga
dapat diubah nilainya, sebagaimana pada contoh berikut nilai attribute year
dan description diubah melalui pemanggilan instance method
set_details() .
Karena instance method wajib dideklarasikan dengan parameter pertama
self , maka parameter untuk menampung data year dan description
ditulis sebagai parameter setelahnya.
Setelah itu, ubah statement pengisian nilai year dan description
menggunakan method set_details() seperti ini:
class Car:
def __init__(self):
self.name = ""
self.manufacturer = ""
self.year = 0
self.description = ""
def info(self):
print(f"Car name: {self.manufacturer} {self.name}")
print(f"Description: {self.description}")
print(f"Year released: {self.year}")
def set_details(self, year, description):
self.year = year
self.description = description
all_cars = []
car1 = Car()
car1.name = "M3 GTR"
car1.manufacturer = "BMW"
car1.set_details(2001, "Best car in NFS Most Wanted")
Pada pemanggilan method set_details() object car1 :
• Argument 2001 ditampung oleh parameter year
• Argument Best car in NFS Most Wanted ditampung oleh parameter
description .
A.34.3. Naming convention method &
param
Mengacu pada dokumentasi PEP 8 – Style Guide for Python Code, nama
method dianjurkan untuk ditulis menggunakan snake_case (seperti fungsi).
Contohnya bisa dilihat pada method get_name() berikut:
Sedangkan aturan penulisan nama parameter/argument yaitu sama seperti
nama variabel, yaitu menggunakan snake_case juga. Misalnya:
class FavoriteFood:
def __init__(self):
self.name = ""
def print_name(self):
print(self.name)
def get_name(self) -> str:
return self.name
class FavoriteFood:
def __init__(self):
self.name = ""
def print_name(self):
print(self.name)
A.34.4. Pengaksesan instance method
dari class
Sebenarnya ada dua cara untuk mengakses instance method:
1. Lewat instance object, contohnya seperti kode car1.set_details() yang
telah dipraktekan.
2. Lewat class dengan ketentuan dalam pemanggilan methodnya, parameter
pertama harus diisi dengan instance object.
Silakan perhatikan kode berikut agar lebih jelas mengenai cara ke-2.
class FavoriteFood:
def __init__(self):
self.name = ""
def print_name(self):
print(self.name)
def get_name(self) -> str:
return self.name
def set_name(self, name):
self.name = name
food1 = FavoriteFood()
food1.set_name("Pizza")
food1.print_name()
print(food1.get_name())
FavoriteFood.set_name(food1, "Burger")
FavoriteFood.print_name(food1)
print(food1.get_name())
Pada kode di atas, food1 merupakan instance object dari class
FavoriteFood . Lewat object tersebut 3 buah method ini dipanggil:
set_name() , print_name() , dan get_name() .
Kemudian dibawahnya lagi, method set_name() dan print_name() dipanggil
ulang namun dengan syntax yang berbeda. Method dipanggil dari class dan
argument parameter parameter pertamanya diisi instance object food1 .
Penulisan pemanggilan method dari class seperti itu yaitu diperbolehkan dan
ekuivalen dengan pemanggilan instance method via instance object.
Perbedaannya:
• Pada pengaksesan instance method via instance object, parameter self
tidak perlu diisi.
• Pada pengaksesan instance method via class, parameter self harus
selalu diisi dengan instance object.
Agar makin jelas, silakan lihat tabel berikut. Contoh di kolom pertama yaitu
ekuivalen dengan contoh di kolom ke 2.
Via instance object Via class
food1.set_name("Pizza") FavoriteFood.set_name(food1, "Pizza")
food1.print_name() FavoriteFood.print_name(food1)
food1.get_name() FavoriteFood.get_name(food1)
A.34.5. Pengaksesan method dari
method lain
Lewat variabel self tidak hanya instance attribute yang dapat diakses,
melainkan semua jenis property (termasuk instance method). Pada contoh
berikut, di dalam method info() terdapat statement pemanggilan method
yaitu get_name() .
Instance method get_name() mengembalikan data string berisi kombinasi
attribute manufacturer dan name .
A.34.6. Argument method: positional,
class Car:
def __init__(self):
self.name = ""
self.manufacturer = ""
self.year = 2023
self.description = ""
def set_details(self, year, description):
self.year = year
self.description = description
def get_name(self):
return f"{self.manufacturer} {self.name}"
def info(self):
print(f"Car name: {self.get_name()}")
print(f"Description: {self.description}")
print(f"Year released: {self.year}")
optional, keyword arg
Aturan-aturan dalam deklarasi parameter dan pengisian argument fungsi juga
berlaku pada method, diantaranya:
• Parameter method yang memiliki default value:
• Positional argument:
• Optional argument:
• Keyword argument:
class Car:
# ...
def set_details(self, year = 2002, description = ""):
self.year = year
self.description = description
# ...
car1 = Car()
car1.name = "M3 GTR"
car1.manufacturer = "BMW"
car1.set_details(2001, "Best car in NFS Most Wanted")
car2 = Car()
car2.name = "RX-8"
car2.manufacturer = "Mazda"
car2.set_details(description="Best car in NFS Underground 2")
A.34.7. Argument method: args & kwargs
Sama seperti fungsi, method juga bisa berisi parameter args maupun kwargs.
Contoh penerapan kwargs pada method bisa dilihat di program berikut.
Modifikasi program di atas, pada method set_details() ubah isinya menjadi
seperti ini:
Melalui parameter **param, kita dapat menentukan attribute mana yang akan
diisi nilainya secara dinamis. Sekarang panggil methodnya lalu isi sesuai
kebutuhan, misalnya:
car3 = Car()
car3.name = "Le Mans Quattro"
car3.manufacturer = "Audi"
car3.set_details(description="Best car in NFS Carbon", year=2003)
class Car:
# ...
def set_details(self, **param):
for key in param:
if key == "name":
self.name = param[key]
if key == "manufacturer":
self.manufacturer = param[key]
if key == "year":
self.year = param[key]
if key == "description":
self.description = param[key]
# ...
Output program:
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../instance-
method
â—‰ Chapter relevan lainnya
• OOP ➜ Class & Object
• OOP ➜ Constructor
• OOP ➜ Class Method
• OOP ➜ Static Method
• OOP ➜ Abstract Method
• OOP ➜ Data Class
car4 = Car()
car4.set_details(name="Chiron Sport", manufacturer="Bugatti")
car4.set_details(year=2021)
car4.set_details(description="Best car in NFS Unbound")
car4.info()
â—‰ TBA
• method & lambda
• method & closure
â—‰ Referensi
• https://docs.python.org/3/tutorial/classes.html
A.35. Python OOP ➜
Constructor
Constructor/konstruktor yaitu salah satu topik penting dalam pemrograman
berbasis object (OOP). Konstruktor sendiri yaitu fungsi khusus yang dipanggil
saat pembuatan object dilakukan dari suatu class.
Pada chapter ini kita akan belajar tentang konstruktor dan apa saja yang bisa
dilakukan didalamnya.
A.35.1. Pengenalan constructor
Di bahasa yang mengadopsi konsep OOP, setiap class memiliki default
constructor. Sebagai contoh pada statement pembuatan object bertipe class
Car , syntax Car() digunakan dan syntax tersebut merupakan contoh
penerapan pengaksesan konstruktor.
Sederhananya, konstruktor yaitu kelas yang dipanggil seperti fungsi
dengan notasi <Class>() .
Agar makin jelas, silakan praktekan kode sederhana berikut:
class Mountain:
pass
mount_everest = Mountain()
print(mount_everest)
# output ➜ <__main__.Mountain object at 0x0000019118A13390>
Class Mountain dideklarasikan tanpa berisi apapun (oleh karena itu keyword
pass digunakan). Kelas tersebut bisa digunakan untuk membuat variabel
object mount_everest dan mount_kilimanjaro dengan cara memanggil
konstruktornya, yaitu Mountain() .
Dalam deklarasi class yang memiliki attribute, constructor wajib di-replace
(atau istilah OOP-nya yaitu di-override) dengan custom constructor yang
didalamnya berisi deklarasi instance attribute.
Sebagai contoh, class Mountain yang telah dibuat dimodifikasi dengan
ditambahkan tiga buah instance attribute didalamnya yaitu name , region ,
dan elevation .
class Mountain:
def __init__(self):
self.name = ""
self.region = ""
self.elevation = 0
def info(self):
print(f"name: {self.name}")
print(f"region: {self.region}")
print(f"elevation: {self.elevation}m")
mount_everest = Mountain()
mount_everest.name = "Everest"
mount_everest.region = "Asia"
mount_everest.elevation = 8848
mount_everest.info()
# output ↓
#
# name: Everest
# region: Asia
# elevation: 8848m
mount_kilimanjaro = Mountain()
Pada contoh di atas, konstruktor __init__(self) meng-override default
constructor milik class Mountain dan digunakan untuk deklarasi instance
attribute.
A.35.2. Constructor dengan custom
param
Konstruktor dapat didesain untuk memiliki parameter, dan metode ini sangat
umum diterapkan.
Sebagai contoh, pada kode berikut class Mountain konstruktornya
dimodifikasi agar bisa menampung data argument untuk parameter name ,
region , dan elevation .
class Mountain:
def __init__(self, name, region, elevation):
self.name = name
self.region = region
self.elevation = elevation
def info(self):
print(f"name: {self.name}")
print(f"region: {self.region}")
print(f"elevation: {self.elevation}m")
mount_everest = Mountain("Everest", "Asia", 8848)
mount_everest.info()
# output ↓
#
# name: Everest
# region: Asia
# elevation: 8848m
mount_kilimanjaro = Mountain("Kilimanjaro", "Africa", 5895)
Seperti halnya method, parameter pertama konstruktor harus self . Dari sini
bisa disimpulkan berarti penambahan parameter harus dituliskan setelah
self . Bisa dilihat di deklarasi konstruktor class Mountain , disitu ada tiga
buah parameter dideklarasikan setelah self .
A.35.3. Constructor overloading
Overloading merupakan istilah OOP untuk pembuatan banyak konstruktor
dengan jumlah dan tipe parameter berbeda.
Python tidak menyediakan API untuk penerapan constructor overloading,
namun pada praktiknya bisa dicapai dengan hack, misalnya menggunakan
opsional/keyword parameter, atau menggunakan *args/**kwargs.
• Pembahasan detail mengenai opsional / keyword parameter ada di
chapter Function ➜ Positional, Optional, Keyword Arguments
• Pembahasan detail mengenai args dan kwargs ada di chapter
Function ➜ Args & Kwargs
Contoh constructor overloading menggunakan opsional parameter:
class Mountain:
def __init__(self, name = "", region = "", elevation = 0):
self.name = name
self.region = region
self.elevation = elevation
def info(self):
print(f"name: {self.name}")
print(f"region: {self.region}")
print(f"elevation: {self.elevation}m")
Penjelasan:
• Konstruktor class Mountain didesain memiliki 3 buah parameter yang
kesemuanya memiliki nilai default.
• Variabel object mount_everest dibuat dengan dengan mengisi kesemua
parameter konstruktornya.
• Variabel object mount_kilimanjaro dibuat dengan dengan hanya mengisi
dua parameter pertama konstruktor.
• Variabel object mount_aconcagua dibuat dengan dengan mengisi
parameter name dan elevation saja pada pemanggilan konstruktor.
• Variabel object mount_kosciuszko dibuat dengan tanpa diikuti dengan
argument parameter.
Silakan coba explore dengan mempraktekan penggunaan *args / **kwargs
pada konstruktor.
A.35.4. Constructor dengan return type
None
Constructor dipanggil saat inisialisasi object, maka bisa dibilang bahwa
constructor tersebut selalu mengembalikan tipe data bertipe class dimana
constructor tersebut dideklarasikan.
Dalam pembuatan konstruktor, tidak perlu menuliskan return type maupun
return statement.
Meski demikian, sebenarnya ada 1 lagi bentuk penulisan konstruktor, yaitu
dengan ditambahkan tipe data None dibelakangnya, dan ini diperbolehkan.
Contohnya:
Kode di atas yaitu ekuivalen dengan kode berikut:
Catatan chapter 📑
â—‰ Source code praktik
github.com/novalagung/dasarpemrogramanpython-example/../class-
constructor
â—‰ Chapter relevan lainnya
• OOP ➜ Class & Object
• OOP ➜ Instance Method
• OOP ➜ Class Method
• OOP ➜ Static Method
• OOP ➜ Abstract Method
• OOP ➜ Data Class
class Mountain:
def __init__(self, name = "", region = "", elevation = 0) -> None:
self.name = name
self.region = region
self.elevation = elevation
class Mountain:
def __init__(self, name = "", region = "", elevation = 0):
self.name = name
self.region = region
self.elevation = elevation
â—‰ Referensi
• https://docs.python.org/3/tutorial/classes.html
A.36. Python OOP ➜
Property Visibility
Visibility atau privacy dalam konteks OOP merujuk pada penentuan apakah
property (baik itu attribute atau method) dapat diakses secara public atau
hanya bisa diakses dari dalam class (private).
Di bab ini, kita akan membahas implementasinya di Python.
A.36.1. Pengenalan visibility/privacy
Python, dari segi API kode yang tersedia, sebenarnya tidak secara eksplisit
mendukung implementasi visibility property instance class. Semua attribute
dan method secara default bersifat public di Python.
Property public berarti property tersebut dapat diakses melalui instance
object atau dari luar block class .
Meskipun demikian, ada beberapa praktik umum untuk menandai bahwa suatu
method atau attribute yaitu private. Salah satunya yaitu menggunakan
teknik name mangling, di mana nama attribute atau method ditulis dengan
diawali 2 karakter underscore, misalnya __name , __list_items , dan
sejenisnya.
Penamaan tersebut tidak benar-benar membuat visibility property menjadi
private, melainkan hanya sebagai penanda saja. Property sendiri tetap bisa
diakses secara publik.
Mari kita coba praktekan. Pertama siapkan project baru deng