Dasar-Dasar Python (Basic 4)
Objek
Python tentu saja mendukung pemrograman berorientasi
objek. Bahkan, nyaris segala sesuatu di Python—mulai dari string, angka,
fungsi—adalah objek. Apakah objek itu? Objek adalah sesuatu yang menampung nilai/data dan dapat kita
kenakan operasi tertentu. Di dunia
nyata ini, banyak hal yang bisa kita sebut objek. Buku misalnya, merupakan
objek karena menampung informasi dan dapat kita baca (kenakan operasi baca) atau tulis (kenakan operasi tulis). Sepeda, binatang, manusia, semua
juga bisa disebut objek.
>>> "aku seorang kapiten".split(" ")
['aku', 'seorang', 'kapiten']
Pada contoh di atas, kita membuat
objek string bernilai “aku seorang kapiten” lalu mengenakan operasi split() pada objek string tersebut, yaitu dengan sintaks
titik diikuti oleh nama operasi (yang disebut metode objek). Hasilnya adalah
sebuah list—yang merupakan objek juga. List ini berisi 3 elemen, masing-masing
elemennya adalah string yang telah dipecah (yang, lagi-lagi, merupakan objek
pula). Sehingga lewat operasi split()
kita telah menciptakan empat objek baru, sebuah list dan tiga buah string.
Catatan: Perhatikan bahwa kode di atas hanya akan berjalan di
Python versi 2 ke atas. Di versi 1.5.2 dan sebelumnya, Python belumlah
“semurni” sekarang, dan belum memperlakukan tiap jenis objek secara konsisten.
Untuk contoh selanjutnya, diasumsikan Anda telah menggunakan Python 2.
>>> kata = "aku seorang kapiten".split(" ")
>>> kata.append("mempunyai")
>>> kata.append("pedang")
>>> kata.append("panjang")
>>> kata
['aku', 'seorang', 'kapiten', 'mempunyai', 'pedang', 'panjang']
>>> kata.sort()
>>> kata
['aku', 'kapiten', 'mempunyai', 'panjang', 'pedang', 'seorang']
Pada contoh di atas, kita
mula-memberi nama objek list hasil split()dengan
variabel kata. Kita lalu
mengenakan operasi append() pada
kata. Operasi append() adalah
operasi pada objek list yang berguna untuk menambah satu elemen di akhir list.
Setelah tiga kali menambah elemen, kita meminta Python mencetak isi objek list
kita. Setelah itu kita mengenakan lagi operasi sort()
pada objek kita. Hasilnya adalah keenam kata yang telah diurutkan secara
alfabetis.
Memberi nilai dan mengenakan
operasi pada objek di Python mudah bukan? Apakah ada jenis objek lain selain
string dan list? Tentu saja. Dictionary, float (bilangan desimal), dan int
(bilangan bulat) semuanya adalah objek. Perhatikan contoh-contoh berikut:
>>> {'tomi':'taurus', 'vira':'virgo', 'santi':'sagitarius'}.keys()
['tomi', 'vira', 'santi']
>>> {'tomi':'taurus', 'vira':'virgo', 'santi':'sagitarius'}.values()
['taurus', 'virgo', 'sagitarius']
>>> (-1.3).__abs__()
1.3
Perhatikan bahwa pada kasus
terakhir, kita perlu memberi tanda kurung dulu sebelum memberi titik dan nama
operasi, agar parser Python tidak kebingungan—ingat bahwa sebuah bilangan
desimal juga dapat mengandung karakter titik. Contoh terakhir juga dapat
ditulis secara “non-OO” yaitu abs(-1.3)
dan akan memberi hasil yang sama.
Refleksi: Fungsi dir()
Kalau Anda menjumpai sebuah
objek, bagaimana kita tahu apa saja yang kita bisa lakukan terhadapnya? Dengan
kata lain, operasi apa saja yang berlaku untuk objek tersebut? Kalau Anda
sedang memakai bahasa level rendah seperti C++ maka jawabannya barangkali:
teliti source codenya untuk mengetahui ini objek jenis apa, lalu teliti source
code lagi untuk mengetahui definisi objeknya atau baca manual untuk mengetahui
daftar metode untuk jenis objek yang dimaksud. Tapi di bahasa level tinggi
seperti Python (atau Ruby atau Smalltalk), ada cara yang jauh lebih mudah:
bertanyalah langsung. Bahasa-bahasa ini sangat terbuka dan mengizinkan kita
mengintip ke dalam tiap objek untuk mengetahui isi perutnya. Istilah yang umum
dipakai untuk urusan intip-mengintip ini adalah refleksi—yang berarti melihat bayangan diri sendiri, seperti
melihat di cermin. Mari kita lihat seperti apa kemampuan refleksi di Python.
Fungsi yang perlu Anda ketahui
paling pertama yaitu dir().
Fungsi dir() akan mengambil
informasi dari objek dan memberitahu kita daftar atribut/operasi yang tersedia
untuk suatu objek. Contoh:
>>> dir("")
['__add__', '__class__', '__contains__', '__delattr__', '__doc__', '__eq__',
'__ge__','__getattribute__', '__getitem__', '__getslice__', '__gt__',
'__hash__', '__init__', '__le__', '__len__', '__lt__', '__mul__', '__ne__',
'__new__', '__reduce__', '__repr__', '__rmul__', '__setattr__', '__str__',
'capitalize', 'center', 'count', 'decode', 'encode', 'endswith',
'expandtabs', 'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower',
'isspace', 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip',
'replace', 'rfind', 'rindex', 'rjust', 'rstrip', 'split', 'splitlines',
'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper']
Pada contoh di atas kita bertanya
pada Python, objek string ("")
itu mengandung atribut/mendukung operasi apa saja? dir() akan mengembalikan list berisi informasi yang
dimaksud. Hm, ada upper() dan lower(). Mari kita coba.
>>> "Prok, Prok, Prok!".upper()
'PROK, PROK, PROK!'
>>> "Prok, Prok, Prok!".lower()
'prok, prok, prok!'
Mudah sekali bukan? Kita tidak perlu
melihat manual untuk mengetahui bagaimana cara mengkonversi sebuah string
menjadi huruf kapital atau huruf kecil. Cukup buatlah objek, menanyakan
jenis-jenis operasi pada Python, lalu memanggil metode yang sesuai.
Tapi tentu tidak semua semudah itu.
Beberapa operasi/metode membutuhkan argumen.
Bagaimana kita mengetahui sintaks setiap operasi?
Lagi-lagi refleksi Python membantu.
Kita dapat mengintip atribut __doc__
sebuah objek untuk mengetahui keterangan singkat mengenai objek tersebut.
Rata-rata objek memiliki atribut __doc__
yang disebut docstring ini.
Misalnya,
>>> "tes".replace.__doc__
'S.replace (old, new[, maxsplit]) -> string\n\nReturn a copy of string S with
all occurrences of substring\nold replaced by new. If the optional argument
maxsplit is\ngiven, only the first maxsplit occurrences are replaced.'
Pada contoh di atas, kita ingin mengetahui sintaks metode replace() pada objek string. Perhatikan bahwa kita tidak menambahkan tanda kurung, (), setelah replace, menandakan bahwa kita bukan ingin memanggil metode objek replace() ini, melainkan mengambil atribut __doc__-nya. "tes" adalah sebuah objek berjenis string, dan "tes".replace adalah juga sebuah objek berjenis fungsi/metode. Jika kita menambahkan () setelah menyebutkan fungsi, maka kita mengenakan operasi memanggil atau mengeksekusi objek fungsi tersebut. Apakah "tes".replace.__doc__ sebuah objek juga? Ya, sebuah string.
Kembali ke __doc__. Sewaktu kita meminta nilai "tes".replace.__doc__ pada
Python, Python memberikan nilai mentahnya. Buktinya, bisa Anda lihat kode
escape \n yang terkandung di
dalamnya. Bagaimana agar \n
benar-benar tercetak sebagai newline? Mudah saja, print-lah docstring tersebut.
>>> print "tes".replace.__doc__
S.replace (old, new[, maxsplit]) -> string
Return a copy of string S with all occurrences of substring
old replaced by new. If the optional argument maxsplit is
given, only the first maxsplit occurrences are replaced.
Lebih enak dibaca bukan? Dari
docstring ini kita mengetahui bahwa metode replace()
membutuhkan dua atau tiga argumen. Argumen pertama, old, adalah string yang ingin diganti oleh argumen kedua, new. Sementara argumen ketiga yang
bersifat opsional menyatakan jumlah penggantian maksimum yang boleh dilakukan.
Mari praktikkan.
>>> "kadal".replace("l","k").replace("a","o")
'kodok'
>>> "kadal".replace("l","k").replace("a","o",1)
'kodak'
Contoh pertama mula-mula mengganti
huruf “l” dengan huruf “k” pada objek string “kadal”, sehingga menghasilkan objek
string baru bernilai “kadak”.
Objek baru ini langsung dioperasi lagi dengan replace()
kedua sehingga semua “a”-nya
menjadi “o”. Sehingga hasil
akhirnya menjadi “kodok”. Contoh
kedua sama, tapi menggunakan argumen ketiga pada replace() kedua.
Silakan Anda bermain-main dengan dir() dan mengintip apa saja yang bisa
dilakukan terhadap objek-objek Python. Cobalah perintah-perintah berikut di
interpreter interaktif Python dan telitilah lebih lanjut tiap atribut yang
dikembalikan oleh dir(). Jika
Anda butuh, cetaklah atribut __doc__-nya.
>>> dir(1)
>>> dir({})
>>> dir([])
>>> dir(None)
>>> dir(dir)
>>> import os
>>> dir(os)
>>> print os.rename.__doc__
>>> _
Kelas
Setelah puas bermain-main dengan
objek yang ada di Python, Anda mungkin kini bertanya: bisakah saya membuat jenis
objek saya sendiri? Jawabnya: tentu bisa, dengan bantuan objek khusus bernama kelas. Kelas adalah objek yang kita
pakai untuk membuat objek lain. Kelas di Python didefinisikan dengan kata kunci
class. Contoh definisi kelas paling
sederhana:
class Titik:
pass
Kelas Titik kita adalah kelas kosong yang siap dipakai untuk membuat
objek. Bagaimana cara membuat objek dari kelas? Jawabnya: dengan menggunakan
(), dengan kata lain memanggil kelas
tersebut.
titikku = Titik()
Maka jadilah sebuah objek kosong.
Objek ini memiliki tipe Titik,
dan disebut juga sebagai instans dari Titik.
Cobalah mencetak nilainya di interpreter interaktif Python:
>>> titikku = Titik()
>>> titikku
<__main__.Titik instance at 0x815b72c>
Python memberitahu bahwa titikku berisi objek yaitu instans dari
kelas Titik. Apa yang bisa kita
lakukan dengan objek ini? Kita bisa mengisinya dengan atribut atau nilai.
titikku.x = 5
titikku.y = 10
Objek titikku di sini dapat Anda pandang sebagai kantung atau
namespace yang Anda isi dengan atribut-atribut bernama dan bernilai. Dan bisa
juga Anda padang sebagai dictionary. Bahkan, sebetulnya, atribut-atribut ini
memang disimpan oleh Python di sebuah atribut dictionary khusus bernama __dict__.
Refleksi: __dict__
Selain __doc__, ada satu atribut objek spesial
lain yang disebut __dict__. __dict__ ini adalah sebuah dictionary yang
dipakai Python untuk menyimpan daftar atribut pada objek bersangkutan.
Objek-objek seperti modul dan instans kelas dapat Anda intip __dict__-nya untuk mengetahui atribut apa
saja yang ada di dalamnya. Contoh:
>>> import os
>>> dir(os)
>>> print os.__dict__
Kalau Anda perhatikan keluarannya,
maka dir() dan __dict__ akan memberikan hasil yang
mirip-mirip. Untuk apa __dict__? Dengan __dict__ kita dapat memanipulasi daftar atribut
sebuah objek atau mengambil atribut sebuah objek secara dinamik. Contohnya:
>>> for cmd in ['setuid','open','stat']:
... print cmd
... print os.__dict__[cmd].__doc__
... print
...
setuid
setuid(uid) -> None
Set the current process's user id.
open
open(filename, flag [, mode=0777]) -> fd
Open a file (for low level IO).
stat
stat(path) -> (st_mode, st_ino, st_dev, st_nlink, st_uid, st_gid,
st_size, st_atime, st_mtime, st_ctime)
Perform a stat system call on the given path.
>>> _
Pada contoh di atas, kita mencetak
docstring dari ketiga fungsi yang terdapat di modul os (yang telah kita import
sebelumnya, tentu saja). Tapi alih-alih menggunakan sintaks os.open.__doc__, kita menggunakan os.__dict__['open'].__doc__. Keduanya
setara, tapi dengan menggunakan dictionary __dict__,
kita dapat menyebutkan atribut objek dengan nama variabel. Dengan __dict__ kita juga mencari sebuah atribut
dari program kita. Bahkan kita dapat menghapus atribut objek dengan
memanipulasi isi __dict__.
Ingat, __dict__ adalah sebuah
objek dictionary, dan kita bisa melakukan operasi sebagaimana kita memanipulasi
sebuah dictionary biasa.
Kembali ke objek titikku kita sebelumnya:
>>> titikku = Titik()
>>> titikku.__dict__
{}
Saat pertama kita cetak, __dict__ dari objek titikku masih kosong
karena belum ada atribut apa-apa pada objek kita tersebut. Tapi setelah kita
melakukan:
>>> titikku.x = 5
>>> titikku.y = 10
>>> titikku.__dict__
{'y': 10, 'x': 5}
Maka __dict__ pun berisi atribut yang telah kita isikan
sebelumnya. Jadi bisa Anda lihat bukan? Dengan mengintip atribut __dict__ pada sebuah objek instans kelas,
kita dapat melakukan refleksi terhadap objek tersebut. Kita dapat mengetahui
atribut-atribut apa yang terkandung dalam objek kita. Bahkan, seperti telah
disebutkan sebelumnya, kita dapat menambah atau menghapus atribut objek lewat __dict__ ini.
>>> titikku.__dict__['x'] = 7
>>> titikku.x
7
>>> titikku.__dict__['z'] = -3
>>> titikku.z
-3
>>> del titikku.__dict__['y']
>>> titikku.__dict__
{'x': 7, 'z': -3}
>>> titikku.y
Traceback (most recent call last):
File "<stdin>", line 1, in ?
AttributeError: Titik instance has no attribute 'y'
>>> _
Pada contoh di atas, kita
menambahkan elemen “z” pada
atribut __dict__ sehingga titikku.z dikenali. Lalu kita menghapus
atribut “y” sehingga titikku
tidak lagi memiliki atribut tersebut.
Mari kita kembali kepada dir(). Apa yang akan dilaporkan oleh dir() untuk objek titikku?
>>> dir(titikku)
['__doc__', '__module__', 'x', 'z']
Kenapa sudah ada dua atribut, __doc__ dan __module__, di situ? Padahal kita tidak pernah membuat atau
mengisinya bukan? Ingat, atribut-atribut yang memiliki sintaks __NAMA__ adalah atribut spesial. __doc__, misalnya, sebetulnya diambil dari source code
program. Coba cetak nilainya:
>>> titikku.__doc__
>>> _
Ternyata kosong. Tapi jika kita mendefinisikan kelas Titik seperti ini:
class Titik:
"Membuat sebuah objek titik."
pass
Maka jika kita membuat instans Titik lagi:
>>> titikku=Titik()
>>> titikku.__doc__
'Membuat sebuah objek titik.'
maka __doc__ secara ajaib telah terisi. Ya. __doc__, sesuai namanya, akan diisi oleh
Python dengan string pertama pada sebuah definisi kelas atau fungsi. Programer
Python biasanya menaruh dokumentasi singkat di dalam string ini. Sehingga jika
ingin melihatnya nanti bisa dengan mudah mengintip __doc__. Python akan mengambilkan nilai string ini untuk
Anda. Cobalah mengintip ke dalam file os.py
(lokasinya di /usr/lib/python2.2/os.py
atau bisa berbeda di sistem Anda). Maka Anda akan dapat melihat banyak
docstring yang nantinya bisa Anda lihat lagi dari Python dengan mengakses __doc__. Refleksi yang satu ini amat
mempermudah kita dalam mengekstrak dokumentasi dari program Python itu sendiri.
Catatan: pass pada
definisi kelas Titik di atas boleh ada atau tidak. Pada kasus sebelumnya wajib
ada karena Python membutuhkan minimal satu statement untuk definisi kelas.
Metode Objek
Sampai sejauh ini objek titik
kita—meski bisa diisi atribut apa saja—tetap saja agak-agak garing karena tidak
bisa kita apa-apakan lagi. Dengan kata lain, tidak ada operasi yang tersedia
untuk objek kita ini. Bagaimana caranya mendefinisikan operasi untuk jenis
objek kita? Jawabnya: dengan mendefinisikan fungsi di dalam definisi kelas.
Definisikan kembali kelas Titik
kita sbb.:
class Titik:
"Titik yang dapat dipindah-pindahkan."
def __init__(self, initialX, initialY):
self.x = initialX
self.y = initialY
def move(self, amountX, amountY):
"""move(amountX, amountY) -> None
Pindahkan titik sebanyak amountX ke kanan, amountY ke atas."""
self.x += amountX
self.y += amountY
def whereami(self):
print "Aku ada di (%d, %d)" % (self.x, self.y)
Ada beberapa hal yang perlu
diperhatikan. Pertama, kita
mendefinisikan dua operasi bagi instans kelas Titik,
yaitu move() dan whereami() dan sebuah operasi khusus __init__() untuk menginisialisasi
atribut-atribut awal objek. Kedua, __init__()
tidak dipanggil manual, tapi akan dipanggil saat kita membuat objek Titik(). Ketiga, perhatikan bahwa argumen pertama semua metode ini adalah self. Python memang menyisipkan instans
kelas kita nanti di argumen pertama, agar tiap fungsi/metode ini dapat
mengakses isi instans kelas. Waktu kita memanggil metode dengan sintaks obj.namametode(a, b, c) nanti, self tidak perlu disebutkan lagi karena
akan dimasukkan secara otomatis oleh Python menjadi obj.namametode(obj, a, b, c). Empat, perhatikan pula kita memberi docstring pada kelas Titik (docstring satu baris) dan pada
metode move() (docstring banyak
baris/multiline).
Setelah kelas Titik didefinisikan,
mari membuat instansnya. Karena terdapat __init__
yang menerima dua argumen (di luar self),
maka kita dapat membuat instans objek Titik
dengan cara:
>>> t = Titik(5, 10)
Andaikata tidak ada __init__(), kita tetap dapat membuat
sebuah titik yang berlokasi awal di koordinat (5, 10) dengan cara:
>>> t = Titik()
>>> t.x = 5
>>> t.y = 10
Jadi kegunaan __init__() adalah sebagai notasi ringkas
inisialisasi objek.
Mari kita coba menggunakan
metode-metode objek kita:
>>> t.whereami()
Aku ada di (5, 10)
>>> t.move(1,1)
>>> t.whereami()
Aku ada di (6, 11)
>>> t.move(-1,1)
>>> t.whereami()
Aku ada di (5, 12)
Akhirnya, titik kita sudah lebih
keren sekarang. Bisa dipindah-pindahkan dengan operasi buatan sendiri.
Refleksi Lagi
Apakah kita bisa mengintip objek
kelas Titik maupun
instans-instansnya dengan fasilitas refleksi? Tentu saja. Berikut
contoh-contohnya.
>>> t=Titik(5, 10)
>>> dir(Titik)
['__doc__', '__init__', '__module__', 'move', 'whereami']
>>> dir(t)
['__doc__', '__init__', '__module__', 'move', 'whereami', 'x', 'y']
>>> t.__doc__
'Titik yang dapat digerak-gerakkan.'
>>> t.move.__doc__
'move(amountX, amountY) -> None\n\n Pindahkan titik sebanyak
amountX ke kanan, amountY ke atas.'
>>> t.__dict__
{'y': 10, 'x': 5}
>>> t.__dict__['x'] = 10
>>> t.__dict__['y'] = 1
>>> t.move(-5, 9)
>>> t.__dict__
{'y': 10, 'x': 5}
>>> _
Penutup
Pada kesempatan lain kita akan
lebih jauh membahas mengenai metode dan paradigma OO seperti pewarisan.
Sementara itu, Anda bisa mencoba sebuah modul standar bernama inspect. Modul ini membantu kita melakukan
refleksi dengan lebih praktis. Bagaimana cara menggunakan modul ini? Anda bisa
membaca manual Python atau… terlebih dahulu mengintip modul inspect ini dengan refleksi yang
disediakan Python! Selamat berefleksi. (sh)
0 comments:
Posting Komentar
PEDOMAN KOMENTAR
Ayo berpartisipasi membangun budaya berkomentar yang baik. Pantang bagi kita memberikan komentar bermuatan menghina atau spam.
Kolom komentar tersedia untuk diskusi, berbagi ide dan pengetahuan. Hargai pembaca lain dengan berbahasa yang baik dalam berekspresi. Setialah pada topik. Jangan menyerang atau menebar kebencian terhadap suku, agama, ras, atau golongan tertentu.
Bangun sharing ilmu dengan berkomentar disini :