Özel metotlar ve özel istisnalar

print(obj) yazdığınızda ekrana ne çıkacağını, obj1 == obj2 karşılaştırmasının ne zaman True vereceğini ya da nesnenin bir listenin içinde nasıl görüneceğini siz belirleyebilirsiniz. Bunun için sınıfa, adı iki alt çizgiyle başlayıp biten özel metotlar yazarsınız: __str__, __repr__, __eq__ gibi. Bu metotları siz çağırmazsınız; print(), repr() ya da == kullanıldığında Python kendisi çağırır. Hangi işlemin hangi özel metodu çağıracağını 6. haftada tanıdığınız Python veri modeli belirler. Bu hafta ayrıca programın konusuna özgü hataları, örneğin “yetersiz bakiye” hatasını, kendi istisna sınıflarınızla bildireceksiniz.

str ve len gibi Python işlemlerinin __str__ ve __len__ gibi özel metotlara bağlanmasını gösteren diyagram.

Özel metot protokolü

Bu bölümün kapsamı

NoteSınavda sorulur
  • __str__ ile kullanıcıya dönük temsil
  • __repr__ ile durumu açık gösteren temsil
  • Koleksiyonların elemanlarını gösterirken repr() kullanması
  • __eq__ ile iki nesnenin ne zaman eşit sayılacağını belirleme
  • Alt sınıfın uygulaması gereken metodu raise NotImplementedError ile işaretleme
  • __eq__ tanımlayan sınıfın hash sözleşmesi
  • Özel istisna için uygun temel sınıfı seçme
  • __eq__ içinde return NotImplemented kalıbının ayrıntısı
  • __hash__ yazımı
  • __lt__, __add__ gibi diğer özel metotlar ve functools.total_ordering
  • İstisna zincirleme (raise ... from ...)

Bu başlıklar konunun devamıdır; ileride karşınıza çıkar ama bu derste ezberlemeniz beklenmiyor.

Bu iki nesne ne zaman “aynı” sayılır?

Aynı ISBN’li iki Book nesnesi aynı kitap mıdır? Bunu Python bilemez. Kararı programın ele aldığı konuya, yani problem alanına bakarak siz verirsiniz: bir kitapçının satış programında aynı ISBN aynı kitap demektir, ama bir kütüphanede aynı kitabın iki ayrı kopyası da olabilir. Bu karar yalnız == işlecini etkilemez. Listede in ile arama ve remove() ile silme de aynı eşitlik tanımını kullanır.

__str__: kullanıcıya dönük temsil

Sınıfta __str__ tanımlıysa print(product) ve str(product) onun döndürdüğü metni kullanır. Bu metin, nesnenin kullanıcıya gösterilecek hâlidir. Buna kullanıcıya dönük temsil denir.

__repr__: geliştiriciye dönük temsil

repr çıktısı geliştirici içindir. Bu derste onu en çok hata ayıklarken nesnenin durumunu bir bakışta görmek için yazıyorsunuz: Product(code='P1', name='Klavye') çıktısından hangi sınıfın hangi değerlerle oluşturulduğu okunur.

Hangi işlem hangi metodu çağırır?

Pratikte şu üç kurala dikkat edin:

  1. Sınıfta __str__ yok ama __repr__ varsa str(obj) ve print(obj) geliştirici temsilini, yani __repr__ sonucunu kullanabilir.
  2. Yalnız __str__ tanımlarsanız repr(obj) değişmez; <__main__.Product object at 0x...> biçimindeki varsayılan temsilde kalır.
  3. Liste gibi koleksiyonlar elemanlarını gösterirken repr() kullanır. Bu yüzden print([product]), product.__str__() yerine product.__repr__() sonucunu gösterir.
Importantprint(obj) ile print([obj]) aynı protokolü kullanmaz

print(obj) nesnenin kullanıcıya dönük str temsilini yazar. print([obj]) ise listeyi yazdırır ve liste kendini metne çevirirken her elemanın repr temsilini kullanır. __str__ yazdığınız hâlde print(products) çıktısı değişmiyorsa nedeni çoğu zaman budur.

__eq__: iki nesne ne zaman eşit?

== artık bizim koyduğumuz kurala bakar: ürün kodları aynıysa True verir. is ise hâlâ iki adın aynı nesneyi gösterip göstermediğini, yani kimliği sorar. Burada iki ayrı nesne olduğu için False verir.

