Anda di halaman 1dari 95

Pengecekan Style Guide PEP8

Sampai dengan saat ini, Anda tentu sudah menuliskan kode pemrograman
Python cukup banyak, termasuk di antaranya kode yang Anda tulis
mengalami kesalahan sintaksis atau indentasi. Lalu bagaimana agar ke
depan bisa mencegah hal tersebut terjadi?

Bergantung dengan editor yang Anda gunakan untuk menulis kode Python,
dimana salah satu fitur yang memudahkan penulisan, sehingga menghemat
banyak waktu untuk memformat kode sesuai arahan gaya penulisan (style
guide) PEP8 dan mengecek akan kemungkinan terjadinya kesalahan (error)
pada kode yang ditulis. Untuk itu akan dijelaskan sejumlah aplikasi yang
dapat Anda gunakan, dengan memanggil perintah atau sebaiknya
diintegrasikan ke editor kode yang Anda pakai, dengan tujuan untuk
membantu Anda mengecek kemungkinan kesalahan dan kesesuaian dengan
PEP8.

Lint
Lint adalah proses pengecekan kode atas kemungkinan terjadi kesalahan
(error), termasuk dalam proses ini adalah mengecek kesesuaian terhadap
arahan gaya penulisan kode (style guide) PEP8. Aplikasi yang digunakan
untuk proses ini disebut linter. Integrasi linter dengan editor kode Anda akan
membuat efisien dalam menulis kode Python. Pertimbangan ini karena
keluaran dari aplikasi linter hanya berupa teks singkat berupa keterangan
dan kode Error atau Warning atau Kesalahan Konvensi Penamaan (Naming
Conventions), akan dicontohkan selanjutnya.

Dengan lint atau linting akan meminimalkan kode Anda mengalami error,


sebagai contoh salah satunya karena kesalahan indentasi di Python.
Sebelum kode Anda diprotes oleh interpreter Python dengan
IndentationError, lint akan memberitahukannya lebih dahulu ke Anda.

Berikut akan dibahas 3 jenis aplikasi linter, silakan dicermati dahulu, tidak
harus semuanya diinstal/dicoba, hanya paket yang menurut Anda sesuai
kebutuhan saja yang digunakan. Hasil keluarannya mungkin mirip, tapi pada
kondisi tertentu akan ada keluaran atau fitur yang mungkin sesuai dengan
kebutuhan Anda menulis kode.
Pycodestyle (sebelumnya bernama pep8)

Pycodestyle adalah aplikasi open source (berlisensi MIT/Expat) untuk


membantu mengecek kode terkait gaya penulisan kode dengan konvensi
PEP8.

Untuk instalasi menggunakan manajer paket pip sebagai berikut : pip install
pycodestyle.

Pylint

Pylint adalah aplikasi open source (berlisensi GPL v2) untuk melakukan


analisis kode Python, mengecek untuk kesalahan (error) pemrograman,
memaksakan standar penulisan kode dengan mengecek penulisan kode
yang tidak baik, serta memberikan saran untuk refactoring sederhana.

Untuk instalasi menggunakan manajer paket pip sebagai berikut : pip install
pylint.

Flake8

Flake8 adalah aplikasi open source (berlisensi MIT) yang membungkus


sejumlah kemampuan aplikasi lain seperti pycodestyle, pyflakes, dan
sejumlah (skrip/fitur) lainnya.

Untuk instalasi menggunakan manajer paket pip sebagai berikut : pip install
flake8

Selanjutkan kita akan membahas sebuah contoh kode class sederhana yang
akan diproses lint, misal disimpan dalam sebuah file kal.py. Perhatikan di
baris 5, kolom 5 dan kolom 10. Ditulis berjeda antar huruf agar mudah dicek
penomoran kolomnya.

Jika diproses dengan pycodestyle. Menunjukkan error (E301) di baris 5


kolom 5, serta error (E112) di baris 7 kolom 5.
1. pycodestyle kal.py

2. kal.py:5:5: E301 expected 1 blank line, found 0

3. kal.py:7:5: E112 expected an indented block

Jika diproses dengan pylint. Menunjukkan error (E0001) di baris 7 kolom 10.
1. pylint kal.py

2. ************* Module kal

3. kal.py:7:10: E0001: invalid syntax (<unknown>, line 7) (syntax-error)

Jika diproses dengan flake8. Menunjukkan error (E301) di baris 5 kolom 5,


error (E112) di baris 7 kolom 5, serta error (E999) di baris 7 kolom 10.
1. flake8 kal.py
2. kal.py:5:5: E301 expected 1 blank line, found 0

3. kal.py:7:5: E112 expected an indented block

4. kal.py:7:10: E999 IndentationError: expected an indented block

Setelah kodenya diperbaiki, kali ini diubah secara manual dengan


mengetikkan, pada pembahasan berikutnya mengenai memformat kode akan
menangani hal ini dengan otomatis.
1. """kalkulator"""

2.  

3. class Kalkulator:

4.     """kalkulator tambah kurang"""

5.     def __init__(self, _i):

6.         self.i = _i

7.  

8.     def tambah(self, _i): return self.i + _i

9.  

10.     def kurang(self, _i):

11.         return self.i - _i

Kemudian diproses kembali dengan pycodestyle dan flake8 tidak


memunculkan pesan lagi.

Diproses dengan pylint menghasilkan peringatan tentang lebih dari satu


pernyataan (statement) dalam satu baris, serta kedua fungsi belum
dilengkapi dengan dokumentasi. Hasilnya pylint memberikan skor 5.71 dari
10.

Memformat Kode
Jika proses lint atau linting hanya melakukan pengecekan, terkait arahan
gaya penulisan kode Anda bisa menggunakan aplikasi tambahan untuk
memformat kode agar sesuai PEP8. Sehingga untuk Anda yang
menggunakan editor kode yang sangat ringan dan ringkas fitur sekalipun,
misalnya tanpa fasilitas lint, tetap bisa menghasilkan kode sesuai konvensi
PEP8.

Proses memformat kode dengan menggunakan aplikasi, cukup sederhana,


setelah melakukan instalasi, akan muncul perintah dengan nama yang sama
dengan nama aplikasinya. Kemudian perintah itu dapat dieksekusi untuk
memformat satu file ataupun satu direktori kode Python.

Berikut akan dibahas 3 jenis aplikasi untuk memformat kode, silakan


dicermati dahulu, tidak harus semuanya diinstal, hanya paket yang menurut
Anda sesuai kebutuhan saja yang digunakan.

Black

Black adalah proyek open source yang dikembangkan di repository Python


Software Foundation (PSF) dengan lisensi MIT. Untuk mendapatkan
gambaran, versi online (tidak resmi) ada di https://black.now.sh.

Untuk instalasi menggunakan manajer paket pip sebagai berikut: pip install


black.

YAPF (Yet Another Python Formatter)

YAPF adalah proyek open source yang dikembangkan di repository Google,


dengan lisensi Apache.

Untuk mendapatkan gambaran, versi online (tidak resmi) ada


di https://yapf.now.sh

Untuk instalasi menggunakan manajer paket pip sebagai berikut: pip install


yapf.

Autopep8
Autopep8 adalah proyek open source (berlisensi MIT) yang termasuk paling
awal untuk memformat kode, dengan bantuan lint pycodestyle. Untuk
instalasi menggunakan manajer paket pip sebagai berikut: pip install
autopep8.

Kita akan menggunakan contoh kode sebelumnya kal.py yang berisi class
Kalkulator, versi awal sebelum diperbaiki dan dicek dengan linter, sebagai
berikut.

class Kalkulator:

    """kalkulator tambah kurang"""

    def __init__(self, _i=0):

        self.i = _i

    def tambah(self, _i): return self.i + _i

    def kurang(self, _i):

        return self.i - _i

Berikut adalah hasil kode diproses dengan black, dengan mengeksekusi


perintah: black kal.py

class Kalkulator:

    """kalkulator tambah kurang"""

    def __init__(self, _i=0):

        self.i = _i

    def tambah(self, _i):

        return self.i + _i

    def kurang(self, _i):

        return self.i - _i
Kemudian jika diproses dengan yapf, tidak langsung mengubah isi file kal.py
tetapi tampil ke layar, dengan mengekseskusi perintah: yapf kal.py.

class Kalkulator:

    """kalkulator tambah kurang"""

    def __init__(self, _i=0):

        self.i = _i

    def tambah(self, _i):

        return self.i + _i

    def kurang(self, _i):

        return self.i - _i

Sama dengan yapf, untuk pemrosesan dengan autopep8, tidak langsung


mengubah isi file kal.py tetapi tampil ke layar, dengan mengeksekusi
perintah: autopep8 kal.py.

class Kalkulator:

    """kalkulator tambah kurang"""

    def __init__(self, _i=0):

        self.i = _i

    def tambah(self, _i): return self.i + _i

    def kurang(self, _i):

        return self.i - _i
Setelah mempelajari kedua mekanisme: pengecekan gaya penulisan (style
guide) dan proses memformat kode, Anda tinggal fokus dengan penulisan
indentasi dalam kode Python, untuk format sisanya dapat dibantu oleh
aplikasi-aplikasi yang telah kita pelajari di atas.

Jika Anda menulis dengan editor kode yang sangat sederhana, anggap saja
seperti notepad di Windows atau pico/nano di Linux, maka dalam menuliskan
kode Python cukup perhatikan indentasi untuk setiap baris pernyataan
(statement). Setelah selesai menuliskan kodenya, simpan kodenya sebagai
file .py, lalu eksekusi perintah linter atau langsung eksekusi perintah aplikasi
untuk memformat kode. Hasilnya, kode Anda sudah dirapikan sesuai arahan
gaya penulisan PEP8 juga dilakukan pengecekan terhadap kemungkinan
kesalahan (jika Anda lakukan linting).

Untuk Anda yang mengikuti instalasi editor kode PyCharm pada modul
Persiapan, secara bawaan sudah menggunakan fitur inspeksi dengan
kemampuan yang kurang lebih sama, meskipun jika Anda mau, bisa juga
menambahkan aplikasi lint yang sudah dijelaskan sebagai tambahan dari
yang bawaan. Demikian juga untuk fitur format ulang kode juga tersedia
secara bawaan di aplikasi PyCharm.

Python Basic Style Guide - Statement Gabungan,


Trailing Commas, dan Anotasi Fungsi

Statement gabungan

Usahakan untuk tidak menggabungkan >1 statement pada baris yang sama.
Disarankan:
1. if foo == 'blah':

2.     do_blah_thing()

3. do_one()

4. do_two()

5. do_three()

Tidak disarankan:
1. if foo == 'blah': do_blah_thing()

2. do_one(); do_two(); do_three()

Anda diperbolehkan untuk membuat sebuah konten/isi dari if/for/while yang


cukup pendek untuk diletakkan dalam satu baris (program tetap berjalan).
Namun pastikan tidak melakukannya jika if/for/while Anda bertingkat atau
bersifat multi clause, misalnya if-else, try-finally, dan sebagainya.

Tidak disarankan:
1. if foo == 'blah': do_blah_thing()

2. for x in lst: total += x

3. while t < 10: t = delay()

Sangat tidak disarankan:


1. if foo == 'blah': do_blah_thing()

2. else: do_non_blah_thing()

3. try: something()

4. finally: cleanup()

5. do_one(); do_two(); do_three(long, argument,

6.                              list, like, this)

7. if foo == 'blah': one(); two(); three()

Penggunaan Trailing Commas

Koma di bagian akhir (trailing commas) umumnya bersifat opsional, satu


statemen dimana ia bersifat wajib adalah saat kita membuat variabel
menggunakan tipe tuple dengan satu elemen. Hal ini umumnya diperjelas
dengan kurung untuk menghindari penghapusan atau pembersihan.

Disarankan:
1. FILES = ('setup.cfg',)

Tidak disarankan:
1. FILES = 'setup.cfg',

Saat trailing comma bersifat redundan, Anda akan merasakan


kemudahannya saat menggunakan VCS (Version Control System), atau pada
kode yang mungkin Anda tambahkan dalam beberapa waktu kedepan. Pola
yang disarankan adalah meletakkan nilai atau string pada sebuah baris baru,
mengikuti indentasi yang ada, dan menambahkan trailing comma, dan
menutup kurung/kurawal/siku pada baris selanjutnya.

Tidak umum jika Anda meletakkan trailing comma pada baris di mana Anda
menutup kurung/kurawal/siku, kecuali dalam tuple dengan satu elemen.

Disarankan:
1. FILES = [

2.     'setup.cfg',

3.     'tox.ini',

4.     ]

5. initialize(FILES,

6.            error=True,

7.            )

Tidak disarankan:
1. FILES = ['setup.cfg', 'tox.ini',]

2. initialize(FILES, error=True,)

Anotasi Fungsi
Penggunaan anotasi fungsi sebaiknya menggunakan aturan baku untuk titik
dua (:) dan menggunakan spasi untuk penggunaan ->. Hal ini dijelaskan lebih
lanjut di PEP 484.
1. Yes:

2. def munge(input: AnyStr): ...

3. def munge() -> AnyStr: ...

4.  

5. No:

6. def munge(input:AnyStr): ...

7. def munge()->PosInt: …

Tidak menggunakan tanda sama dengan (=) untuk mengindikasikan keyword


argumen atau nilai dasar/default pada parameter fungsi tanpa menggunakan
anotasi.
1. Yes:

2. def complex(real, imag=0.0):

3.     return magic(r=real, i=imag)

4.  

5. No:

6. def complex(real, imag = 0.0):

7.     return magic(r = real, i = imag)

Ketika melakukan kombinasi argumen anotasi dan nilai dasar/default, Anda


justru disarankan untuk menggunakan spasi sebelum dan setelah tanda =.
1. Yes:

2. def munge(sep: AnyStr = None): ...

3. def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...

4.  
5. No:

6. def munge(input: AnyStr=None): ...

7. def munge(input: AnyStr, limit = 1000): …

Python Basic Style Guide - Prinsip Penamaan pada


Python

Penamaan pada Python

Penamaan pada pustaka (library) Python agak sulit dibuat konsisten,


mengingat jumlah paketnya sudah banyak dan terdapat beberapa library
eksternal yang sudah tidak lagi dikelola. Namun, berikut adalah beberapa
rekomendasi untuk penamaan. Modul dan Paket-paket yang baru (termasuk
framework) sebaiknya ditulis dengan standar baru ini. Namun Anda juga
dapat memilih mempertahankan styling pada pustaka lama yang sudah Anda
gunakan sebelumnya. Sekali lagi, konsistensi internal lebih diutamakan.

Prinsip Overriding

Nama yang dilihat oleh user publik (misalnya API) sebaiknya merefleksikan
penggunaan/fungsinya, tidak merefleksikan implementasinya. Misal nama
fungsi berikut.
1. cariJalan() 

akan lebih mudah dipahami dibanding,


1. aStarSearch()

Algoritma yang digunakan dapat dijelaskan dalam docstring ataupun


komentar.

