En iyi bilinen OO dillerinde, gibi bir ifade SomeClass(arg1, arg2)
yeni bir örnek atar, örneğin niteliklerini başlatır ve sonra döndürür.
En iyi bilinen OO dillerinde, "örneğin özniteliklerini başlat" bölümü , temel olarak yalnızca yeni örnek üzerinde çalışan bir kod bloğu olan bir kurucu tanımlanarak (kurucu ifadesine sağlanan argümanlar kullanılarak) her sınıf için özelleştirilebilir ) istediğiniz başlangıç koşullarını ayarlamak için. Python'da bu, sınıfın __init__
yöntemine karşılık gelir .
Python's __new__
, "yeni bir örnek ayır" bölümünün sınıf başına benzer özelleştirmesinden başka bir şey değildir. Bu elbette yeni bir tane ayırmak yerine mevcut bir örneği döndürmek gibi olağandışı şeyler yapmanıza izin verir. Bu yüzden Python'da bu kısmı gerçekten de tahsisi içeren bir şey olarak düşünmemeliyiz; tek ihtiyacımız olan şey__new__
bir yerden uygun bir örnek bulmak.
Ama hala işin sadece yarısı ve Python sisteminin bazen işin diğer yarısını ( __init__
) daha sonra çalıştırmak istediğini ve bazen de yapmadığını bilmenin bir yolu yok. Bu davranışı istiyorsanız, bunu açıkça söylemelisiniz.
Çoğu zaman, sadece ihtiyacınız __new__
olan ya da ihtiyacınız olmayan __new__
ya da __init__
zaten başlatılmış bir nesnede farklı davranan şekilde yeniden düzenleme yapabilirsiniz . Eğer gerçekten, Python aslında izin vermez istiyorsanız böylece Ama, "İşi" yeniden tanımlama SomeClass(arg1, arg2)
mutlaka çağrı gelmez __new__
izledi __init__
. Bunu yapmak için bir metasınıf oluşturmanız ve __call__
yöntemini tanımlamanız gerekir .
Metasınıf sadece bir sınıfın sınıfıdır. Bir sınıf __call__
yöntemi, sınıfın örneklerini çağırdığınızda ne olacağını kontrol eder. Yani bir metasınıf ' __call__
yöntemi, bir sınıfı çağırdığınızda ne olacağını kontrol eder; yani , örnek oluşturma mekanizmasını baştan sona yeniden tanımlamanızı sağlar . Bu, singleton deseni gibi tamamen standart dışı bir örnek oluşturma işlemini en zarif şekilde uygulayabileceğiniz düzeydir. Aslında, kod 10'dan az hatları ile bir uygulayabilirsiniz Singleton
sonra bile futz sizi gerektirmeyen metaclass __new__
hiç ve açabilirsiniz herhangi basitçe ekleyerek bir singleton içine aksi normalin sınıf __metaclass__ = Singleton
!
class Singleton(type):
def __init__(self, *args, **kwargs):
super(Singleton, self).__init__(*args, **kwargs)
self.__instance = None
def __call__(self, *args, **kwargs):
if self.__instance is None:
self.__instance = super(Singleton, self).__call__(*args, **kwargs)
return self.__instance
Ancak bu muhtemelen bu durum için gerçekten garanti edilenden daha derin bir sihirdir!