NoteEşitlik tasarım kararıdır

Product için ürün kodu, Book için ISBN, Student için öğrenci numarası iki nesneyi “aynı” saymanın ölçütü olabilir. __eq__ yazmadan önce bu kuralı problem alanına bakarak belirleyin.

NotImplemented ve NotImplementedError aynı şey değildir

Adları benzer ama işleri tamamen farklıdır:

Ad Tür Ne yapılır? Tipik kullanım
NotImplemented Python’da tek örneği olan özel bir değer return ile döndürülür __eq__ gibi iki nesneyi karşılaştıran metotta “bu türle karşılaştırmayı desteklemiyorum” demek
NotImplementedError istisna sınıfı raise ile yükseltilir bir metodun bu sınıfta yazılmadığını bildirmek

Doğru örnekler:

def __eq__(self, other):
    if not isinstance(other, Product):
        return NotImplemented
class Shape:
    def area(self):
        raise NotImplementedError("Alt sınıf hesaplamalı")
Warningreturn NotImplementedError ve raise NotImplemented yazmayın

10. haftada NotImplementedError istisnasını raise ile yükselttiniz; bu hafta __eq__ içinde NotImplemented değerini return ile döndürüyorsunuz. İkisini karıştırmayın.

__eq__ ve hash sözleşmesi

3. haftada sözlük anahtarlarının ve küme elemanlarının hashlenebilir olması gerektiğini gördünüz. Eşit sayılan iki nesnenin hash değeri de aynı olmalıdır. Bir sınıfa __eq__ yazıp uygun bir __hash__ yazmazsanız o sınıfın nesneleri çoğu durumda hashlenemez olur. Bu derste __hash__ yazmıyorsunuz. Yalnız, değeri sonradan değişebilen (mutable) bir nesneyi set elemanı ya da dict anahtarı yapmadan önce eşitliğin ve hash’in nasıl tanımlanacağını düşünün.

Özel istisna hangi sınıftan türemeli?

Programın konusuna özgü hatalar (yetersiz bakiye, geçersiz sınav notu gibi) için güvenli başlangıç Exception sınıfıdır:

class InsufficientBalanceError(Exception):
    pass

Kendi istisnalarınızı doğrudan BaseException sınıfından türetmeyin. BaseException, KeyboardInterrupt (kullanıcının Ctrl+C’ye basması) ve SystemExit (programın sys.exit() ile kapanması) gibi programın akışını durduran istisnaların da köküdür.

Hatanız yerleşik bir hata türünün özel bir biçimiyse o türden türetebilirsiniz. Örneğin geçersiz bir sınav notu, geçersiz bir değerdir; yani bir tür ValueError hatasıdır:

class InvalidScoreError(ValueError):
    pass

Bu durumda çağıran kod hatayı except InvalidScoreError ile de, daha genel except ValueError ile de yakalayabilir. Hangi temel sınıfın doğru olduğunu hatanın anlamı belirler. Yalnızca özel sınıf yazmış olmak için katman katman istisna sınıfları kurmayın.

Hatayı kendi adıyla bildirmek

withdraw() gibi bir metot hatayı çoğu zaman yükseltir; onu kullanıcıyla konuşan kod, örneğin menüyü gösterip mesajı ekrana yazan kısım yakalar. Account hatayı kendi içinde print() ile yazıp geçerse çağıran kod para çekmenin başarısız olduğunu güvenilir biçimde anlayamaz.

Genel bir hata yerine probleme özgü bir istisnanın yükseltilip yakalandığını gösteren diyagram.

Özel istisna

Alıştırma: __str__ ekle

return f"{self.student_id} - {self.name}"

Alıştırma: repr farkını gözlemle

Bir sınıfa hem __str__ hem __repr__ ekleyin. print(obj), repr(obj) ve print([obj]) sonuçlarını yan yana yazdırın; hangi çağrının hangi özel metoda gittiğini açıklayın.

Alıştırma: Eşitlik kuralını seç

Book(isbn, title, author) sınıfında eşitliği ISBN’e göre tanımlayın: ISBN’leri aynı olan iki kitap eşit sayılsın. Başka türden nesne geldiğinde NotImplemented döndürün. Bu alıştırmada __hash__ yazmanız beklenmez.

Sıra sizde: Üyelik modeli

