Soal 1Saat result = a + b berjalan, method mana yang dipanggil Python di balik layar?
Special Method — Mengajari Class Cara + dan print Berperilaku
Pelajari special method (dunder method) Python. Sesuaikan + dengan __add__, kontrol output print dengan __str__, dan definisikan ulang == dengan __eq__ — semuanya dengan diagram.
Sebelumnya kita menyusun instance, class, dan static method. Sekarang kita bahas jenis lain — special method (alias dunder method).
Apa itu special method? — "Dunder Method"
Method seperti __init__ dan __str__ — nama yang diapit dua underscore di tiap sisi — disebut special method. Karena duduk di antara double underscores, mereka juga disebut dunder method.
Hal kunci tentang special method adalah kamu tidak memanggilnya langsung. Python memanggil mereka otomatis ketika kamu melakukan operasi tertentu. Tulis v1 + v2 dan Python memanggil v1.__add__(v2) di balik layar. Tulis print(p) dan p.__str__() dipanggil. Tulis a == b dan a.__eq__(b) berjalan.
+, ==, dan teman-teman.__add__ — Mendefinisikan operator +
Ambil + sebagai contoh paling jelas. Misalkan kamu punya class Money untuk jumlah dalam yen, dan kamu ingin Money(300) + Money(500) menghasilkan Money(800). Coba menjumlahkannya begitu saja dan Python akan melempar TypeError karena tidak tahu cara menambahkan Money dengan Money.
Cara mengajari Python cara menambahkannya adalah method __add__. Definisikan def __add__(self, other): dan kembalikan instance baru yang dibangun dari self (sisi kiri) dan other (sisi kanan). Sekarang + bekerja pada class-mu.
class Money:
def __init__(self, amount):
self.amount = amount
def __add__(self, other): # dipanggil saat menulis +
return Money(self.amount + other.amount)
wallet = Money(300)
payment = Money(500)
total = wallet + payment # sebenarnya wallet.__add__(payment)
print(total.amount) # 800
+ dan Python memanggil self.__add__(other). self adalah operand kiri, other adalah yang kanan. Apapun instance baru yang kamu kembalikan menjadi hasil dari +.__str__ dan __repr__ — Dua jenis representasi string
Berikutnya: special method yang dipanggil ketika instance dikonversi ke string. Ada dua, dengan tujuan berbeda.
- __str__ — dipanggil oleh print(p) dan str(p). String yang ramah pengguna dan mudah dibaca.
- __repr__ — dipanggil di REPL atau saat debugging. String yang mirip kode, dengan detail.
Tanpa override, print(user) menampilkan sesuatu seperti <__main__.User object at 0x...> — cukup tidak berguna. Definisikan __str__ untuk tampilan rapi, dan definisikan juga __repr__ agar debugging menunjukkan tipe dan kontennya sekilas.
class User:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self): # untuk print() / str()
return f"{self.name} (umur {self.age})"
def __repr__(self): # untuk debugging
return f"User(name={self.name!r}, age={self.age})"
u = User("Budi", 30)
print(u) # Budi (umur 30) <- __str__
print(repr(u)) # User(name='Budi', age=30) <- __repr__
- Dipanggil oleh
print(u)danstr(u) - Tujuan: string untuk dibaca pengguna akhir
- Contoh:
Budi (umur 30)
- Dipanggil oleh
repr(u)dan REPL interaktif - Jadi cadangan saat __str__ tidak ada selama print
- Tujuan: string debug menunjukkan tipe dan konten
- Contoh:
User(name='Budi', age=30)
__repr__ — membuat debugging jauh lebih mudah.__eq__ — Mendefinisikan ==
Sekarang tentang kesetaraan. Saat kamu menulis a == b, Python memanggil a.__eq__(b) secara internal. Jika class-mu tidak mendefinisikan __eq__, default-nya adalah «apakah mereka object yang sama di memory?» (cek id).
Misalkan kamu punya class Coupon dan kamu ingin dua kupon dengan kode sama dianggap kupon yang sama — meski nilai diskon berbeda. Itu kesetaraan «tingkat bisnis», dan __eq__ adalah tempat kamu menjelaskannya.
== adalah cek id — konten sama tapi instance terpisah tetap False. Dengan __eq__, kamu bisa membandingkan berdasar konten (code).class Coupon:
def __init__(self, code, discount):
self.code = code
self.discount = discount
def __eq__(self, other):
return self.code == other.code # kode sama = kupon sama
c1 = Coupon("SPRING10", 0.10)
c2 = Coupon("SPRING10", 0.20) # diskon beda, kode sama
c3 = Coupon("SUMMER15", 0.15)
print(c1 == c2) # True (kode cocok)
print(c1 == c3) # False (kode beda)
Apa yang terjadi tanpa __eq__?
Jika kamu tidak mendefinisikan __eq__, c1 == c2 mengecek apakah mereka object yang sama di memory (literal menunjuk box yang sama). Bahkan jika setiap atribut cocok sempurna, dua instance yang dibangun terpisah hidup di alamat memory yang berbeda dan hasilnya False. Kapanpun kamu mau «sama menurut konten», definisikan __eq__ sendiri.
Special method umum lainnya — __call__ / __len__ / __bool__
Selain empat yang telah kita bahas, beberapa special method lain sering muncul. Tiga yang patut diketahui sekarang:
- __call__ — membuat instance bisa dipanggil seperti fungsi (sintaks obj(...))
- __len__ — menentukan apa yang dikembalikan len(obj)
- __bool__ — menentukan bagaimana instance dievaluasi sebagai nilai kebenaran dalam if obj: atau bool(obj)
Masing-masing mengajari operasi bawaan — pemanggilan fungsi, len(), cek truthiness if — ke class buatanmu. Logger yang mengakumulasi entri log adalah contoh bagus untuk meletakkan ketiganya pada satu class.
class Logger:
def __init__(self, name):
self.name = name
self.log = []
def __call__(self, message): # logger("...") jalan
self.log.append(message)
return f"[{self.name}] {message}"
def __len__(self): # untuk len(logger)
return len(self.log)
def __bool__(self): # untuk if logger:
return len(self.log) > 0
app = Logger("app")
print(app("Aplikasi mulai")) # [app] Aplikasi mulai
print(app("Login berhasil")) # [app] Login berhasil
print(len(app)) # 2
if app:
print("Ada log") # Ada log
logger(...), len(logger), if logger: — diajarkan ke class kustommu lewat tiga dunder yang cocok.Bagaimana kalau tidak mendefinisikan __bool__?
Saat __bool__ tidak ada, Python jatuh ke __len__. Panjang 0 jadi False; selain itu jadi True. Kalau keduanya tidak ada, instance selalu truthy, apapun keadaannya. Itulah aturan yang sama yang membuat list kosong dan string kosong dievaluasi False.
Masih banyak lagi — __hash__ (untuk dipakai sebagai key set/dict), __lt__ / __gt__ (perbandingan < / >), __getitem__ (sintaks obj[key]), __iter__ (iterasi for x in obj:), dan lainnya. Kamu tidak perlu menghafal semuanya. Cukup simpan peta mental ini: «kalau kamu mau mengajari operasi bawaan ke class-mu, kemungkinan ada dunder yang cocok». Lalu cari saat kamu butuh.
| Special method | Sintaks | Kapan dipanggil |
|---|---|---|
| __init__ | Money(300) | Saat membuat instance |
| __add__ | a + b | Operator + |
| __str__ | print(p) / str(p) | String untuk pengguna |
| __repr__ | repr(p) / tampilan REPL | String untuk developer |
| __eq__ | a == b | Perbandingan kesetaraan |
| __call__ | obj(...) | Panggilan gaya fungsi |
| __len__ | len(obj) | Panjang |
| __bool__ | if obj: / bool(obj) | Truthiness |
Cek Pemahaman
Jawab setiap pertanyaan satu per satu.
Soal 2Mana deskripsi __str__ dan __repr__ yang paling akurat?
Soal 3Jika class tidak mendefinisikan __eq__, apa yang dibandingkan a == b? (Keduanya instance dari class yang sama.)