Python'da bir sınıf nesnesinin oluşturulması iki aşamalı bir süreçtir:
__new__ metodu çağrılır.__init__ çağrılır.__new__ — oluşturma (herhangi bir yeni nesne döndürebilir; zorunlu parametre — sınıf).__init__ — başlatma (zaten ayrılmış bir instance ile çalışır).__new__, değiştirilemez türlerin (tuple, str, int) miras alınması, singleton oluşturulması ve "fabrika" kalıbı için yeniden tanımlanır.class MyStr(str): def __new__(cls, value): print("__new__ çağrıldı") instance = super().__new__(cls, value.upper()) # oluşturulmadan önce değeri değiştiriyoruz return instance def __init__(self, value): print("__init__ çağrıldı", value) s = MyStr('abc') # __new__ çağrıldı -> __init__ çağrıldı abc print(s) # 'ABC'
Eğer sınıfta __new__ tanımlanmadan, değiştirilemez bir nesne __init__ ile başlatılabilir mi?
Hayır! Örneğin, değiştirilemez türler için (str, int, tuple gibi) alanlar/ değerler üzerinde herhangi bir değişiklik __new__ içinde yapılmalıdır, aksi takdirde __init__ içinde değeri değiştirmek mümkün değildir.
class MyTuple(tuple): def __init__(self, items): print(f'__init__! {items}') def __new__(cls, items): print(f'__new__! {items}') return super().__new__(cls, map(str, items)) t = MyTuple([1, 2, 3]) print(t) # ('1', '2', '3')
Hikaye
Büyük bir Django projesinde, özel string türlerini saklamak için str'den miras aldık. Değeri __init__ içinde değiştirmeye çalıştık - ancak sonuç değişmedi çünkü str değiştirilemez. Sadece __new__'ü öğrenip yeniden tanımladıktan sonra düzelttik.
Hikaye
Singleton kalıbını uygularken, __new__ içinde mevcut örneği geri döndürme mantığını unuttuk: sınıfın birçok çağrısı yine de yeni nesneler oluşturdu ve bu hafıza parçalanmasına neden oldu.
Hikaye
Veri serileştirme kütüphanesinde, önbellekleme sırasında __init__'i yeniden tanımlanmış bir sınıf kullandık, ancak önbellek için __new__ ile aynı nesnenin geri döndürülmesi gerektiğini gözden kaçırdık. Bu sebeple, her yeni çağrıda farklı nesneler oluşturulduğu için önbellek bozuldu.