Member(member_id, name, active) sınıfını yazın. Sınıfa __str__, __repr__ ve __eq__ ekleyin; member_id değerleri aynı olan iki üye eşit sayılsın. InactiveMemberError(Exception) adlı özel istisnayı tanımlayın ve üye aktif değilse bu istisnayı yükselten bir ensure_active() metodu ekleyin.

Çalışır kod görevi: member_id değeri aynı olan iki ayrı nesne oluşturup == ve is sonuçlarını doğrulayın. print(member) ile print([member]) arasındaki farkı gösterin. Pasif bir üyede ensure_active() çağrısının InactiveMemberError yükselttiğini test edin. Ayrıca NotImplemented ve NotImplementedError için birer doğru kullanım satırı yazın.

Sınav provası

Önce kendi cevabınızı seçin; sonra cevap anahtarında her şıkkın neden doğru veya yanlış olduğunu okuyun. Çeldiriciler uydurma değil, bu konuda gerçekten yapılan hatalardır. Sınav maddeleri de bu mantıkla yazılır.

Madde 1. Aşağıdaki program ne yazdırır?

class Product:
    def __init__(self, code, name):
        self.code = code
        self.name = name

    def __str__(self):
        return f"{self.code} - {self.name}"

print(Product("P1", "Klavye"))
  • A. Product(code='P1', name='Klavye')
  • B. TypeError; print() bir nesne alamaz
  • C. P1 - Klavye
  • D. <__main__.Product object at 0x...>
  • E. None

Madde 2. Bir sınıfta yalnız __str__ tanımlanırsa repr(obj) ne verir?

  • A. __str__ sonucunu verir; tanımlı tek temsil odur
  • B. Varsayılan temsili verir; repr() __str__ metoduna bakmaz
  • C. AttributeError yükseltir; __repr__ tanımlı değildir
  • D. Boş metin verir
  • E. None verir

Madde 3. Aşağıdaki program ne yazdırır?

class Product:
    def __init__(self, code):
        self.code = code

    def __str__(self):
        return f"Ürün {self.code}"

    def __repr__(self):
        return f"Product({self.code!r})"

product = Product("P1")
print(product)
print([product])
  • A. Product('P1') ve [Product('P1')]
  • B. Ürün P1 ve [Ürün P1]
  • C. İki satırda da Ürün P1
  • D. Ürün P1 ve [Product('P1')]
  • E. Ürün P1 ve [<__main__.Product object at 0x...>]

Madde 4. __str__ yazdığınız hâlde print(products) çıktısının değişmemesi neyle açıklanır?

  • A. print() listeleri hiçbir zaman biçimlendirmez
  • B. __str__ metodunun adı __string__ olmalıdır
  • C. Liste, elemanlarını gösterirken repr temsilini kullanır
  • D. Listelerde __str__ tanımlamak için list sınıfı türetilmelidir
  • E. __str__ yalnız tek elemanlı listelerde çalışır

Madde 5. Aşağıdaki program ne yazdırır?

class Product:
    def __init__(self, code):
        self.code = code

    def __eq__(self, other):
        if not isinstance(other, Product):
            return NotImplemented
        return self.code == other.code

first = Product("P1")
second = Product("P1")
print(first == second)
print(first is second)
  • A. True ve False
  • B. True ve True
  • C. False ve False
  • D. False ve True
  • E. NotImplemented ve False

Madde 6. __eq__ yazmadan önce ne belirlenmelidir?

  • A. Nesnelerin bellekte yan yana olup olmadığı
  • B. Sınıfın hangi üst sınıftan türeyip neyi devraldığı
  • C. __hash__ metodunun kaç bit döndüreceği
  • D. İki nesnenin hangi kurala göre “aynı” sayılacağı
  • E. Sınıfta karşılaştırılacak kaç nitelik bulunduğu

Madde 7. Aşağıdaki program çalıştırıldığında ne olur?

class Shape:
    def area(self):
        raise NotImplementedError("Alt sınıf hesaplamalı")

class Square(Shape):
    def __init__(self, side):
        self.side = side

s = Square(3)
print("Oluşturuldu")
print(s.area())
  • A. Hiçbir şey yazdırılmaz, Square(3) satırında hata yükselir
  • B. Oluşturuldu, ardından area() sonucu olarak None yazdırılır
  • C. Oluşturuldu, ardından NotImplemented yazdırılır
  • D. Oluşturuldu, ardından 9 yazdırılır
  • E. Oluşturuldu yazdırılır, ardından NotImplementedError yükselir