Penamaan Deskriptif
Terdapat berbagai cara penamaan. Akan sangat membantu jika Anda telah
memilih sebuah cara penamaan, terlepas bagaimana cara tersebut
digunakan. Beberapa cara penamaan yang umum, antara lain:

 b (satu karakter huruf kecil).


 B (satu karakter huruf besar).
 hurufkecil.
 huruf_kecil_dengan_pemisah_kata_garis_bawah.
 HURUFBESAR.
 HURUF_BESAR_DENGAN_PEMISAH_GARIS_BAWAH.
 HurufBesarDiAwalKata (atau CapWords, CamelCase). Pastikan semua
singkatan/akronim dituliskan dengan huruf besar, contohnya
HTTPServerError, bukan HttpServerError.
 hurufCampuran (mirip dengan CapWords, hanya berbeda di karakter
paling awal).
 Huruf_Besar_Di_Awal_Kata_Dengan_Garis_Bawah.

Pada beberapa pustaka juga digunakan frase awalan pendek untuk


mengelompokkan beberapa fungsi atau variabel yang berelasi atau berasal
dari satu induk. Misalnya pada fungsi os.stat(), seluruh parameter
menggunakan awalan st karena pada prinsipnya, fungsi tersebut akan
memanggil properti pada struct (st_size, st_mode, st_mtime, dll). Atau
pustaka X11 yang menggunakan awalan X pada seluruh fungsi publiknya.

Penggunaan frase atau huruf pada awal fungsi ini tidak disarankan pada
Python, atau lebih tepatnya tidak dibutuhkan, karena struktur pada Python:

 Atribut dan method name bersifat pre-fixed dengan objek,


 Function name selalu diawali dengan module name.

Beberapa bentuk khusus yang umum ditemukan (dapat digabungkan dengan


case convention):

1. _diawali_sebuah_garis_bawah: weak "internal use" indicator. impor


fungsi
from M import * tidak akan mengimpor objek dengan awalan garis
bawah.

2. diakhiri_sebuah_garis bawah_: digunakan untuk mengatasi redundant


dengan keyword / reserved words di Python, misal:
Tkinter.Toplevel(master, class_='ClassName').
3. __diawali_dua_garis bawah: menegaskan bahwa sebuah objek
merupakan bagian dari kelas tertentu (pada kelas FooBar, fungsi
__boo menjadi _FooBar__boo).

4. __diawali_dan_diakhiri_dua_garis bawah__: Objek atau atribut tertentu


yang diciptakan Python untuk digunakan dalam program: __init__,
__import__ or __file__. Jangan membuatnya sendiri, hanya gunakan
yang telah didokumentasikan.

Yang perlu diperhatikan dalam penamaan

Nama yang dihindari

Hindari karakter l (huruf L kecil), O (huruf O besar) atau I (huruf I besar)


sebagai nama variabel 1 karakter karena mereka sulit dibedakan dengan
angka satu dan nol. Saat Anda ingin menggunakan l (huruf l kecil), akan
sangat membantu jika Anda menggunakan L besar.

ASCII

Identifiers yang digunakan pada library standar harus ASCII-Compatible -


lihat PEP 3131.

Nama Paket dan Nama Modul

Nama Modul sebaiknya pendek/singkat, menggunakan huruf kecil dan


opsional garis bawah (_) untuk meningkatkan keterbacaan. Nama Paket
menggunakan huruf kecil dan hindari garis bawah(_). Jika sebuah modul
yang ditulis dengan C/C++ menyediakan Interface, maka modul C/C++
tersebut ditulis dengan diawali garis bawah (misalnya _socket).

Nama Kelas

Gunakan CamelCase atau CapWords convention. Pastikan semua akronim


(misal HTTP) ditulis keseluruhan dengan huruf besar. 
Penulisan Tipe Variable

Umumnya menggunakan CamelCase atau CapWords, lebih pendek lebih


baik:
1. T, AnyStr, Num

Jika terdapat covariant atau contravariant dari sebuah variabel, tambahkan di


akhir variabel untuk mempermudah pembacaan.
1. from typing import TypeVar

2. VT_co = TypeVar('VT_co', covariant=True)

3. KT_contra = TypeVar('KT_contra', contravariant=True)

Nama Exception

Karena exception seharusnya bertipe kelas, Anda juga menerapkan konvensi


penamaan kelas pada exception. Bedanya, tambahkan “Error” atau nama
deskriptif lain pada nama exception Anda.

Nama Variabel Global

Nama Variabel Global mengikuti fungsi/modul yang bersifat publik. Anda bisa
menggunakan garis bawah untuk menghindari variabel tersebut di-import jika
ia merupakan modul non-publik.

Nama Fungsi, Parameter, dan Variabel

Nama fungsi, parameter, dan variabel sebaiknya menggunakan huruf kecil,


dengan pemisahan menggunakan garis bawah untuk meningkatkan
keterbacaan. mixedCase dapat digunakan jika ada dependensi dengan
pustaka dengan style tertentu.
Instansiasi Fungsi dan Method

Gunakan self sebagai argument pertama instansiasi method.

Gunakan cls sebagai argumen pertama pada class methods.

Jika nama argument fungsi merupakan reserved keyword, tambahkan garis


bawah di akhir nama argument. Jangan mengorbankan keterbacaan nama
dengan menyingkatnya. Mengganti argumen bernama class dengan class_
atau kelas, lebih baik daripada clss, misalnya.

Nama Method dan Nama Variabel dalam Method

Gunakan standar penamaan Fungsi: huruf kecil dengan pemisah kata garis
bawah untuk meningkatkan keterbacaan. Tambahkan garis bawah sebagai
awalan untuk method non-publik dan variabel internal pada fungsi.

Untuk menghindari kesamaan dengan subkelas, gunakan


__dimulai_dua_garis_nama_method untuk memanggil proses yang tepat.
Python menggabungkan nama modul dengan nama kelas. Jika kelas Foo
memiliki atribut __a, maka kita tidak dapat mengaksesnya melalui Foo.__a,
melainkan Foo._Foo__a. Mulai dengan dua garis bawah hanya digunakan
jika terjadi konflik dengan atribut di kelas atau subkelas lainnya.

Konstanta

Konstanta umumnya didefinisikan pada bagian atas modul dengan huruf


besar, misalnya MAX_OVERFLOW dan TOTAL.

Selalu Persiapkan untuk Inheritance

Saat sebuah metode dan variabel dalam sebuah kelas didefinisikan,


sebaiknya Anda dapat langsung mengetahui atribut pada metode dan
variabel tersebut, apakah publik atau non-publik. Jika Anda ragu, jadikan
atributnya non-publik. Karena lebih mudah menjadikan sebuah
variabel/method bersifat non-publik menjadi publik, dibandingkan
sebaliknya.

Method/Variabel Publik dipersiapkan untuk pihak eksternal menggunakan


kelas Anda. Anda juga otomatis berkomitmen untuk menghindari
adanya incompatible backward changes. Sebaliknya, Method/Variabel
dengan atribut non-publik hanya digunakan oleh Anda sebagai developer,
dan tidak memberikan garansi kepada siapapun bahwa Anda tidak akan
mengubah atau menghapusnya. Di sini kita tidak menggunakan
atribut Private karena di Python tidak ada atribut yang benar-benar Private.

Kategori lain dari atribut adalah "subclass API", umumnya disebut protected
pada bahasa lain. Sebuah kelas dapat didesain untuk diwariskan (inherited-
from), misalnya untuk memodifikasi atau menjadi ekstensi dari perilaku
(behavior) kelas. Dalam mendesain kelas-kelas sejenis, pastikan untuk
membuat keputusan eksplisit, mana Variabel/Method yang memiliki atribut
publik, bagian dari subclass API, dan mana yang hanya anda gunakan
secara internal.

Saat mendeklarasikan variabel/method tersebut, ikuti panduan Pythonic


berikut:

 Atribut publik tidak menggunakan awalan garis bawah.


 Jika nama sebuah Method/Variabel publik sama dengan reserved
keyword, tambahkan akhiran garis bawah. Hindari menyingkat atau
mengurangi huruf.
 Pada Data publik bersifat simple, hindari nama yang terlalu panjang.
Cukup dengan nama atribut sependek mungkin. Ingatlah bahwa di
masa depan Anda akan mungkin mengembangkan skema atau data
ini, sehingga nama sependek mungkin akan menguntungkan Anda.
 Jika Anda berniat untuk mewariskan atau membuat subclass dari kelas,
dan menginginkan sebuah variabel hanya digunakan di kelas utama
saja, tambahkan awalan dua garis bawah. Ini akan memudahkan Anda
karena Python mengenalinya sebagai konvensi kelas, menghindari
kemungkinan kesamaan nama atau implementasi.

Interface

Umumnya, garansi backward compatibility hanya diaplikasikan pada interface


publik. Untuk itu pengguna harus dapat membedakan dengan jelas, interface
publik dan internal/non-publik. Interface yang didokumentasikan umumnya
dianggap sebagai interface publik, kecuali dijelaskan secara eksplisit.
Sebaliknya, setiap interface yang tidak terdokumentasi, umumnya dianggap
bersifat internal.

Untuk keterbacaan, modul sebaiknya mendeklarasikan nama interface/API


melalui atribut __all__. Jika __all__ kosong, artinya modul tersebut tidak
memiliki interface/API Publik. Selain __all__ yang diisi dengan sesuai,
internal interface (paket, modul, kelas, fungsi, atribut, atau nama lainnya),
sebaiknya tetap dituliskan dengan diawali garis bawah.

Sebuah interface otomatis dianggap internal, jika namespace (paket, modul,


atau kelasnya) bersifat internal.

Nama yang di-import harap selalu dianggap sebagai detail implementasi.


Modul lainnya tidak diperbolehkan untuk melakukan akses tidak langsung
untuk nama-nama tersebut, kecuali jika sudah didokumentasikan, misalnya
os.path atau modul __init__ yang mengekspos fungsionalitas dari submodul.

Percabangan dan Ternary Operators


Beberapa contoh aplikasi dasar untuk pengenalan percabangan yang sering digunakan adalah:

 Genap atau Ganjil.


 Positif atau Negatif.
 Positif, Negatif, atau Nol.

If
Seperti bahasa pemrograman lainnya, Python juga memiliki statemen percabangan IF. Di
Python, expression diletakkan setelah if, dan keputusan ditentukan berdasarkan nilai kebenaran
dari expression tersebut.

Tip: Python menganggap setiap nilai non-zero dan non-null sebagai True dan nilai zero/null
sebagai False.

Jika expression dievaluasi sebagai True, maka blok statement di dalam if statement akan
dieksekusi. Sesuai konvensi, blok ini memiliki indentasi masuk setelah tanda titik dua (:). Jika
expression dievaluasi sebagai False, maka blok selanjutnya (setelah statement IF) yang akan
dijalankan. Contoh:
1. kelerengku = 10

2. if kelerengku:

3.    print ("Cetak ini jika benar")

4.    print (kelerengku)

Output:

Cetak ini jika benar


10

Anda dapat menyingkat penulisan statement yang akan dieksekusi jika ia terwakili dalam 1 baris.
Misalnya:

1. if kerelengku: hitung()

Else
Statement Else dapat dikombinasikan dengan IF Statement, sebagai jalan keluar saat kondisi /
hasil evaluasi bernilai False. Else bersifat opsional dan tunggal. Mari kita implementasikan
dalam kasus pengecekan tinggi badan pengunjung di suatu wahana.

1. tinggi_badan = int(input("Masukkan tinggi badan Anda : "))

2. if tinggi_badan>=160:

3.    print ("Silakan, Anda boleh masuk")

4. else:

5.    print ("Maaf, Anda belum boleh masuk")

Output 1:

Masukkan tinggi badan Anda : 160


Silakan, Anda boleh masuk

Output 2:
Masukkan tinggi badan Anda : 140
Maaf, Anda belum boleh masuk

Mari implementasikan pada kasus yang berbeda, kali ini kasusnya adalah pengecekan bilangan
ganjil atau genap pada suatu variabel.

1. bilangan = 4

2. if bilangan % 2 == 0:

3.     print('Bilangan {} adalah genap'.format(bilangan))

4. else:

5. print('Bilangan {} adalah ganjil'.format(bilangan))

Output:

Bilangan 4 adalah genap

Elif - Alternatif untuk Switch/Case dan IF bertingkat di


python
Elif adalah kependekan dari else if, dan merupakan alternatif untuk if bertingkat atau switch/case
di beberapa bahasa pemrograman lain. Sebuah IF Statement dapat diikuti satu atau lebih
statement elif (opsional & tidak dibatasi). Mari kita implementasikan pada kasus penilaian tugas
siswa.

1. nilai = int(input("Masukkan nilai tugas Anda : "))

2. if nilai>80:

3.    print("Selamat! Anda mendapat nilai A")

4. print("Pertahankan!")

5. elif nilai>70:

6.    print("Hore! Anda mendapat nilai B")

7. print("Tingkatkan!")

8. elif nilai>60:
9. print("Hmm.. Anda mendapat nilai C")

10. print("Ayo semangat!")

11. else:

12.    print("Waduh, Anda mendapat nilai D")

13. print("Yuk belajar lebih giat lagi!")

Output 1:

Masukkan nilai tugas Anda : 85


Selamat! Anda mendapat nilai A
Pertahankan!

Output 2:

Masukkan nilai tugas Anda : 75


Hore! Anda mendapat nilai B
Tingkatkan!

Output 3:

Masukkan nilai tugas Anda : 65


Hmm.. Anda mendapat nilai C
Ayo semangat!

Output 4:

Masukkan nilai tugas Anda : 30


Waduh, Anda mendapat nilai D
Yuk belajar lebih giat lagi!

Catatan: Jika sudah memenuhi salah satu kondisi if/elif, maka program akan keluar dari blok IF
Statement. Anda harus memastikan urutan secara logika, IF, Elif, dan Else dalam tingkatan yang
tepat. Contoh yang perlu diperhatikan adalah sebagai berikut:

Input Nilai #Kasus 1 #Kasus 2

if nilai>80: if nilai>0:
print("Selamat! Anda mendapat nilai A") print("Selamat! Anda mendapat nilai A")
print("Pertahankan!") print("Pertahankan!")
elif nilai>70: elif nilai<80:
print("Hore! Anda mendapat nilai B") print("Hore! Anda mendapat nilai B")
print("Tingkatkan!") print("Tingkatkan!")
elif nilai>60: elif nilai<70:
print("Hmm.. Anda mendapat nilai C") print("Hmm.. Anda mendapat nilai C")
print("Ayo semangat!") print("Ayo semangat!")
else: else:
print("Waduh, Anda mendapat nilai D") print("Waduh, Anda mendapat nilai D")
print("Yuk belajar lebih giat lagi!")     print("Yuk belajar lebih giat lagi!")

85 Masukkan nilai tugas Anda: 85 Masukkan nilai tugas Anda: 85


Selamat! Anda mendapat nilai A Selamat! Anda mendapat nilai A
Pertahankan! Pertahankan!

65 Masukkan nilai tugas Anda: 65 Masukkan nilai tugas Anda: 65


Hmm.. Anda mendapat nilai C Selamat! Anda mendapat nilai A
Ayo semangat! Pertahankan!