Madde 8. Alt sınıfın uygulaması gereken bir davranışı üst sınıfta işaretlemek için hangi yazım doğrudur?

  • A. raise NotImplemented
  • B. pass yazıp gövdeyi boş bırakmak
  • C. return NotImplemented
  • D. return NotImplementedError("Alt sınıf hesaplamalı")
  • E. raise NotImplementedError("Alt sınıf hesaplamalı")

Madde 9. __eq__ tanımlayıp uygun __hash__ tanımlamayan bir sınıfın örnekleri için ne olur?

  • A. Python kendiliğinden uygun bir __hash__ üretir
  • B. Hashlenemez olur; set elemanı ya da dict anahtarı olamaz
  • C. Sınıftan nesne oluşturulamaz
  • D. Hiçbir şey olmaz; hash davranışı __eq__ tanımından etkilenmez
  • E. Örnekler karşılaştırılamaz hâle gelir

Madde 10. Programın konusuna özgü bir hata (örneğin yetersiz bakiye) için özel istisna tanımlarken hangi temel sınıf uygundur?

  • A. Exception; kendi hatalarınız için güvenli başlangıçtır
  • B. object; Python’daki her sınıfın atasıdır
  • C. NotImplementedError; işlemin yapılamadığını bildirir
  • D. SystemExit; hata olunca programı durdurur
  • E. BaseException; bütün istisnaların köküdür

Madde 11. class InvalidScoreError(ValueError): pass yazmanın, Exception sınıfından türetmeye göre kazancı nedir?

  • A. Hata mesajı otomatik olarak üretilir
  • B. Çağıran kod ister InvalidScoreError ister daha genel ValueError olarak yakalayabilir
  • C. ValueError sınıfından türeyen istisna kendiliğinden günlüğe yazılır
  • D. Python hatayı kendiliğinden yakalar
  • E. İstisna daha hızlı yükseltilir

Madde 1. Doğru: C. Sınıfta __str__ tanımlı olduğu için print() onun döndürdüğü metni yazar.

  • A yanlış: Bu bir __repr__ çıktısı biçimidir; burada __repr__ tanımlı değildir.
  • B yanlış: print() her nesneyi alır ve onu metne çevirerek yazar.
  • D yanlış: Bu varsayılan temsildir; yalnız __str__ de __repr__ de tanımlı değilse görünür.
  • E yanlış: __str__ bir metin döndürür ve print onu yazar.

Madde 2. Doğru: B. Yerine geçme tek yönlüdür: __str__ yoksa str() __repr__ sonucunu kullanabilir; ama repr() hiçbir zaman __str__ metoduna bakmaz. Yalnız __str__ tanımlamak repr davranışını değiştirmez.

  • A yanlış: Sınıfta tek temsil metodu olduğu için Python’un onu her yerde kullanacağı sanılabilir. Ama repr kendi varsayılanında kalır.
  • C yanlış: Sınıfta __repr__ yazılmadığı için metodun eksik olduğu düşünülebilir. Ama varsayılan __repr__ her sınıfta bulunur.
  • D yanlış: Temsil yazılmadığı için boş sonuç beklenebilir. Ama varsayılan temsil sınıfın adını ve nesnenin kimlik bilgisini (0x...) içerir.
  • E yanlış: Bir şey tanımlanmadığında sonuç None olacakmış gibi görünür. Ama repr() her zaman bir metin döndürür.

Madde 3. Doğru: D. print(product) kullanıcıya dönük str temsilini yazar. Liste ise kendini metne çevirirken her elemanın repr temsilini kullanır.

  • A yanlış: İlk satırda __str__ tanımlı olduğu için o kullanılır.
  • B yanlış: Koleksiyonlar elemanları için str değil repr kullanır.
  • C yanlış: Liste gösterimi elemanın __str__ metodunu hiç çağırmaz.
  • E yanlış: Sınıfta __repr__ tanımlıdır; varsayılan temsil kullanılmaz.

Madde 4. Doğru: C. Liste kendini metne çevirirken her elemanın repr temsilini kullanır; __str__ bu sırada hiç çağrılmaz. print(obj) ile print([obj]) aynı metodu çağırmaz. Liste çıktısını değiştirmek için sınıfa __repr__ da yazmak gerekir.

  • A yanlış: Liste çıktısı köşeli parantezlerle ham göründüğü için print() onu hiç işlemiyormuş gibi görünür. Biçimlendirir, ama elemanları gösterirken repr kullanır.
  • B yanlış: Metot çağrılmıyormuş gibi göründüğü için adın yanlış yazıldığı sanılabilir. Doğru ad __str__tir; tek nesne yazdırılınca çalıştığı da görülür.
  • D yanlış: Çıktıyı veren liste olduğu için değişikliğin list sınıfında yapılması gerektiği düşünülebilir. Gerekli değildir; elemanın __repr__ metodu yeterlidir.
  • E yanlış: Tek nesne yazdırılınca çıktı değiştiği için sorun eleman sayısında sanılabilir. Ama eleman sayısıyla ilgisi yoktur.

Madde 5. Doğru: A. == artık bizim koyduğumuz kurala (ürün kodları aynı mı?) göre karar verir; is ise hâlâ kimliği sorar ve ortada iki ayrı nesne vardır.

  • B yanlış: __eq__ yazmak nesneleri aynı nesne yapmaz.
  • C yanlış: __eq__ tanımlandığı için kodlar eşit olduğunda True döner.
  • D yanlış: Sonuçlar ters yazılmış.
  • E yanlış: other bir Product olduğu için o dal hiç çalışmaz.

Madde 6. Doğru: D. Eşitlik bir tasarım kararıdır ve programın konusuna göre verilir: Product için kod, Book için ISBN, Student için öğrenci numarası olabilir.

  • A yanlış: is kimliği sorduğu için eşitliğin de bellekle ilgili olduğu sanılabilir. Ama bellek yerleşimiyle ilgisi yoktur.
  • B yanlış: Metotların üst sınıftan devralındığını bilen öğrenci eşitliğin de oradan geleceğini düşünebilir. Ama kalıtım eşitlik kuralını belirlemez.
  • C yanlış: __eq__ ile __hash__ birlikte anıldığı için hash ayrıntısı öncelikli görünebilir. Bu bir uygulama ayrıntısıdır; önce eşitlik kuralı belirlenir.
  • E yanlış: Eşitlik “bütün nitelikler aynı mı?” diye düşünülünce nitelik sayısı önemli görünür. Ama nitelik sayısı kuralı belirlemez; kural, nesneyi hangi niteliğin tanıttığına bağlıdır.

Madde 7. Doğru: E. Square, area metodunu yeniden yazmayı (override) unutmuş. Python bunu nesne oluşturulurken denetlemediği için Square(3) sorunsuz çalışır. s.area() çağrılınca üst sınıftaki gövde çalışır ve NotImplementedError açıkça ortaya çıkar.

  • A yanlış: Eksik metot nesnenin kendisini eksik bırakıyormuş gibi görünebilir. Ama NotImplementedError yalnız metot çağrılınca yükselir; nesne oluşturmak onu tetiklemez.
  • B yanlış: area() alt sınıfta yazılmadığı için bir şey döndürmeyeceği sanılabilir. Ama metot None döndürmez, istisna yükseltir. None ancak gövde pass ile boş bırakılsaydı görülürdü.
  • C yanlış: NotImplemented ile NotImplementedError adları birbirine çok benzer. Ama raise bir değer döndürmez, istisna yükseltir; program print çağrısına ulaşamaz.
  • D yanlış: Kare ve kenar uzunluğu verildiği için alanın hesaplanacağı düşünülebilir. Ama alan hesabı hiçbir yerde yazılmadı; Python side niteliğinden alanı kendisi çıkarmaz.

Madde 8. Doğru: E. NotImplementedError, metodun bu sınıfta yazılmadığını bildiren istisnadır ve raise ile yükseltilir.

  • A yanlış: NotImplemented bir istisna değildir; yükseltilemez.
  • B yanlış: Metot hata vermeden None döndürür; alt sınıfın metodu yazmadığı fark edilmez.
  • C yanlış: return NotImplemented, __eq__ gibi iki nesneyi karşılaştıran metotlarda kullanılır.
  • D yanlış: İstisna sınıfı döndürülmez; yükseltilir.