30 Masukkan nilai tugas Anda: 30 Masukkan nilai tugas Anda: 30


Waduh, Anda mendapat nilai D Selamat! Anda mendapat nilai A
Yuk belajar lebih giat lagi! Pertahankan!

Pada #Case 2, elif dan else tidak pernah dijalankan karena nilai berapapun (yang bernilai positif)
akan selalu masuk pada IF (klausa pertama).

Mari kita implementasikan pada kasus pengecekan bilangan positif, negatif, atau nol.

1. bilangan = -3

2. if bilangan > 0:

3.     print('Bilangan {} adalah positif'.format(bilangan))

4. elif bilangan < 0:

5.     print('Bilangan {} adalah negatif'.format(bilangan))

6. else:

7. print('Bilangan {} adalah nol'.format(bilangan))

Output:

Bilangan -3 adalah negatif


Ternary Operators
Ternary operator lebih dikenal sebagai conditional expressions pada Python. Operator
menentukan sesuatu berdasarkan kondisi True atau False. Jika statement atau klausa if Anda
cukup sederhana, maka ternary Operators akan sangat membantu.

Perbandingan klausa IF dengan ternary Operators:

IF Ternary

if (condition): condition_if_true if condition else condition_if_false
condition_if_true
else:
condition_if_false

lulus = True lulus = True


if (lulus): kata = "selamat" if lulus else "perbaiki"
kata = ”selamat”
else:
kata = “perbaiki”

Opsi lain dari ternary operators melibatkan tuples. Contoh kodenya berikut:

IF Ternary_Tuples

if (condition): (condition_if_false, condition_if_true)[condition]
condition_if_true
else:
condition_if_false

lulus = True nice = True


if (lulus): kata= ("perbaiki", "selamat")[lulus]
kata=”selamat”
else:
kata=“perbaiki”

Pada tuple ini, dimanfaatkan nilai [0] sebagai False dan [1] sebagai True.

Aplikasi kedua ini menurut beberapa aktivis kurang ‘pythonic’, salah satunya karena cukup
membingungkan untuk meletakkan klausa saat True atau False. Selain itu, kedua nilai akan tetap
dievaluasi walaupun hanya dibutuhkan salah satunya. Lihat contoh berikut:

1. kondisi = True

2. print(2 if kondisi else 1/0)

3. #Output is 2
4.  

5. print((1/0, 2)[kondisi])

6. #Eror Pembagian Nol akan muncul

Ternary-tuples sebaiknya dihindari, terutama untuk kode (dan klausa True/False) yang kompleks.
Ternary dapat digunakan untuk menyingkat kode saat klausa True/False Anda cukup pendek -
misalnya sebuah fungsi tanpa parameter.

ShortHand Ternary
Selain Ternary Operators, dikenal juga shorthand ternary tag yang mungkin membantu Anda
untuk memeriksa kode/hasil dari sebuah fungsi dan memastikan outputnya tidak menyebabkan
error (atau minimal memberikan informasi relevan saat error):

1. hasil = None

2. pesan = hasil or "Tidak ada data"

3. print(pesan)

Output:

 Tidak ada data

Perulangan

For

Seperti di bahasa pemrograman lainnya, Python juga memiliki fungsi for.


Bedanya di Python, For tidak hanya untuk perulangan dengan jumlah finite
(terbatas), melainkan lebih ke fungsi yang dapat melakukan perulangan pada
setiap jenis variabel berupa kumpulan atau urutan. Variabel yang dimaksud
bisa berupa list, string, ataupun range. Jika sebuah list atau urutan berisi
expression, maka Ia akan dievaluasi terlebih dahulu. Kemudian item pertama
pada urutan/list akan diassign sebagai variabel iterating_var. Setelahnya,
blok statement akan dieksekusi, berlanjut ke item berikutnya, berulang,
hingga seluruh urutan habis.
1. for huruf in 'Dicoding':  # Contoh pertama

2.     print('Huruf: {}'.format(huruf))

3.  

4. flowers = ['mawar', 'melati', 'anggrek']

5. for flower in flowers:  # Contoh kedua

6.     print('Flower: {}'.format(flower))

Output:

Huruf : D
Huruf : i
Huruf : c
Huruf : o
Huruf : d
Huruf : i
Huruf : n
Huruf : g
Flower: mawar
Flower: melati
Flower: anggrek

Anda juga dapat melakukan perulangan berdasarkan indeks atau range


dengan memanfaatkan fungsi len():
1. flowers = ['mawar', 'melati', 'anggrek']

2. for index in range(len(flowers)):

3.     print('Flowers: {}'.format(flowers[index]))

Output:

Flower : mawar
Flower : melati
Flower  : anggrek
While

While pada bahasa Python digunakan untuk mengeksekusi statement selama


kondisi yang diberikan terpenuhi (True). Kondisi dapat berupa expression
apapun, dan harap diingat bahwa True di Python termasuk semua nilai
non-zero. Saat kondisi menjadi False, program akan melanjutkan ke baris
setelah blok statement.

Tip: Python tidak memiliki do.. while statement

Seperti for dan semua statement percabangan, blok statement yang


mengikuti kondisi while dan memiliki posisi indentasi yang sama, dianggap
blok statement yang akan dieksekusi.

Contoh:
1. count = 0

2. while (count < 7):

3.     print('Hitungannya adalah: {}'.format(count))

4. count = count + 1

Output:

Hitungannya adalah: 0
Hitungannya adalah: 1
Hitungannya adalah: 2
Hitungannya adalah: 3
Hitungannya adalah: 4
Hitungannya adalah: 5
Hitungannya adalah: 6

Seperti pada bahasa lainnya, eksekusi statement while mungkin bersifat


infinit / infinite loop saat sebuah kondisi tidak pernah bernilai False.
Contohnya sebagai berikut:
1. var = 1
2. while var == 1:  # This constructs an infinite loop

3.     num = input('Masukkan angka: ')

4.     print('Anda memasukkan angka: {}'.format(num))

5.  

6.  

7. while True:  # This constructs an infinite loop

8.     num = input('Masukkan angka: ')

9.     print('Anda memasukkan angka: {}'.format(num))

Potongan kode di atas tidak akan pernah bernilai False karena nilai var tidak
pernah berubah. Untuk menghentikan infinite loop, gunakan CTRL (atau
CMD⌘) - C untuk menghentikannya dan keluar dari program.

Anda juga dapat menyingkat penulisan blok statement While jika statement
Anda cukup terwakili oleh satu baris.
1. while (var1): do_something()

Perulangan Bertingkat

Ada kalanya Anda perlu untuk melakukan perulangan bertingkat, misalnya


untuk menghasilkan contoh print-out berikut:

******
*****
****
***
**
*
Anda dapat melakukannya dengan kode berikut:
1. for i in range(0, 6):

2.     for j in range(0, 6 - i):


3.         print('*', end='')

4.     print()

Tip: Tambahkan parameter end pada print untuk mengatur karakter yang
mengakhiri pencetakan string/teks Anda. Secara default, karakter end ini
adalah newline ('\n').

Kontrol Perulangan

Break

Pernyataan break menghentikan perulangan kemudian keluar, dilanjutkan


dengan mengeksekusi pernyataan (statement) setelah blok perulangan.
Salah satu penggunaannya yang paling sering adalah sebuah kondisi
eksternal yang membutuhkan program untuk keluar dari perulangan. Jika
Anda memiliki perulangan bertingkat, break akan menghentikan perulangan
sesuai dengan tingkatan atau di perulangan mana ia berada. Namun jika ia
diletakkan di perulangan dengan kedalaman kedua misalnya, hanya
perulangan itu saja yang berhenti, tidak dengan perulangan utama.

Contoh 1:
1. for huruf in 'Dico ding':

2.     if huruf == ' ':

3.         break

4.     print('Huruf saat ini: {}'.format(huruf))

Output contoh 1:

Huruf saat ini: D


Huruf saat ini: i
Huruf saat ini: c
Huruf saat ini: o
Contoh 2, cetak bintang dengan memanfaatkan fungsi break
1. for i in range (0,10):

2. for j in range (0,10):

3. if j>i:

4. print()

5. break

6. else:

7. print("*",end="")

8.  

Output contoh 2:

*
**
***
****
*****
******
*******
********
*********
**********

Continue

Pernyataan continue akan membuat iterasi saat ini berhenti, kemudian


melanjutkan ke iterasi berikutnya, mengabaikan pernyataan (statement)
yang berada antara continue hingga akhir blok perulangan.

Contoh 1:
1. for huruf in 'Dico ding':

2.     if huruf == ' ':

3.         continue

4.     print('Huruf saat ini: {}'.format(huruf))


Output contoh 1:

Huruf saat ini: D


Huruf saat ini: i
Huruf saat ini: c
Huruf saat ini: o
Huruf saat ini: d ## perhatikan spasi dilewati
Huruf saat ini: i
Huruf saat ini: n
Huruf saat ini: g

Contoh 2, cetak bintang yang sama dengan contoh 2 pada pembahasan


fungsi break, dengan 1 loop dan 1 if (tanpa else):
1. jumlahbaris = 10

2. baris = 0

3. bintang = 0

4. while baris < jumlahbaris:

5. if (bintang) >= (baris+1):

6. print()

7. baris = baris+1

8. bintang=0

9. continue ##saat masuk ke if, maka bagian print * diluar

if tidak akan dijalankan, langsung ulang ke while

10. print("*",end="")

11. bintang= bintang+1

*
**
***
****
*****
******
*******
********
*********
**********

Else setelah For

Pada Python juga dikenal fungsi else setelah for. Fungsinya diutamakan
pada perulangan yang bersifat pencarian - untuk memberikan jalan keluar
program saat pencarian tidak ditemukan.

Struktur umumnya adalah sebagai berikut:


1. for item in items:

2.     if cari(item):

3.         #ditemukan!

4.         proses_item()

5.         break

6. else:

7.     #Item tidak ditemukan

8.     not_found_in_container()

Anda mungkin melihat sesuatu yang menarik. Ada If dan Else, namun dalam
tingkatan yang berbeda, apakah mereka terkait? 

Saat sebuah perulangan dijalankan, fungsi if akan dievaluasi. Saat ia pernah


sekali saja benar, maka else tidak akan dieksekusi. Dengan kata lain, if yang
berada dalam perulangan harus selalu salah untuk memicu blok statemen
else dijalankan. Lebih singkat lagi, struktur pseudocode yang diikuti dalam
membuat else pada perulangan adalah seperti berikut:
1. if any(something_about(thing) for each thing in container):

2.     do_something(that_thing)

3. else:

4.     no_such_thing()
Contoh penggunaan dari for-else dapat dilihat pada potongan kode berikut
(jalankan di konsol sebelum melanjutkan ke bagian selanjutnya):
1. for n in range(2, 10):

2.     for x in range(2, n):

3.         if n % x == 0:

4.             print(n, 'equals', x, '*', n/x)

5.             break

Potongan kode di atas melakukan pencarian faktor dari setiap bilangan


antara 2 s/d 9. Namun demikian, pada saat bilangan n bernilai 2, 3, 5, 7,
program tidak akan mencetak apapun. Ini karena bilangan-bilangan tersebut
merupakan bilangan prima. Hal ini bisa diatasi dengan menambahkan
keterangan else dan mencetak bahwa bilangan tersebut adalah bilangan
prima:
1. for n in range(2, 10):

2.     for x in range(2, n):

3.         if n % x == 0:

4.             print( n, 'equals', x, '*', n/x)

5.             break

6.     else:

7.         # loop fell through without finding a factor

8.         print(n, ' adalah bilangan prima')

Else setelah While


Berbeda dengan Else setelah For, pada statement while, blok statement
else akan selalu dieksekusi saat kondisi pada while menjadi salah. Contoh
mudahnya adalah sebagai berikut:
1. n = 10

2. while n > 0:

3.     n = n - 1

4. if n == 7:

5.         break

6.     print(n)

7. else:

8.     print("Loop selesai")

Output:

9
8

Pada contoh diatas, loop akan di break saat nilai n == 7, saat keluar dari
perulangan, maka python tidak akan memunculkan tulisan Loop selesai,
namun jika tidak dilakukan break (perulangan berakhir dengan normal):
1. n = 10

2. while n > 0:

3.     n = n - 1

4.     print(n)

5. else:

6.     print("Loop selesai")

Output:

9
8
7
6
5
4
3
2
1
0
Loop selesai

Pass

Digunakan jika Anda menginginkan sebuah pernyataan atau blok pernyataan


(statement), namun tidak melakukan apapun - melanjutkan eksekusi sesuai
dengan urutannya. Kontrol ini banyak digunakan saat Anda belum melakukan
implementasi (atau menyiapkan tempat untuk implementasi), serta
membiarkan program tetap berjalan saat misalnya Anda mengalami
kegagalan atau exception.

Pass statement adalah operasi bersifat Null (kosong), tidak ada yang terjadi
saat ia dipanggil. Contohnya:
1. def sebuahfungsi():

2. pass

Output:

#tidak ada

Jika Anda mendeklarasi sebuah fungsi tanpa kode apapun, justru akan
terjadi error:
1. def sebuahfungsi():

Output:

File "<test.py>", line 2


^
IndentationError: expected an indented block
Contoh pass untuk mengantisipasi exception/kegagalan fungsi, perhatikan
contoh kode yang belum ditambahkan pass berikut:
1. var1=""

2. while(var1!="exit"):

3.     var1=input("Please enter an integer (type exit to exit): ")

4.     print(int(var1))

Output:

Please enter an integer (type exit to exit): 1


1
Please enter an integer (type exit to exit): a
Traceback (most recent call last):
File "testp3.py", line 7, in <module>
print(int(var1))
ValueError: invalid literal for int() with base 10: 'a'

Kita dapat membaca bahwa program gagal saat mencoba proses konversi
variabel var1. Saat program mengalami kegagalan atau exception, ia akan
langsung keluar. Bandingkan dengan pendekatan berikut (mengenai
exception, import/library sys, dan try/except akan dibahas pada modul-modul
pembelajaran berikutnya:
1. import sys

2. data=''

3. while(data!='exit'):

4.     try:

5.         data=input('Please enter an integer (type exit to exit): ')

6.         print('got integer: {}'.format(int(data)))

7.     except:

8.         if data == 'exit':

9.             pass  # exit gracefully without prompt any error

10.         else:
11.             print('error: {}'.format(sys.exc_info()[0]))

Outputnya saat dijalankan:

Please enter an integer (type exit to exit): 1


got integer: 1
Please enter an integer (type exit to exit): a
Unexpected error: <class 'ValueError'>
Please enter an integer (type exit to exit): b
Unexpected error: <class 'ValueError'>
Please enter an integer (type exit to exit): c
Unexpected error: <class 'ValueError'>
Please enter an integer (type exit to exit): exit

Pada pendekatan kedua, program akan memberitahu kegagalan yang terjadi


sesuai dengan yang kita tuliskan pada baris berwarna kuning, namun tetap
terus berjalan, dalam hal ini hingga dituliskan exit. Anda dapat melakukan
antisipasi apapun sebelum menulis pass (misalnya memasukkan informasi
terkait error ke log, memberi notifikasi ke admin, dan sebagainya).

List Comprehension (membuat list dengan inline loop dan if)

Ada kalanya Anda perlu untuk membuat sebuah list baru dari dengan sebuah
operasi dari list sebelumnya. Misalnya membuat nilai kuadrat dari semua
item dalam list:
1. #Cara 1

2. angka = [1, 2, 3, 4]

3. pangkat = []

4. for n in angka:

5.   pangkat.append(n**2)

6. print(pangkat)

Cara yang umum digunakan adalah cara di atas, yakni melakukan


perulangan sejumlah item pada list angka kemudian membuat list baru
(pangkat) dan menambahkan hasil operasinya dalam list baru (pangkat).
Bandingkan dengan cara berikut:
1. #Cara 2 List Comprehension

2. angka = [1, 2, 3, 4]

3. pangkat = [n**2 for n in angka]

4. print(pangkat)

Cobalah kedua contoh di atas. Hasilnya sama bukan?

Output:

[1, 4, 9, 16]

List comprehension adalah salah satu cara untuk menghasilkan list baru
berdasarkan list atau iterables yang telah ada sebelumnya. Sintaksis
dasarnya adalah sebagai berikut:
1. new_list = [expression for_loop_one_or_more conditions]

Contoh kedua di atas dapat diartikan sebagai: untuk setiap anggota angka
buatlah nilai kuadratnya. List comprehension dapat digunakan lebih lanjut,
misalnya:
1. #Contoh3 menemukan item yang ada di kedua list

2. list1 = ['d', 'i', 'c', 'o']

3. list2 = ['d', 'i', 'n', 'g']

4. duplikat = []

5. for a in list1:

6.   for b in list2:

7.     if a == b:

8.       duplikat.append(a)
9.      

10. print(duplikat)  # Output ['d','i']

Bandingkan dengan:
1. #Contoh4 Implementasi dengan list comprehension

2. list1 = ['d', 'i', 'c', 'o']

3. list2 = ['d', 'i', 'n', 'g']

4. duplikat = [a for a in list1 for b in list2 if a == b]

5. print(duplikat) # Output: ['d','i']

Sangat memudahkan bukan? Dari 5 baris cukup disingkat menjadi 1 baris


saja. 

Contoh penggunaan yang lain dapat dilihat pada contoh 5 berikut:


1. # Contoh 5 kecilkan semua huruf

2. list_a = ["Hello", "World", "In", "Python"]

3. small_list_a = [_.lower() for _ in list_a]

4. print(small_list_a)

Output:

['hello', 'world', 'in', 'python']

Anda tidak perlu bingung saat melihat kode di Internet yang menuliskan
seperti contoh di atas, karena garis bawah (underscore) termasuk
penamaan variabel yang valid. Secara umum "_" biasa digunakan
sebagai throwaway variable (variabel tidak penting). 

Banyak hal yang mungkin dilakukan dengan list comprehension. Coba


perkirakan apa yang akan dimunculkan oleh potongan kode berikut dan pilih
jawaban yang tepat pada kuis di bagian berikutnya:
1. list_a = range(1, 10, 2)

2. x = [[a**2, a**3] for a in list_a]

3. print(x)

Penanganan Kesalahan (Error dan Exception


Handling)
Ada setidaknya dua jenis kesalahan berdasarkan kejadiannya: 

1. Kesalahan sintaksis (syntax errors) atau sering disebut kesalahan


penguraian (parsing errors).
2. Pengecualian (exceptions) atau sering disebut kesalahan saat
beroperasi (runtime errors).

Kesalahan sintaksis terjadi ketika Python tidak dapat mengerti apa yang
Anda perintahkan. Sedangkan pengecualian (kesalahan saat beroperasi)
terjadi ketika Python mengerti apa yang Anda perintahkan tetapi
mendapatkan masalah saat mengikuti yang Anda perintahkan (terjadi saat
aplikasi sudah mulai beroperasi).

Kesalahan Sintaksis
Kesalahan sintaksis biasanya sering terjadi saat Anda masih baru memulai
belajar Python, misalnya contoh berikut adalah penempatan indentasi (spasi
di awal) yang tidak sesuai.
1. print('salah indentasi')

2.  File "<stdin>", line 1

3.    print('salah indentasi')

4.    ^

5. IndentationError: unexpected indent

Contoh berikut ini menampilkan kesalahan sintaksis, di mana setelah kondisi


dari perintah while diharuskan ada tanda titik dua (:).
1. while True print('Hello world')

2.  File "<stdin>", line 1

3.    while True print('Hello world')

4.                   ^

5. SyntaxError: invalid syntax

Pada kesalahan sintaksis, baris di mana kesalahan terdeteksi dimunculkan


kembali, kemudian terdapat tanda panah yang menunjukkan titik paling awal
dari kesalahan.

Kedua contoh di atas memiliki kelompok (tipe) kesalahan yang berbeda, yang
pertama adalah IndentationError dan yang kedua adalah SyntaxError.
Kemudian setelah penyebutannya, ada pesan detail kesalahan (keterangan),
misalnya indentasi yang tidak diharapkan (unexpected).

Jika Anda menggunakan mode pemanggilan skrip, nama file skrip dan nomor
baris di mana terjadi kesalahan akan dimunculkan. Sedangkan untuk mode
interaktif pada dua contoh di atas, nama file muncul sebagai “<stdin>”.
Berikut adalah contoh pada pemanggilan skrip bernama
contoh_salah_sintaksis.py di mana terjadi kesalahan pada baris 2.
1. python contoh_salah_sintaksis.py  

2.  File "contoh_salah_sintaksis.py", line 2

3.    if True print('salah sintaksis')

4.                ^

5. SyntaxError: invalid syntax

Pengecualian
Meski pernyataan atau ekspresi dari Python sudah Anda tulis dengan benar,
ada kemungkinan terjadi kesalahan ketika perintah tersebut dieksekusi.
Kesalahan yang terjadi saat proses sedang berlangsung disebut
pengecualian (exceptions) dan akan berakibat fatal jika tidak ditangani.
Kebanyakan pengecualian di Python tidak ditangani oleh aplikasi, sehingga
aplikasi terhenti kemudian muncul pesan kesalahan seperti contoh berikut.
1. print(angka)

2. Traceback (most recent call last):

3.  File "<stdin>", line 1, in <module>

4. NameError: name 'angka' is not defined

Misalkan Anda lupa memberikan nilai pada variabel angka, tetapi Anda
langsung memanggil variabel tersebut. Secara sintaksis sudah sesuai, tapi
muncul pengecualian dengan kelompok (tipe) kesalahan NameError dan
pesan detail kesalahan yang menyatakan bahwa variabel angka tidak
terdefinisi.

Contoh lain terkait pengecualian yang sering juga terjadi adalah operasi dari
variabel yang jenisnya tidak sesuai, misalnya contoh berikut.
1. bukan_angka = '1'

2. bukan_angka + 2

3. Traceback (most recent call last):

4.  File "<stdin>", line 1, in <module>

5. TypeError: can only concatenate str (not "int") to str

Pada contoh tersebut, variabel bukan_angka berjenis string, sehingga saat


mengoperasikan variabel tersebut dengan angka (berjenis integer), meskipun
secara sintaksis sudah sesuai, muncul pengecualian dengan kelompok (tipe)
kesalahan TypeError dan pesan detail kesalahan yang menyatakan bahwa
operasi penambahan untuk string (contatetation) hanya bisa dilakukan jika
kedua operannya adalah string (dan bukan integer).

Seperti terlihat bahwa pada saat terjadi pengecualian, informasi yang muncul
seperti saat terjadi kesalahan (errors), termasuk juga informasi nama file dan
nomor baris di mana kesalahan terjadi.
Penanganan Pengecualian
Pada aplikasi Python yang Anda buat bisa dilengkapi dengan penanganan
terhadap pengecualian (exceptions handling) dari kelompok (tipe) kesalahan
yang Anda tentukan. Proses penanganan pengecualian menggunakan
pernyataan try yang berpasangan dengan except.

Misalnya kita ingin menangani pengecualian yang terjadi jika ada pembagian
angka dengan nilai nol (0).
1. >>> z = 0

2. >>> 1 / z

3.  

4. Traceback (most recent call last):

5. File "<stdin>", line 1, in <module>

6. ZeroDivisionError: division by zero

7.  

8. >>> try:

9. ...     x = 1 / z

10. ...     print(x)

11. ... except ZeroDivisionError:

12. ...     print('tidak bisa membagi angka dengan nilai nol')

13.  

14. tidak bisa membagi angka dengan nilai nol

Perhatikan bahwa operasi aplikasi berhenti di x = 1 / z, sedangkan


bagian print(x) tidak sempat dioperasikan, karena aplikasi sudah mengalami
pengecualian, sehingga yang tercetak adalah operasi print(‘tidak bisa
membagi angka dengan nilai nol’).

Pada operasi yang dicontohkan di atas, penanganan pengecualian untuk


ZeroDivisionError dilakukan sehingga aplikasi tidak lagi keluar dari eksekusi
karena kesalahan, tapi digantikan dengan mencetak pesan ke layar. Pada
contoh ini kita fokus pada penanganan pengecualian, meskipun ada cara lain
untuk menyelesaikannya, misal menggunakan kondisi (percabangan) untuk
menghindari nilai nol.

Pernyataan except dilanjutkan dengan kelompok (tipe) kesalahan yang ingin


ditangani, atau bisa juga berupa tuple dari satu atau lebih tipe kesalahan
yang akan ditangani. Di contoh berikut,
menangani FileNotFoundError sebagai tuple satu elemen, jangan lupa dalam
menuliskan tuple satu elemen harus tetap diakhiri dengan koma.
1. >>> try:

2. ...     with open('contoh_tidak_ada.py') as file:                   

3. ...         print(file.read())                          

4. ... except (FileNotFoundError, ):

5. ...     print('file tidak ditemukan')

6. ...  

7. file tidak ditemukan

Pada operasi di atas, aplikasi akan membuka dan mengakses file bernama
contoh_tidak_ada.py, tetapi file tersebut tidak ada di direktori dimana aplikasi
Python tersebut berada, selanjutnya akan terjadi pengecualian (exceptions)
tetapi ditangani, dalam pasangan pernyataan try dan except, sehingga
aplikasi tidak terhenti tetapi tercetak di layar bahwa file tidak ditemukan.

Dalam aplikasi yang lebih kompleks, penanganan pengecualian dapat


menggunakan pernyataan except lebih dari satu. Di contoh berikutnya akan
menggunakan pernyataan except lebih dari satu (untuk satu pernyataan try),
maupun menggunakan satu pernyataan except yang menangani lebih dari
satu tipe kesalahan yang digabung dalam sebuah tuple.
1. >>> d = {'ratarata': '10.0'}

2. >>> try:

3. ...     print('rata-rata: {}'.format(d['rata_rata']))

4. ... except KeyError:                                 


5. ...     print('kunci tidak ditemukan di dictionary')

6. ... except ValueError:              

7. ...     print('nilai tidak sesuai')

8. ...  

9. kunci tidak ditemukan di dictionary

10. >>> try:

11. ...     print('rata-rata: {}'.format(d['ratarata']/3))

12. ... except KeyError:                                 

13. ...     print('kunci tidak ditemukan di dictionary')

14. ... except (ValueError, TypeError):

15. ...     print('nilai atau tipe tidak sesuai')

16. ...  

17. nilai atau tipe tidak sesuai

18. >>> try:

19. ...     print('pembulatan rata-rata: {}'.format(int(d['ratarata'])))

20. ... except (ValueError, TypeError) as e:         

21. ...     print('penangan kesalahan: {}'.format(e))

22. ...  

23. penangan kesalahan: invalid literal for int() with base 10: '10.0'

Pada contoh tersebut, yang paling awal terjadi pengecualian untuk tipe
kesalahan KeyError karena dalam dictionary d tidak memiliki kunci
(key) rata_rata, yang ada adalah kunci ratarata.

Kemudian contoh selanjutnya terjadi pengecualian untuk tipe


kesalahan TypeError karena nilai d[‘ratarata’] memiliki tipe string, sehingga
tidak dapat dibagi dengan integer (angka) 3. Dalam penanganan
kesalahannya, satu buah pernyataan except menangani tipe
kesalahan ValueError atau TypeError, sehingga cocok salah satunya akan
menampilkan ke layar bahwa nilai atau tipe tidak sesuai.

Di bagian paling akhir contoh, terjadi pengecualian untuk tipe kesalahan


ValueError karena berusaha melakukan konversi (casting) dari sebuah string
ke integer dengan format yang tidak sesuai (bilangan bulat seharusnya tidak
memiliki titik dalam penulisannya). Dalam penulisan penanganan
kesalahannya digunakan variasi lain untuk mendapatkan pesan kesalahan
sebagai variabel e untuk kemudian variabel tersebut dicetak dalam pesan
yang ditampilkan ke layar.

Bentuk lengkap dari pernyataan try dapat dilihat pada bagan berikut, terdiri


dari pernyataan except, else, finally.

Menghasilkan Pengecualian
Dalam membuat aplikasi, ada kemungkinan Anda butuh untuk menghasilkan
pengecualian (raise exceptions), salah satu caranya bisa dengan
menggunakan pengecualian yang sudah ada, hanya ditambahkan informasi
detailnya saja.

Misalnya dalam contoh berikut, Anda mewajibkan sebuah dictionary memiliki


kunci (key) total.
1. >>> d = {'ratarata': '10.0'}

2. >>> if 'total' not in d:                                              

                                                                     

    

3. ...     raise KeyError('harus memiliki total')                        

                                                  

4. ...                                                                  

5. Traceback (most recent call last):                                    

                                                                     

    

6.  File "<stdin>", line 2, in <module>                                  

7. KeyError: 'harus memiliki total'

Fungsi - Definisi, Memanggil, dan Mengembalikan


Fungsi

Fungsi

Di matematika, fungsi adalah proses yang merelasikan antara sebuah


masukan (input) dan keluaran (output). Pada Python, selain fungsi relasi
tersebut, fungsi juga adalah salah satu cara untuk mengorganisasikan kode -
dengan tujuan akhir kode dapat digunakan kembali (reusability).

Beberapa syarat umum fungsi adalah modularisasi dan fungsionalitasnya.


Jadi sebaiknya fungsi hanya memiliki satu kegunaan spesifik namun dapat
digunakan kembali. Fungsi-fungsi umum telah disediakan oleh Python
misalnya print(). Namun Anda dapat selalu mendefinisikan fungsi Anda
sendiri.
Mendefinisikan fungsi

Fungsi didefinisikan dengan keyword def diikuti dengan nama fungsi dan
parameternya dalam kurung (). 
1. def nama_fungsi( parameter )

Secara opsional, Anda dapat menambahkan docstring - string dokumentasi


yang menjelaskan konteks fungsi. Blok kode dalam setiap fungsi dimulai
dengan titik dua dan menggunakan indentasi. Fungsi berhenti ketika terdapat
statement return [expression] yang mengembalikan [expression] kepada
pemanggilnya. Anda juga bisa membuat fungsi tidak mengembalikan
keluaran dengan return None.

Sintaksis fungsi secara lengkap pada Python:


1. def nama_fungsi( parameter ):

2.     "dokumentasi fungsi"

3. statemen atau kode fungsi

4.    return [expression]

Secara default, Python akan memposisikan setiap parameter sesuai dengan


urutan pendaftaran pada saat didefinisikan, dan harus dipanggil sesuai
dengan urutan tersebut. Contoh: fungsi berikut akan menerima sebuah string
sebagai parameter dan mencetaknya.
1. def cetak( param1 ):

2.    print(param1)

3.    return

Sintaksis return tanpa ekspresi atau return None dapat juga tidak dituliskan.
Fungsi di atas akan sama seperti di bawah ini.
1. def cetak( param1 ):

2.     print(param1)

Memanggil Fungsi

Mendefinisikan sebuah fungsi hanya memberikan namanya, menentukan


parameter yang ingin menjadi bagian dari fungsi dan struktur dasar kode
tersebut. Setelah struktur dasar terpenuhi, Anda dapat memanggilnya pada
fungsi yang lain atau dari Python prompt. Contoh berikut untuk memanggil
fungsi printme().
1. def cetak( param1 ):

2.     print(param1)

3.     return

4.  

5. #panggil

6. cetak("Panggilan Pertama")

7. cetak("Panggilan Kedua")

Saat kode diatas dijalankan, akan menghasilkan keluaran berikut:

Output:

Panggilan Pertama
Panggilan Kedua

Return

Pernyataan return [expression] akan membuat eksekusi program keluar dari


fungsi saat itu, sekaligus mengembalikan nilai tertentu. Nilai return yang tidak
mengembalikan (ekspresi) nilai bersifat sama dengan contoh di bawah ini. 
1. return None
Contoh fungsi dengan return:
1. def kali(angka1, angka2):

2.     # Kalikan kedua parameter

3.     hasil = angka1 * angka2

4.     print('Dicetak dari dalam fungsi: {}'.format(hasil))

5.     return hasil

6.  

7. # Panggil fungsi kali

8. keluaran = kali(10, 20);

9. print('Dicetak sebagai kembalian: {}'.format(keluaran))

Saat dipanggil:

Dicetak dari dalam fungsi: 200

Dicetak sebagai kembalian: 200

Nilai kembalian dari sebuah fungsi dapat disimpan dalam sebuah variabel. Ini
yang akan membedakan sebuah fungsi yang mengembalikan nilai dengan
sebuah fungsi yang tidak mengembalikan nilai (sering disebut sebagai
prosedur). Cobalah kode berikut ini:
1. def kuadrat(x):

2.     return x*x

3. a = 10

4. k = kuadrat(a)

5. print('nilai kuadrat dari {} adalah {}'.format(a, k))

Pass by reference vs value


Seluruh parameter (argumen) pada bahasa Python bersifat “passed by
reference”. Artinya saat Anda mengubah sebuah variabel, maka data yang
mereferensi padanya juga akan berubah, baik di dalam fungsi, maupun di
luar fungsi pemanggil. Kecuali jika anda melakukan operasi assignment
yang akan mengubah reference parameter.

Contohnya:
1. def ubah(list_saya):

2.     list_saya.append([1, 2, 3, 4])

3.     print('Nilai di dalam fungsi: {}'.format(list_saya))

4.  

5. # Panggil fungsi ubah

6. list_saya = [10, 20, 30]

7. ubah(list_saya)

8. print('Nilai di luar fungsi: {}'.format(list_saya))

Dapat dilihat dalam kode diatas, objek mylist yang direferensi adalah sama.
Sehingga saat melakukan perubahan, maka perubahannya terjadi pada
mylist baik didalam maupun diluar fungsi ubah:

Nilai di dalam fungsi:  [10, 20, 30, [1, 2, 3, 4]]


Nilai di luar fungsi:  [10, 20, 30, [1, 2, 3, 4]]

Namun Anda harus berhati-hati karena assignment variabel bernama sama


dengan parameter, berarti membuat variabel baru dalam scope lokal dan
tidak terkait dengan variabel global.
1. def ubah(list_saya):

2.     "Deklarasi Variabel list_saya berikut hanya dikenali (berlaku) di

dalam fungsi ubah"

3.     list_saya = [1, 2, 3, 4]

4.     print ('Nilai di dalam fungsi: {}'.format(list_saya))


5.  

6. # Panggil fungsi ubah

7. list_saya = [10, 20, 30]

8. ubah(list_saya)

9. print('Nilai di luar fungsi: {}'.format(list_saya))

Variabel mylist dibuat kembali versi localnya dalam fungsi ubah dengan
operator assignment (sama dengan), sehingga nilai mylist akan berbeda
karena bersifat lokal dalam fungsi ubah saja. Hasilnya akan sebagai berikut:

Nilai di dalam fungsi:  [1, 2, 3, 4]


Nilai di luar fungsi: [10, 20, 30]

Tips: Untuk perubahan parameter sangat disarankan menggunakan keluaran


fungsi

Argumen dan Parameter Fungsi

Apa perbedaan Argumen dan Parameter fungsi? Menurut FAQ Programming


di dokumentasi Python, adalah sebagai berikut:

Parameters are defined by the names that appear in a function definition,


whereas arguments are the values actually passed to a function when calling
it. Parameters define what types of arguments a function can accept. For
example, given the function definition:

Jadi parameter adalah definisi masukan yang diterima fungsi, dan argumen
adalah hal yang Anda masukkan saat memanggil fungsi tersebut.

Contohnya, saat Anda membuat fungsi seperti berikut


1. def fungsi_saya (a, b, c):

2. #lakukansesuatudenganabc

maka a,b,c adalah parameter. Namun saat Anda memanggilnya


1. fungsi_saya (1, b=14, c='Dicoding')

maka 1, 14, dan 'Dicoding' adalah argumen.

Fungsi - Argumen dan Parameter

Argumen yang dapat dikirimkan pada fungsi

Sebagai nilai yang akan dimasukkan pada saat fungsi dipanggil, ada dua
jenis argumen:

 Keyword Argument, yakni argumen yang disertai identifier atau nama


parameter yang secara eksplisit disebutkan. Hal ini termasuk jika kita
mengirimkan nilai melalui dictionary yang diawali dua tanda * (**). 
 Positional Argument, yakni argumen selain keyword argument. Jika kita
mengirimkan variabel bersifat iterable, maka harus diawali tanda *

Contoh:

Keyword Argument
1. daftar(tanggal=1, bulan='Januari', tahun=2020)

2. daftar(**{'tanggal': 1, 'bulan': 'Januari', 'tahun'=2020})

Positional Argument
1. daftar(1,'Januari',2020)

2. daftar(*(1, 'Januari, 2020))

Sintaksis prefix * digunakan sebagai penanda iterable di Python, sedangkan


prefix ** digunakan sebagai penanda kontainer/dictionary.

Kontainer (Dictionary) ini bisa bersifat opsional, artinya tidak wajib diisi (boleh
kosong), jika memang tidak ada argumen yang perlu ditambahkan. Pada saat
diisi, seperti layaknya Dictionary dapat memiliki jumlah/panjang yang
dinamis, dengan pasangan kunci-nilai (key-value) yang bervariasi. 

Susunan/Urutan Parameter Fungsi

Terdapat 5 kemungkinan susunan/urutan parameter fungsi menurut


dokumentasi Python:

 positional-or-keyword: Anda bisa menuliskan argumen sebagai


keyword argument atau positional argument.
1. def kali(nilai1, nilai2=None, nilai3): ...

 positional-only: Anda menentukan bahwa argumen tertentu hanya


dapat diletakkan di posisi tertentu. Hal ini dilakukan dengan cara
mendeklarasi posisi utama kemudian diikuti tanda /. Seperti pada
contoh berikut, nilai1 dan nilai2 merupakan positional only (harus
diletakkan pada posisi tersebut):
1. def (nilai1, nilai2, /, nilai3): ...

 keyword-only: Anda menentukan bahwa argumen tertentu harus


disupply dalam bentuk keyword argument. specifies an argument that
can be supplied only by keyword. Hal ini dilakukan dengan cara
mendeklarasi satu buah var-positional argument diikuti tanda *. Seperti
pada contoh berikut, nilai2 dan nilai3 merupakan keyword-only (harus
dikirim dengan keyword):
1. def func(arg, *, kw_only1, kw_only2): ...

 var-positional dan var-keyword: Anda menentukan bahwa ada


beberapa positional argument dan ada beberapa keyword argument
yang akan Anda proses. var-positional ditandai dengan awalan *
(iterable) dan var-keyword ditandai dengan awalan ** (dictionary).
Contohnya dengan *args yang bersifat var-positional dan **kwargs
yang berupa var-keyword.
1. def func(*args, **kwargs): ...
Jika ada argumen posisi dinamis dan argumen kata kunci (keyword) dinamis,
maka urutannya adalah argumen posisi dahulu, baru argumen kata kunci.
Contoh penggunaan var-positional dan var-keyword pada sebuah berkas
python adalah sebagai berikut:
1. def printinfo(*args, **kwargs):

2.     for a in args:

3.         print('argumen posisi {}'.format(a))

4.     for key, value in kwargs.items():

5.         print('argumen kata kunci {}:{}'.format(key, value))

6.  

7.  

8. # Panggil printinfo

9. printinfo()

10. printinfo(1, 2, 3)

11. printinfo(i=7, j=8, k=9)

12. printinfo(1, 2, j=8, k=9)

13. printinfo(*(2, 3), **{'i':7, 'j':8})

Output:

# printinfo() --> kosong

argumen posisi 1
argumen posisi 2
argumen posisi 3

argumen kata kunci i:7


argumen kata kunci j:8
argumen kata kunci k:9

argumen posisi 1
argumen posisi 2
argumen kata kunci j:8
argumen kata kunci k:9

argumen posisi 2
argumen posisi 3
argumen kata kunci i:7
argumen kata kunci j:8

Fungsi Anonim
Fungsi Anonim (anonymous) tidak dideklarasikan seperti halnya fungsi pada
umumnya dengan kata kunci def, melainkan menggunakan kata kunci
(keyword) lambda. Sebuah fungsi lambda dapat menerima argumen dalam
jumlah berapa pun, namun hanya mengembalikan satu nilai expression.
Fungsi Lambda tidak dapat memuat perintah atau ekspresi lainnya, misalnya
tidak bisa melakukan print.

Fungsi lambda bersifat mandiri, memiliki namespace-nya sendiri, dan tidak


dapat mengakses nilai apapun selain yang berada dalam parameter list dan
variabel global. Meskipun mirip, Lambda tidak dapat disamakan dengan
inline statement pada bahasa C/C++.

Sintaks:
1. lambda [arg1 [,arg2,.....argn]]:expression

Contoh penggunaannya jika kita bandingkan dengan fungsi kali yang berada
di modul sebelumnya
1. kali = lambda nilai1, nilai2: nilai1 * nilai2;

2. print ("Hasil : ", kali( 11, 21 ))

3. print ("Hasil : ", kali( 2, 2 ))

Hasilnya

Hasil : 231
Hasil : 4
Menulis Method dan Kelas pada Python
Module Python adalah berkas teks berekstensi .py yang berisikan kode
Python. Anda dapat mereferensi berkas .py apa pun sebagai modul. Modul-
modul umum yang disediakan oleh Python Standard Library dan mungkin
sudah terinstal secara default pada instalasi Python Anda. PIP juga dapat
dimanfaatkan untuk menginstal modul atau library berikut dengan
dependensi yang dibutuhkannya. Anda pun dapat membuat dan
menghasilkan modul Python Anda sendiri.

Menulis Modul

Menuliskan modul pada bahasa Python dapat dimulai dengan menuliskan


definisi fungsi, kelas, dan variabel yang dapat digunakan kembali pada
program lainnya. Misalkan saja kita membuat berkas hello.py yang akan kita
panggil di berkas lain.

hello.py
1. # Define a function

2. def world():

3.     print("Hello, World!")

Jika hello.py dijalankan, maka program tidak akan menjalankan apapun


karena world() hanya berupa definisi fungsi, kita belum memanggilnya. Jika
kita biasanya memanggil sebuah fungsi dari berkas yang sama di bagian
main, kali ini kita akan membuat berkas lain main.py yang seolah mengimpor
hello.py. Pastikan hello.py dan main.py berada dalam satu direktori agar
dapat diimpor dan dipanggil.

main.py
1. #impor

2. import hello

3.

4. #panggil
5. hello.world()

Saat memanggil sebuah fungsi dari modul yang kita impor, jangan lupa untuk
menambahkan nama modulnya diikuti tanda titik, baru fungsi yang akan kita
panggil. Dalam hal ini karena kita mengimpor hello.py, maka cukup kita tulis
import hello, dan saat memanggilnya dengan hello.world(). Selain itu, kita
juga dapat menggunakan from ... import ..., dalam hal ini adalah from hello
import world dan memanggil fungsinya langsung yakni world().

Sekarang, saat memanggil main.py, maka akan menghasilkan:

Hello, World!

Menambahkan variabel

Menambahkan variabel pada modul hello, tambahkan variabel nama,


misalnya Dicoding.

hello.py
1. def world():

2.     print("Hello, World!")

3.

4. nama = "Dicoding"

Berikutnya, kita coba cetak variabel nama.

main.py
1. #impor

2. import hello

3.  

4. #panggil

5. hello.world()
6.

7. #cetak

8. print(hello.nama)

Saat Dijalankan:

Hello, World!
Dicoding

Menambahkan kelas

Contoh yang lain, mari tambahkan kelas di modul hello. Kita akan membuat
kelas Reviewer dengan atribut nama dan kelas, serta fungsi review() yang
akan mencetak atribut yang telah didefinisikan.

hello.py
1. def world():

2.     print("Hello, World!")

3.

4. nama = "Dicoding"

5.

6. class Reviewer:

7.     def __init__(self, nama, kelas):

8.         self.nama = nama

9.         self.kelas = kelas

10.

11.     def review(self):

12.         print("Reviewer " + self.nama + " bertanggung jawab di kelas " +

self.kelas)
Tambahkan kelas pada main.py.

main.py
1. #impor

2. import hello

3.

4. #panggil

5. hello.world()

6.

7. #cetak

8. print(hello.nama)

9.

10. #review

11. diko = hello.Reviewer("Diko", "Python")

12. diko.review()

Seperti umumnya kelas pada bahasa pemrograman lainnya, Fungsi dan


Atributnya dapat diakses setelah kita melakukan instansiasi. Fungsi Review
adalah fungsi yang melekat pada kelas Reviewer. Kita juga dapat memanggil
diko.Nama atau diko.Kelas sebagai atribut yang melekat di kelas tersebut.

Output:

Hello, World!
Dicoding
Reviewer Diko bertanggung jawab di kelas Python

Lihat kedua variabel "nama" yang dapat menghasilkan dua nilai berbeda,
karena nama yang pertama (hello.nama) melekat pada modul, sementara
diko. Nama adalah atribut nama pada kelas Reviewer. Anda harus cukup
berhati-hati dalam memastikan variabel seperti pada pembahasan fungsi
yang lalu.

Implementasi Kode

Seringkali, modul dimanfaatkan untuk dapat memisahkan antara definisi dan


implementasi kode. Namun modul juga dapat berfungsi selayaknya program
pada umumnya, yang juga langsung mengeksekusi dalam modul itu sendiri.
Contohnya, kita buat hello2.py seperti berikut:

hello2.py
1. # Definisi

2. def world():

3.     print("Hello, World!")

4.

5. # Panggil disini

6. world()

Kemudian bersihkan main.py hingga menyisakan import hello2 saja.

main.py
1. import hello2

Saat main_program dijalankan, langsung muncul:

Hello, World!

Sehingga modul dapat digunakan dengan berbagai metode pemanggilan,


bergantung pada definisi, maupun implementasi.
Mengakses Modul dari Folder Lain
Jika Anda bekerja dengan beberapa proyek secara paralel, berikut adalah
opsi untuk mengakses modul dari folder lain:

Menambahkan path folder

Opsi ini dipilih umumnya di tahap awal pengembangan, sebagai solusi


temporer. Untuk mengetahui path pemanggilan utama, Anda perlu bantuan
dari modul sys yang sudah tersedia. Impor modul sys di main program dan
gunakan fungsi sys.path.append. Misalnya berkas hello.py kita berada di
direktori /home/dicoding/ dan main.py di direktori lainnya. Anda cukup
menambahkan path /home/dicoding pada main.py seperti di bawah:
1. import sys

2. sys.path.append('/home/dicoding')

3.

4. import hello

5. …

Menambahkan modul pada Python Path

Alternatif ini dapat dipilih saat Anda melakukan pemanggilan modul >1x.
Pada intinya pilihan ini akan menambahkan modul yang Anda buat pada
Path yang diperiksa oleh Python sebagai modul dan paket-paket bawaan.
Anda dapat memanfaatkan sys.path kembali untuk mengetahui posisi Anda
saat ini.
1. print(sys.path)

Anda mungkin akan menerima output seperti berikut, sangat bergantung


dengan jenis environment Anda, tapi pilihlah (atau cobalah satu per satu) jika
ada beberapa output.

'/home/dicoding/my_env/lib/python3.5/site-packages'
Pindahkan hello.py pada direktori di atas. Maka Ia akan dikenali sebagai
sebuah modul yang dapat diimpor oleh siapa saja dalam environment
tersebut.

Pada main_program.py cukup impor.


1. import hello

Pastikan path yang Anda assign tepat untuk menghasilkan pemanggilan


yang tepat. Modul yang tersebar pada beberapa folder mungkin akan
menghasilkan galat. Usahakan peletakan yang se-sederhana mungkin.

Pengenalan Pemrograman Berorientasi Objek (OOP)


dengan Python - Class, Objek, dan Method
Kelas atau dalam bahasa Inggris disebut class, merupakan sebuah konsep
yang menyediakan sarana untuk menyatukan data dan fungsionalitas secara
satu kesatuan. Membuat sebuah kelas artinya membuat sebuah tipe baru,
kemudian dengan membuat instance dari kelas tersebut akan menghasilkan
objek baru dari tipe tersebut. Setiap objek (hasil instance dari kelas tersebut)
dapat memiliki atribut untuk mengelola status dari objek tersebut, juga dapat
memiliki metode untuk mengubah status atau informasinya.

Catatan:

 Kata objek adalah terjemahan bahasa Inggris dari kata object.


 Kata metode adalah terjemahan bahasa Inggris dari kata method.

Selanjutnya kita akan mempelajari secara mendalam implementasi kelas dan


fitur-fitur terkait di bahasa pemrograman Python.

Class
Class merupakan sintaksis di Python yang menyediakan semua fitur-fitur
standar dari Pemrograman Berorientasi Objek atau dalam bahasa Inggris
disebut dengan Object Oriented Programming (OOP).

Definisi dari kelas menggunakan sintaksis class seperti hanya definisi fungsi
yang menggunakan sintaksis def, kemudian perlu dipanggil (dieksekusi)
dahulu sebelum dapat digunakan dan memiliki efek pada program.
1. class NamaKelas:

2.     pass  # gantikan dengan pernyataan-pernyataan, misal: atribut atau

metode

Pada pemanggilan sintaksis class tersebut, setelah seluruh pernyataan-


pernyataan semuanya selesai diproses (didaftarkan sebagai atribut ataupun
metode), maka kelas sudah dibuat dan dapat digunakan.

Sebuah kelas sendiri mendukung dua macam operasi:

1. Mengacu pada atribut.


2. Pembuatan instance atau dalam bahasa Inggris disebut instantiation.

Agar lebih jelas, kita akan membahas menggunakan contoh berikut.


1. class Kalkulator:

2.     """contoh kelas kalkulator sederhana"""

3.     i = 12345

4.  

5.     def f(self):

6.         return 'hello world'

Dari pembuatan class Kalkulator di atas, di dalamnya ada definisi


atribut i dan definisi fungsi f.

Proses mengacu atribut yaitu Kalkulator.i dan Kalkulator.f sesuai definisi


akan mengembalikan nilai integer dan fungsi. Pada proses mengacu atribut
tersebut juga dapat mengubah nilainya, misalnya dengan memberikan
bilangan bulat lain ke Kalkulator.i akan mengubah nilai yang ada saat ini.
1. Kalkulator.i = 1024  # maka nilai atribut i dalam Kalkulator berubah

dari 12345 menjadi 1024

Objek (object: an instance of a class)


Pembahasan berikutnya adalah instantiation dari sebuah class,
menggunakan notasi fungsi yaitu dengan kurung buka-kurung tutup, akan
menghasilkan sebuah objek. Kemudian hasil instantiation ini biasanya
disimpan dalam sebuah variabel dengan nama yang representatif.

Berikut ini adalah contoh membuat instance dari class


Kalkulator menghasilkan sebuah objek.
1. k = Kalkulator()  # membuat instance dari kelas jadi objek, kemudian

disimpan pada variabel k

Sebagai hasil instance sebuah class, suatu objek memiliki atribut dan metode
yang didapatkan dari class. Sebuah metode atau dalam bahasa Inggris
disebut method, adalah sebuah fungsi khusus yang menjadi "milik" suatu
objek. 

Untuk memanggil metode f dari objek k, hasil instance dari class Kalkulator di


atas sebagai berikut.
1. print(k.f())  # akan mencetak hello world ke layar

Kenapa metode adalah sebuah fungsi khusus?


Jika diperhatikan kembali fungsi f dalam definisi class Kalkulator memiliki
satu argumen bernama self, sedangkan dalam pemanggilan metode dari
objek k di atas tidak menggunakan argumen. Apabila f adalah fungsi biasa
pada Python tentu pemanggilan ini akan mengembalikan kesalahan (error).
Lebih detail mengenai konvensi ini akan dibahas pada bagian metode
dari class.
Pembahasan lebih lanjut mengenai metode dari class ada di bagian
selanjutnya.

Class’ Constructor
Kembali membahas proses instantiation dari class, sering ditemui kebutuhan
mengeset nilai awal atau kondisi awal dari atribut yang dimiliki oleh class
tersebut, sehingga untuk kebutuhan ini digunakan sebuah fungsi khusus
yang biasa disebut sebagai pembangun atau dalam bahasa Inggris
disebut constructor. Di Python, fungsi khusus atau metode sebagai
constructor ini bernama __init__ atau biasa diucapkan sebagai "double
underscore init". Pada saat dilakukan instantiation dari class, metode __init__
ini secara otomatis akan dipanggil di terlebih dahulu.

Berikut adalah definisi class Kalkulator di atas jika diubah dengan


menggunakan constructor.
1. class Kalkulator:

2.     """contoh kelas kalkulator sederhana"""

3.  

4.     def __init__(self):

5.         self.i = 12345

6.  

7.     def f(self):

8.         return 'hello world'

Nilai dari atribut i tidak terdefinisi pada awal definisi Kalkulator, setelah


dilakukan instantiation maka nilai atribut i akan bernilai 12345. Meskipun bisa
mendefinisikan variabel i sebagai atribut dari class Kalkulator, tetapi
sebaiknya berhati-hati mengenai variabel yang akan terbagi (shared) untuk
semua instance dari class, terutama untuk tipe yang dapat berubah
(mutable), misalnya list dan dictionary.
referensi: https://docs.python.org/id/3.8/tutorial/classes.html#class-and-
instance-variables
1. class KeranjangBelanja:

2.     """contoh tidak baik dilakukan dengan definisi variabel terbagi"""

3.     isi = []  # menggunakan list di sini akan terbagi untuk semua

instance. JANGAN DILAKUKAN

Lanjut pembahasan constructor, dengan dilengkapi constructor pun


proses instantiation tidak berubah dari sebelumnya.
1. k = Kalkulator()  # membuat instance dari kelas jadi objek, kemudian

disimpan pada variabel k

Lebih lanjut tentang constructor, tentu saja untuk mendukung aplikasi yang


lebih dinamis maka constructor dapat memiliki parameter yang bisa
dikirimkan saat proses instantiation, bahkan parameternya bisa lebih dari
satu jika diperlukan.

Pada contoh berikut ini, constructor memiliki parameter i yang bersifat


opsional, apabila dalam proses instantiation tidak dikirimkan parameter,
secara otomatis i akan diisi nilai bawaan 12345.
1. class Kalkulator:

2.     """contoh kelas kalkulator sederhana"""

3.  

4.     def __init__(self, i=12345):

5.         self.i = i  # i adalah variabel pada constructor, self.i

adalah variabel dari class

6.  

7.     def f(self):

8.         return 'hello world'

Dengan contoh pemanggilan berikut.


1. k = Kalkulator(i=1024)  # melakukan instantiation sekaligus mengisi

atribut i jadi 1024

2. print(k.i)             # mencetak atribut i dari objek k dengan

keluaran nilai 1024

Metode (Method)
Pembahasan lebih detail mengenai metode, selain yang dibahas
sebelumnya, kita akan membahas 3 jenis metode:

1. Metode dari objek (object method)


2. Metode dari class (class method)
3. Metode secara static (static method)

Pertama kita membahas metode dari objek, seperti yang sempat dijelaskan
secara singkat di atas mengenai metode, atau dalam bahasa Inggris disebut
method, secara umum metode adalah sebuah fungsi khusus yang menjadi
“milik” suatu objek, yakni hasil instantiation dari class.

Salah satu hal khusus yang dimiliki oleh metode dengan adanya argumen
bernama self, Anda tentu bertanya-tanya tentang argumen self pada metode-
metode dalam kelas tersebut sebetulnya apa?
Argumen pertama dari metode-metode dalam class, biasa diberikan nama
self sebagai suatu konvensi atau standar penamaan, meskipun Anda bisa
juga menggunakan nama lain. Bahkan dalam Python tidak ada arti khusus
tentang sintaksis self ini, namun sangat disarankan menggunakan konversi
ini agar program Python yang Anda buat akan lebih mudah dimengerti oleh
pemrogram lainnya. 

Seperti yang Anda sudah perkirakan, untuk sebuah metode, sebetulnya


dikirimkan objek (hasil instance dari class) sebagai argumen pertamanya,
dalam hal ini bernama self.

Misalnya menggunakan contoh di atas, jika k adalah objek hasil instance


dari class Kalkulator, saat melakukan pemanggilan metode f.
1. k.f()
ekuivalen dengan
1. Kalkulator.f(k)

Argumen self pada metode f akan diisi dengan objek hasil instance dari class


Kalkulator.

Sebelum kita membahas yang kedua dan ketiga, yakni metode dari class dan
metode secara static, Anda tentu mengingat bahwa sebelumnya sudah
belajar fungsi-fungsi bawaan (built-in) dari Python, antara
lain: open, sorted, int, str, dan sejumlah lainnya. Terkait metode, ada dua
fungsi bawaan yang akan kita bahas, yakni classmethod dan staticmethod.

Catatan:

fungsi decorator adalah sebuah fungsi yang mengembalikan fungsi lain,


biasanya digunakan sebagai fungsi transformasi dengan "pembungkus"
sintaksis @wrapper.

Referensi: https://docs.python.org/id/3.8/glossary.html#term-decorator .

Classmethod adalah sebuah fungsi yang mengubah metode menjadi metode


dari class (class method). Dalam penggunaannya, fungsi ini dijadikan
sebagai fungsi decorator @classmethod, kemudian pemanggilannya bisa
langsung dari class yang terdefinisi ataupun melalui objek.
Metode dari class (class method) menerima masukan class secara implisit
sebagai argumen pertama yang secara konvensi diberikan nama cls.

Berdasar contoh yang sama dengan class sebelumnya, berikut adalah


metode dari class.
1. class Kalkulator:

2.     """contoh kelas kalkulator sederhana"""

3.  

4.     def f(self):

5.         return 'hello world'

6.  

7.     @classmethod
8.     def tambah_angka(cls, angka1, angka2):

9.         return '{} + {} = {}'.format(angka1, angka2, angka1 + angka2)

Nampak pada kode, sesuai konvensi ada metode yang menggunakan


argumen pertama self, sedangkan untuk class method menggunakan
konvensi argumen pertama cls. 

Untuk melakukan pemanggilan dari class, dilakukan seperti berikut, dimana


argumen pertama cls sudah mendapatkan masukan class Kalkulator.
1. Kalkulator.tambah_angka(1, 2)  # tanpa perlu memberikan masukan untuk

argumen cls

Metode dari class (class method) juga dapat dipanggil dari objek, hasil


instantiation dari class Kalkulator, contohnya mirip seperti pemanggilan
metode dari objek (object method).
1. k = Kalkulator()

2. print(k.tambah_angka(1, 2))

Staticmethod adalah sebuah fungsi yang mengubah metode menjadi metode


statis (static method). Dalam penggunaannya, fungsi ini dijadikan sebagai
fungsi decorator @staticmethod, kemudian pemanggilannya bisa langsung
dari class yang terdefinisi ataupun melalui objek.
Metode statis (static method) tidak menerima masukan argumen pertama
secara implisit.

Untuk Anda yang pernah memrogram Java atau C++, metode statis ini mirip
seperti yang ada di bahasa pemrograman tersebut.

Berdasar contoh yang sama dengan class sebelumnya, berikut adalah


metode statis.
1. class Kalkulator:

2.     """contoh kelas kalkulator sederhana"""

3.  
4.     def f(self):

5.         return 'hello world'

6.  

7.     @staticmethod

8.     def kali_angka(angka1, angka2):

9.         return '{} x {} = {}'.format(angka1, angka2, angka1 * angka2)

Nampak pada kode, tidak ada argumen pertama yang implisit seperti halnya
pada dua metode sebelumnya.

Pemanggilan dari class seperti halnya pemanggilan fungsi biasa.


1. a = Kalkulator.kali_angka(2, 3)

2. print(a)

Metode statis (static method) juga dapat dipanggil dari objek, hasil
instantiation dari class Kalkulator, mirip seperti pemanggilan fungsi biasa
meskipun dipanggil dari objek.
1. k = Kalkulator()

2. a = k.kali_angka(2, 3)

3. print(a)

Pengenalan Pemrograman Berorientasi Objek (OOP) -


Inheritance

Mekanisme Pewarisan (Inheritance)

Paradigma Pemrograman Berorientasi Objek memiliki konsep pewarisan atau


dalam bahasa Inggris disebut inheritance, tentunya di Python mendukung
fitur ini.
Suatu kelas B dapat mewarisi kelas A, sehingga secara otomatis
memiliki semua fitur yang dimiliki oleh kelas A, dalam hal ini atribut-atribut
dan metode-metode.

Dalam contoh ini, kelas A disebut sebagai kelas dasar, yakni kelas yang
memberikan warisan atau biasa juga disebut kelas yang diturunkan.

Kemudian kelas B disebut sebagai kelas turunan, yakni kelas yang


mendapatkan warisan.
Jika di kelas B memiliki metode dengan nama yang sama dengan yang
dimiliki kelas A, maka metode tersebut akan menimpa metode yang
diwariskan dari kelas A.

Catatan:

 Frasa kelas dasar adalah terjemahan bahasa Inggris dari frasa base
class.
 Frasa kelas turunan adalah terjemahan bahasa Inggris dari
frasa derived class.
 Frasa menimpa metode adalah terjemahan bahasa Inggris dari frasa
method override.
 Di Python, mekanisme pewarisan memungkinkan untuk memiliki lebih
dari satu kelas dasar (kelas orang tua, yang diwarisi).

Referensi: https://docs.python.org/id/3.8/tutorial/classes.html#multiple-
inheritance

Kita akan mengembangkan aplikasi yang sudah dimiliki di atas, class


Kalkulator sebagai kelas dasar yang mempunyai fungsi melakukan
penambahan melalui metode tambah_angka.
1. class Kalkulator:
2.     """contoh kelas kalkulator sederhana. anggap kelas ini tidak boleh

diubah!"""

3.  

4.     def __init__(self, nilai=0):

5.         self.nilai = nilai

6.  

7.     def tambah_angka(self, angka1, angka2):

8.         self.nilai = angka1 + angka2

9.         if self.nilai > 9:  # kalkulator sederhana hanya memroses

sampai 9

10.             print('kalkulator sederhana melebihi batas angka:

{}'.format(self.nilai))

11.         return self.nilai

Kemudian kita punya kebutuhan membuat sebuah kelas yang punya fitur
perkalian tapi juga punya fitur penambahan, dalam contoh ini misalnya kita
tidak boleh mengubah kalkulator yang sudah ada. Dibandingkan dengan
membuat kelas baru kemudian menuliskan kembali implementasi
penambahan angka, maka mewarisi kelas yang sudah ada akan lebih efisien.

Dari situ, kita membuat class KalkulatorKali yang mewarisi class Kalkulator.


1. class KalkulatorKali(Kalkulator):

2.     """contoh mewarisi kelas kalkulator sederhana"""

3.  

4.     def kali_angka(self, angka1, angka2):

5.         self.nilai = angka1 * angka2

6.         return self.nilai
Dengan pemanggilan class KalkulatorKali sebagai berikut.
1. kk = KalkulatorKali()

2. a = kk.kali_angka(2, 3)  # sesuai dengan definisi class memiliki fitur

kali_angka

3. print(a)

4.  

5. b = kk.tambah_angka(5, 6)  # memiliki fitur tambah_angka karena

mewarisi dari Kalkulator

6. print(b)

Dengan melakukan pewarisan, Anda dengan mudah bisa menambahkan


(extend) kemampuan dari suatu class dengan fitur yang ingin Anda buat
sendiri. Hal tersebut akan sangat berguna jika Anda ingin membuat aplikasi
yang mudah diguna-ulang (reusable).

Menimpa (Override) Metode dengan Nama yang Sama Dengan Kelas


Dasar

Anda melihat bahwa kalkulator yang anda operasikan mendapatkan


peringatan melebihi batas angka yang bisa diproses? Lalu bagaimana kalau
Anda ingin mengubah keterbatasan itu? Meski dalam contoh ini anggap tetap
tidak boleh mengubah class Kalkulator yang sudah ada.

Dalam proses pewarisan, kita bisa menimpa (override) definisi metode yang
dimiliki oleh kelas dasar (kelas orang tua, yang diwarisi) dengan nama
metode yang sama. Misalnya kita menimpa metode tambah_angka untuk
menghilangkan batasan yang dimiliki.
1. class KalkulatorKali(Kalkulator):

2.     """contoh mewarisi kelas kalkulator sederhana"""

3.  

4.     def kali_angka(self, angka1, angka2):


5.         self.nilai = angka1 * angka2

6.         return self.nilai

7.  

8.     def tambah_angka(self, angka1, angka2):

9.         self.nilai = angka1 + angka2

10.         return self.nilai

Kemudian kita coba kembali, apakah batasan yang dimiliki sudah hilang?
1. kk = KalkulatorKali()

2.  

3. b = kk.tambah_angka(5, 6)  # fitur tambah_angka yang dipanggil milik

KalkulatorKali

4. print(b)

Pemanggilan Metode Kelas Dasar dari Kelas Turunan dengan Sintaksis


Super

Anggaplah fungsi tambah_angka adalah sebuah fungsi yang rumit, dimana


kita sebaiknya gunakan saja kemampuan yang sudah ada di kelas dasar,
kemudian kita hanya ubah sebagian fiturnya saja dengan yang kita inginkan.
1. class KalkulatorTambah(Kalkulator):

2.     """contoh mewarisi kelas kalkulator sederhana"""

3.  

4.     def tambah_angka(self, angka1, angka2):

5.         if angka1 + angka2 <= 9:  # fitur ini sudah oke di kelas

dasar, gunakan yang ada saja


6.             super().tambah_angka(angka1, angka2)  # panggil fungsi

dari Kalkulator lalu isi nilai

7.         else:  # ini adalah fitur baru yang ingin diperbaiki dari

keterbatasan kelas dasar

8.             self.nilai = angka1 + angka2

9.         return self.nilai

Variabel Privat di Python

Jika Anda sebelumnya pernah belajar bahasa pemrograman yang memiliki


variabel privat, dimana variabel tersebut tidak dapat diakses kecuali dari
objek yang bersangkutan, di Python hal tersebut tidak ada.

Terkait variabel privat tersebut, di Python ada konvensi dimana penggunaan


nama yang diawali dengan garis bawah (underscore), baik itu fungsi, metode,
maupun anggota data, akan dianggap sebagai non-publik.

Pernak-Pernik Terkait Struktur Data

Buat Anda yang pernah membuat program dengan menggunakan bahasa


pemrograman C atau Pascal, Anda mungkin tertarik untuk membuat sebuah
struktur data seperti halnya struct pada C atau record pada Pascal, bertujuan
menyatukan sejumlah penamaan item data menjadi satu.

Dalam Python, dimana Anda sebelumnya pernah mempelajari


mengenai duck typing, maka Anda cukup mendefinisikan saja sebuah class
kosong, selanjutnya penamaan item data dapat secara langsung
didefinisikan dan diisikan saat sudah instantiation.
1. class Pegawai:

2.     pass  # definisi class kosong

3.  
4. don = Pegawai()  # membuat Pegawai baru menjadi objek bernama don

5.  

6. # tambahkan item data pada objek sebagai record

7. don.nama = 'Don Doo'

8. don.bagian = 'IT'

9. don.gaji = 999

Unit Testing
Sampai di tahap ini, sudah banyak modul pemrograman Python yang kita
dipelajari. Kita telah mengenal operasi-operasi dasar di Python seperti
perulangan, fungsi, hingga OOP pada Python.

Ketika aplikasi yang kita kembangkan nantinya semakin kompleks, akan


muncul dependensi yaitu satu atau lebih fungsi digunakan oleh fungsi lain.
Atau bahkan ketika kita mulai membangun aplikasi dengan rekan kita, kita
membuat fungsi yang digunakan oleh rekan kita, ataupun sebaliknya.

Pada saat membuat fungsi baru ataupun mengubah fungsi yang sudah ada,
tentunya perlu dipastikan bahwa fungsionalitas aplikasi yang sebelumnya
tidak terganggu dengan adanya perubahan baru tersebut. Bagaimana jika
fungsionalitas bukan hanya 5 atau 10, tapi lebih dari itu? Tentu menyulitkan
sekali untuk mengeceknya satu per satu setiap kita melakukan perubahan.

Di sinilah kita butuh pengujian (test) untuk fungsi-fungsi tersebut yang dapat
dilakukan secara otomatis. Kita dapat melakukan ini dengan salah
satu library bawaan Python yaitu unittest, yang penamaannya sesuai
dengan tugas yang dilakukannya. Unittest merupakan proses pengujian
perangkat lunak yang memastikan setiap unit/fungsi dari program teruji. Jika
fungsionalitas dari aplikasi yang kita bangun terdiri dari prosedur-prosedur
dan fungsi-fungsi yang kita tulis, maka kita perlu melakukan unit test untuk
setiap prosedur atau fungsi yang ada.

Sebagai sebuah framework pengujian, unittest mendukung beberapa hal


esensial sebagai berikut:

 Pengujian secara otomatis


 Kode awal proses (setup) dan akhir proses (shutdown) yang dapat
digunakan ulang
 Penyatuan sejumlah pengujian dalam sebuah koleksi
 Terpisahnya framework pengujian dari framework pelaporan (reporting)

Library unittest mendukung sejumlah konsep penting yang berorientasi objek,


antara lain:

 Test fixture merepresentasikan persiapan yang dibutuhkan untuk


melakukan satu pengujian atau lebih, serta proses pembersihannya
(cleanup). Beberapa contohnya antara lain: menyiapkan basis data
pengujian, direktori pengujian, atau mengaktifkan sebuah proses
server.

 Test case adalah sebuah unit dari pengujian, di mana ia mengecek


sejumlah respons dari sebagian kelompok masukan. unittest
menyediakan basis class, TestCase, yang akan digunakan untuk
membuat kasus pengujian baru.

 Test suite adalah sebuah koleksi dari kasus-kasus pengujian, koleksi


dari test suite itu sendiri, atau gabungan keduanya. Hal ini berguna
untuk mengumpulkan pengujian-pengujian yang akan dieksekusi
bersama.

 Test runner adalah komponen yang akan mengatur (orchestrates)


eksekusi dari pengujian-pengujian dan menyediakan keluaran untuk
pengguna. Dalam hal ini runner dapat menggunakan tampilan grafis,
tampilan tekstual, atau mengembalikan nilai spesial yang menyatakan
hasil dari pengujian.

Contoh Unit Test di Python


Tulis kode ini pada IDE PyCharm atau simpan kode ini dalam format .py dan
jalankan pada Command Prompt di perangkat Anda.
1. import unittest

2.  
3. class TestStringMethods(unittest.TestCase):

4.     

5.     def test_strip(self):

6.      

  self.assertEqual('www.dicoding.com'.strip('c.mow'), 'dicoding')

7.     

8.     def test_isalnum(self):

9.         self.assertTrue('c0d1ng'.isalnum())

10.         self.assertFalse('c0d!ng'.isalnum())

11.     

12.     def test_index(self):

13.         s = 'dicoding'

14.         self.assertEqual(s.index('coding'), 2)

15.         # cek s.index gagal ketika tidak ditemukan

16.         with self.assertRaises(ValueError):

17.             s.index('decode')

18.     

19. if __name__ == '__main__':

20.     unittest.main()

Jalankan program di atas. Hasil keluarannya seperti berikut.


Mari kita bahas satu per satu dari kode di atas.

 Kelas TestStringMethods merupakan sebuah kelas yang merupakan


turunan (subclass) dari class unittest.TestCase, sehingga proses test
dapat dilangsungkan tanpa banyak implementasi lain.

 Ada 3 metode pada class tersebut yang semua namanya diawali


dengan kata test, hal ini merupakan konvensi (aturan) yang wajib diikuti
untuk menginformasikan ke test runner bahwa sejumlah metode
tersebut merepresentasikan test yang akan dioperasikan.

 Pada setiap metode, pengujian dilakukan dengan pemanggilan assert.


Pada metode test_strip dilakukan pengecekan kesamaan
menggunakan assertEqual untuk memastikan
bahwa 'www.dicoding.com'.strip('c.mow') sama dengan ‘dicoding’.

 Pada metode test_isalnum dilakukan pengecekan apakah fungsi


bernilai benar (True), dengan assertTrue untuk memastikan
bahwa 'c0d1ng'.isalnum() bernilai benar di mana ‘cOd1ng’ adalah betul
bertipe alfanumerik . Kemudian juga ada pengecekan apakah fungsi
bernilai salah (False) dengan assertFalse untuk memastikan
bahwa 'c0d!ng'.isalnum() betul bernilai salah karena ada karakter yang
bukan alfanumerik yaitu ‘!’.

 Pada metode test_index dilakukan pengecekan kesamaan seperti


sebelumnya dengan menggunakan assertEqual bahwa pencarian
substring coding menempati index sama dengan 2. Kemudian juga ada
pengecekan apakah akan membangkitkan ValueError dengan
menggunakan assertRaises(ValueError), jika pencarian index tidak
berhasil ditemukan pada string yang sudah ditentukan.

 Pada bagian terakhir kode ada pemanggilan unittest.main() untuk mulai


menjalankan test.

Selanjutnya kita akan membahas hasil keluarannya. Tampak pada keluaran


bahwa ada 3 tanda titik (...) yang menyatakan bahwa ketiga fungsi yang dites
berhasil melewati test. Dirangkum juga waktu pemrosesan dari total
3 test tersebut berlangsung sangat cepat selama 0.00 detik. serta di baris
paling akhir adalah rangkuman bahwa semua test berlangsung sukses (OK).

Anda bisa mencoba melihat keluaran lain dengan membuat gagal salah
satu test. Misalnya pada metode test_isalnum keduanya akan diubah
menggunakan assertTrue sehingga salah satu fungsi akan gagal. Kodenya
bisa Anda lihat di bawah.
1. def test_isalnum(self):

2. self.assertTrue('c0d1ng'.isalnum()) # ini akan berhasil

3. self.assertTrue('c0d!ng'.isalnum()) # ini akan gagal

Kemudian jalankan kembali program Anda. Keluarannya akan seperti berikut:

Berikut penjelasannya:

 Seperti yang sudah Anda duga bahwa, akan ada pengujian yang gagal,
sehingga tertulis .F. yang menggambarkan bahwa pengujian metode
kedua gagal (FAIL).

 Berikutnya dijelaskan bahwa kegagalan ada di metode test_isalnum,


yaitu sebuah metode dari class __main__.TestStringMethods.

 Lebih jauh, diinformasikan bahwa test_isalnum yang gagal berada


pada baris ke 10 pada kode Anda, yakni pada
pengecekan self.assertTrue('c0d!ng'.isalnum()) yang memang tadi kita
ubah dari assertFalse. Sistem pengujian juga melaporkan bahwa
pembandingannya tidak sesuai yakni False tidak bernilai benar seperti
yang diharapkan dengan adanya pengujian assertTrue.

 Rekap totalnya ada 3 tests yang dilakukan dalam 0.01 detik. Kemudian
secara umum test menghasilkan 1 buah kegagalan (failure).

Cukup mudah dimengerti bukan? Kita dapat melihat sendiri bahwa pengujian
hasilnya gagal. Tapi kali ini gagalnya memang sesuai dengan harapan kita.
Sekarang kita coba pengujian dengan contoh yang lebih nyata, misalnya kita
memiliki class User di mana kita akan menguji aktif atau tidaknya user
dengan melihat apakah dia terkoneksi ke basis data (DB) atau tidak.

Untuk menyederhanakan kodenya dan lebih fokus pada pengujiannya, tulis


simulasinya dalam 1 file kode sebagai berikut:
1. import unittest

2.  

3. def koneksi_ke_db():

4. print('[terhubung ke db]')

5. def putus_koneksi_db(db):

6.     print('[tidak terhubung ke db {}]'.format(db))

7.  

8. class User:

9. username = ''

10. aktif = False

11. def __init__(self, db, username): # using db sample

12. self.username = username

13. def set_aktif(self):

14. self.aktif = True

15.  

16. class TestUser(unittest.TestCase):

17. def test_user_default_not_active(self):

18. db = koneksi_ke_db()

19. dicoding = User(db, 'dicoding')

20. self.assertFalse(dicoding.aktif) # tidak aktif secara

default
21. putus_koneksi_db(db)

22.  

23. def test_user_is_active(self):

24. db = koneksi_ke_db()

25. dicoding = User(db, 'dicoding')

26. dicoding.set_aktif() # aktifkan user baru

27. self.assertTrue(dicoding.aktif)

28. putus_koneksi_db(db)

29.  

30. if __name__ == '__main__':

31. unittest.main()

Sama seperti sebelumnya, kita akan membuat sebuah class TestUser yang


merupakan turunan dari class unittest.TestCase, kemudian menulis 2 metode
untuk pengujian kali ini.

Karena setiap test itu dioperasikan secara terpisah, akhirnya kita


menjalankan fungsi koneksi ke basis data dan membuat User dicoding setiap
kali proses test. Hal tersebut bukan praktik yang baik karena memakan lebih
banyak memori apalagi jika program yang kita uji berukuran besar. Lalu apa
praktik yang lebih baik?

Kita akan menggunakan metode bawaan dari class TestCase, yakni metode


setUp() dan tearDown().

 Metode setUp() akan dipanggil untuk menyiapkan test sehingga


pemanggilannya akan dilakukan setiap sebelum metode test
dilaksanakan.

 Metode tearDown() akan dipanggil setiap setelah metode test selesai


dilaksanakan, meskipun terjadi kesalahan (exception) pada proses test.

Kode sebelumnya akan kita ubah dengan implementasi kedua metode


setUp() dan tearDown(). Kita cukup melakukan perubahan pada class
TestUser saja seperti di bawah.
1. class TestUser(unittest.TestCase):

2. def setUp(self):

3. self.db = koneksi_ke_db()

4. self.dicoding = User(self.db, 'dicoding')

5.  

6. def tearDown(self):

7. putus_koneksi_db(self.db)

8.

9. def test_user_default_not_active(self):

10. self.assertFalse(self.dicoding.aktif) # tidak aktif secara

default

11.  

12. def test_user_is_active(self):

13. self.dicoding.set_aktif() # aktifkan user baru

14. self.assertTrue(self.dicoding.aktif)

Kemudian jalankan kembali program Anda. Hasil keluarannya seperti berikut.

Terlihat bahwa setiap kali melakukan pengujian, metode setUp() dipanggil.


Begitu juga setelah selesai pengujian, metode tearDown() dipanggil.

Dengan kemampuan pengujian ini, aplikasi yang Anda buat jadi lebih lebih
teruji atau orang biasa bilang dengan istilah lebih tahan banting (robust).
Library Populer pada Python
Kali ini kita akan membahas Modul dan Library yang sering digunakan pada
Python. Artikel ini akan terus di-update sesuai dengan perkembangan dan
jika diperlukan akan ditambah. Modul yang sering dipakai secara umum
dalam scripting  sehari-hari antara lain:

String 
Dokumentasi: https://docs.python.org/3/library/string.html .
String merupakan salah satu modul bawaan Python yang tidak perlu
dideklarasikan. Modul yang sudah bawaan dari Python disebut modul built-in
(https://docs.python.org/3/library/stdtypes.html ). Termasuk di dalam modul
built in antara lain adalah string, list, range, boolean operator, dan
sebagainya. Pada modul string terdapat fungsi-fungsi yang dapat
dioperasikan pada variabel bertipe string seperti di bawah. 

 upper(): Ubah setiap huruf dalam string menjadi huruf kapital. 


 lower(): Ubah setiap huruf dalam string menjadi huruf kecil.
 split(): Pisahkan teks berdasarkan delimiter(karakter pemisah).
 title(): Jadikan setiap awal kata kapital.
 zfill(): Tambahkan nol di awal string sebanyak nilai yang ada pada
parameter.

Contoh implementasi kode di atas pada Notebook IBM Watson Studio


sebagai berikut:
 

OS
Dokumentasi: https://docs.python.org/3/library/os.html
Modul OS pada Python merupakan modul untuk fungsi-fungsi yang berkaitan
dengan sistem operasi, misalnya open(), path(), getcwd(), dan fungsi lainnya.
Modul ini memungkinkan Anda untuk memanfaatkan fungsi yang sama dan
mengeksekusi fungsi terkait OS yang mungkin berbeda di setiap sistem
operasi. Terdapat beberapa fitur yang hanya bekerja pada sistem operasi
tertentu.

Contoh kode di bawah menunjukkan fungsi os.getcwd(). Fungsi ini akan


mengembalikan string representasi dari Current Working Directory yaitu
direktori di mana program Python kita berada. Fungsi ini berlaku di semua
OS.
1. import os

2. print(os.getcwd())

File Input/Output
Dokumentasi: https://docs.python.org/3/tutorial/inputoutput.html .

Modul Input/Output adalah modul yang berkaitan untuk fungsi yang


mengurus masukan dan keluaran pada Python. Contoh fungsi yang ada pada
modul ini adalah fungsi untuk menampilkan hasil dari program Python ke
layar dan membaca teks yang kita ketik di keyboard.

Kode di bawah menunjukkan 2 contoh fungsi yang ada pada modul


Input/Output yaitu membaca teks yang kita ketik di keyboard dan
menampilkan teks tersebut.
1. string = raw_input("Masukkan sesuatu: ")

2. print "Input yang masuk adalah : ",  string


 

Pickle
Dokumentasi: https://docs.python.org/3/library/pickle.html.

Jika Anda memiliki sebuah list yang ingin disimpan atau ditransmisikan tanpa
khawatir bentuknya akan rusak atau kacau, Anda dapat memanfaatkan
fungsi dari library pickle. Pickle merupakan fungsi Object Serialization pada
Python. Pickling adalah istilah untuk mengubah objek menjadi byte stream,
sedangkan Unpickling adalah perlakuan sebaliknya. 

Kode berikut adalah contoh bagaimana melakukan proses pickle pada


sebuah object dictionary dan menyimpannya pada sebuah file.
1. import pickle

2. contoh_dictionary = {1:"6", 2:"2", 3:"f"}

3. pickle_keluar = open("dict.pickle","wb")

4. pickle.dump(contoh_dictionary, pickle_keluar)

5. pickle_keluar.close()

 Kode berikut adalah contoh untuk mengekstraksi berkas pickle dan


menaruhnya pada sebuah variabel.
1. pickle_masuk = open("dict.pickle","rb")

2. contoh_dictionary = pickle.load(pickle_masuk)

  

JSON
Dokumentasi: https://docs.python.org/3/library/json.html .

Untuk serialization dengan bahasa lain, umumnya kita menggunakan JSON


(JavaScript Object Notation) yang memiliki beberapa perbedaan karakteristik
dengan pickle, yakni:
 JSON adalah format text-serialization dan umumnya menggunakan
Unicode atau UTF-8. Sementara pickle bersifat binary serialization.
 JSON dapat dibaca dengan mudah oleh manusia, sementara pickle
tidak.
 JSON dapat dioperasikan dan digunakan di luar ekosistem Python.
Pickle adalah Python-specific.
 JSON secara default hanya dapat merepresentasikan subset dari built-
in type pada Python.
 Pickle dapat merepresentasikan hampir (jika tidak seluruh) tipe Python
dan secara default melakukan kompresi data.

Seperti yang telah disebutkan sebelumnya, JSON adalah format text yang
ditujukan untuk serialization. Agar data dapat dengan mudah ditransmisikan
antar berbagai sumber tanpa khawatir bentuknya kacau, menggunakan
JSON adalah salah satu pilihan yang tepat.

JSON memiliki format yang hampir mirip dengan dictionary di mana data
disimpan dengan format key & value pair. Namun tentunya JSON jauh lebih
kompleks dari dictionary. Dapat dilihat dari contoh JSON untuk data
pembelian di bawah. Dengan JSON kita dapat menyimpan data dengan lebih
terorganisir. Sebuah key seperti children di bawah dapat memiliki sebuah
dictionary baru yang berisi informasi terkait objek children tersebut tersebut.
Untuk membuat JSON sederhana ketik seperti kode di bawah.
1. import json

2.  

3. # contoh JSON:

4. x = '{ "nama":"Buchori", 

5.       "umur":22, 

6.   "Kota":"New York"}'

7.  

8. # parse x:

9. y = json.loads(x)

10.  

11. print(y["umur"])

Scrapper 
Dokumentasi urllib: https://docs.python.org/3/library/urllib.html .
Dokumentasi
beautifulsoup4: https://www.crummy.com/software/BeautifulSoup/bs4/
doc/.

Web scrapping adalah sebuah proses terotomasi untuk mendapatkan dan


parsing data dari web. Disiplin seperti data science, business intelligence,
dan lainnya mendapatkan banyak manfaat dari menganalisis data pada situs-
situs yang ada di internet. Ada 2 buah library yang terkenal untuk web
scraping yaitu urrlib dan beautifulsoup.

 Urrlibadalah library bawaan dari Python. Kode di bawah adalah contoh


untuk memulai proses scraping pada situs dengan
domain python.orgdan menampilkan isi dari tag title dari situs tersebut.
1. url = "http://python.org/"

2. page = urlopen(url)
3. html = page.read().decode("utf-8")

4. start_index = html.find("<title>") + len("<title>")

5. end_index = html.find("</title>")

6. title = html[start_index:end_index]

7. title

 Beautifulsoup adalah library yang penggunaanya lebih sederhana dari


urrlib. Untuk menggunakan beautifulsoup Anda harus menginstalnya
terlebih dahulu. Berikut adalah contoh penulisan kode beautifulsoup.
1. url = "http://python.org/"

2. page = urlopen(url)

3. html = page.read().decode("utf-8")

4. soup = BeautifulSoup(html, "html.parser")

5. soup.title

Regex
Dokumentasi: https://docs.python.org/3/library/re.html .

Regex atau regular expression adalah sebuah cara untuk mencari teks
berdasarkan pola tertentu. Ketika kita ingin mencari sebuah kata dalam
kamus, misalnya arti dari kata parsing, kita akan mencari kata tersebut di
halaman yang yang memiliki kata dengan awalan p, atau pa. Regex bekerja
dengan konsep yang sama. Pada regex, kita mencari sebuah kata atau
kumpulan kata dengan memberikan pola yang kita inginkan. Contoh umum
regex adalah pada email di mana kita dapat menggunakan regex untuk
mengecek apakah karakter @ ada pada email atau tidak.

Contoh di bawah menunjukkan penggunaan regex. Pada variabel pattern di


bawah, ^a berarti kita ingin mencari teks dengan awalan 'a', dan s$ berarti
kita ingin mencari string berakhiran 's'.
1. import re
2.  

3. pola= '^a...s$'

4. string_tes= 'abyss'

5. hasil= re.match(pola, string_tes)

6.  

7. if hasil:

8.     print("Pencarian berhasil.")

9. else:

10.     print("Pencarian gagal.")

Argument Parser
Dokumentasi Getopt: https://docs.python.org/3.8/library/getopt.html .
Dokumentasi ArgParse: https://docs.python.org/3.8/library/argparse.html.

Argument parser bermanfaat jika kita ingin membuat program atau skrip kecil
yang langsung menerima parameter pada saat pemanggilan program. Hal ini
biasa digunakan dalam pemanggilan aplikasi atau skrip di CLI/terminal *nix-
based misalnya linux dan MacOS. Contoh perintah dimaksud adalah:
1. python panggildicoding.py -o

Contoh dengan menggunakan ArgParse untuk menambahkan Argument


yang bersifat opsional / tidak wajib:

file: panggildicoding.py
1. import argparse

2.  

3. parser = argparse.ArgumentParser()
4. parser.add_argument('-o', '--output', action='store_true',

help="tampilkan output")

5. args = parser.parse_args()

6.  

7. if args.output:

8. print("Halo, ini merupakan sebuah output dari panggildicoding.py")

Maka pada saat dijalankan, terdapat beberapa hal yaitu:

 Berkas panggildicoding.py dapat menerima parameter -o atau --output.


 Jika kita memanggil berkas tanpa parameter -o maka berkas tidak akan
menampilkan apapun.
 Jika kita memanggil dengan -o atau --output maka berkas akan
menampilkan Halo, ini merupakan sebuah output dari
panggildicoding.py.
 Jika kita memanggil --help, maka akan tampil help dengan penjelasan
"tampilkan output".

Kita juga bisa membuat argumennya bersifat wajib. Modifikasi berkas


panggildicoding.py menjadi seperti berikut:
1. import argparse

2.  

3. parser = argparse.ArgumentParser()
4. parser.add_argument('-n', '--nama', required=True, help="Masukkan Nama

Anda")

5. args = parser.parse_args()

6.  

7. print("Terima kasih telah menggunakan panggildicoding.py, "+args.nama)

Maka pada saat dijalankan, terdapat beberapa hal yaitu:

 Berkas panggildicoding.py harus dipanggil dengan parameter -n atau --


nama.
 Jika kita memanggil berkas tanpa parameter -n maka berkas akan
meminta parameter n atau nama.
 Jika kita memanggil dengan -n NAMAKITA atau --nama NAMAKITA
maka berkas akan menampilkan Terima kasih telah menggunakan
panggildicoding.py NAMAKITA.
 Jika kita memanggil --help, maka akan tampil help dengan penjelasan
"Masukkan Nama Anda".

Anda dapat mensuplai lebih dari satu argumen, dengan


menambahkan parser.add_argument sejumlah yang Anda inginkan. 

Ayo berlatih melengkapi script sebelumnya agar mampu menampilkan hasil


berikut:
Ketentuan skrip:

 Berkas panggildicoding.py harus dipanggil dengan parameter n/nama


dan t/tanggallahir.
 Format Tanggal lahir adalah dd-mm-yyyy.
 Jika kita memanggil berkas tanpa parameter maka berkas akan
menolak.
 Jika usia pemanggil saat ini kurang dari 30 tahun, tambahkan
panggilan kakak, selain itu gunakan panggilan bapak sebelum
NAMAKITA.

Anda mungkin juga menyukai