Madde 9. Doğru: B. Eşit kabul edilen nesnelerin aynı hash değerine sahip olması gerekir. Python bu sözleşmeyi koruyabilmek için çoğu durumda varsayılan hash’i kaldırır; örnekler set elemanı ya da dict anahtarı olarak kullanılamaz.

  • A yanlış: Python varsayılan __repr__ verdiği için uygun bir __hash__ da yazacağı sanılabilir. Ama Python __hash__ metodunu __eq__ kuralına göre kendiliğinden yazmaz.
  • C yanlış: Eksik bir özel metot sınıfı kullanılamaz hâle getiriyormuş gibi görünebilir. Ama nesne oluşturma etkilenmez.
  • D yanlış: __eq__ yalnız == işlecini ilgilendiriyormuş gibi görünür. Ama hash davranışı da etkilenir; varsayılan __hash__ kaldırılır.
  • E yanlış: Sorun eşitlik metoduyla başladığı için == işleminin bozulduğu sanılabilir. Ama == çalışır; kaybolan hash davranışıdır.

Madde 10. Doğru: A. Programın konusuna özgü hatalar Exception sınıfından türetilir. class InsufficientBalanceError(Exception): pass yaygın ve güvenli kalıptır.

  • B yanlış: Her sınıf object sınıfından türediği için en temel seçim gibi görünür. Ama yalnız object sınıfından türeyen bir sınıf istisna olarak yükseltilemez.
  • C yanlış: Adı işin yapılamadığını çağrıştırdığı için yetersiz bakiyeye uyuyor gibi görünebilir. Ama bu istisna metodun yazılmadığını bildirir; bakiye ya da not hatası gibi konuya özgü hatalar için değildir.
  • D yanlış: Hata olunca programın durması gerektiği düşünülürse bu sınıf akla gelebilir. Ama SystemExit programı kapatma isteğini bildirir; çağıran kod yetersiz bakiyeyi yakalayıp çalışmayı sürdürebilmelidir.
  • E yanlış: Bütün istisnaların kökü olduğu için en kapsamlı seçim gibi görünür. Ama BaseException, KeyboardInterrupt ve SystemExit gibi programın akışını durduran istisnaların da köküdür; kendi hatalarınız doğrudan buradan türetilmez.

Madde 11. Doğru: B. Geçersiz sınav notu zaten geçersiz bir değerdir; ValueError sınıfından türetmek hatanın anlamına uyar. Yine de yalnızca özel sınıf yazmış olmak için katman katman istisna sınıfı kurulmamalıdır.

  • A yanlış: Mesajı istisnayı yükseltirken siz verirsiniz.
  • C yanlış: Günlükleme ayrı bir konudur.
  • D yanlış: Yakalama yine çağıranın işidir.
  • E yanlış: Başarım farkı ölçüt değildir.

Tek sayfa özet

  • __str__, __repr__ ve __eq__ gibi özel metotlar yazarsanız print(), repr() ve == sizin sınıfınızla da istediğiniz gibi çalışır.
  • __str__ kullanıcıya, __repr__ geliştiriciye gösterilecek metni döndürür. Listeler elemanlarını gösterirken repr kullanır.
  • Alt sınıfın yazması gereken metot üst sınıfta raise NotImplementedError ile işaretlenir. Alt sınıf bu metodu yazmayı unutursa hata sessiz kalmaz; metot çağrıldığı anda ortaya çıkar.
  • __eq__, iki nesnenin ne zaman “aynı” sayılacağını problem alanına göre sizin belirlediğiniz kurala bağlar. Hashlenebilirlik bununla ilişkili ayrı bir sözleşmedir: eşit nesnelerin hash değeri aynı olmalıdır.
  • Özel istisnalar çoğunlukla Exception sınıfından türetilir. Hata yerleşik bir türün özel biçimiyse (InvalidScoreError ile ValueError gibi) o türden türetilir.

Bu bölümün kazanımları

Bu bölümü bitiren öğrenci:

  • __str__ ile kullanıcıya dönük temsil yazar.
  • __repr__ ile hata ayıklamada nesnenin durumunu açık gösteren temsil yazar.
  • Koleksiyonların elemanlarını gösterirken repr() kullandığını belirler.
  • __eq__ ile programın konusuna uygun bir eşitlik kuralı yazar ve bunu nesne kimliğinden (is) ayırır.
  • Alt sınıfın uygulaması gereken metodu raise NotImplementedError ile işaretler ve alt sınıf bu metodu yazmayı unutursa ne olacağını açıklar.
  • __eq__ tanımlayan sınıfın hash sözleşmesini gözetmesi gerektiğini bilir.
  • Özel istisna sınıfı için uygun temel sınıfı seçer.
Back to top