__getattribute__ bir öznitelik erişimi gerçekleştiğinde çağrılır.
class Foo(object):
def __init__(self, a):
self.a = 1
def __getattribute__(self, attr):
try:
return self.__dict__[attr]
except KeyError:
return 'default'
f = Foo(1)
f.a
Bu sonsuz tekrarlamaya neden olur. Buradaki suçlu çizgi return self.__dict__[attr]. Tüm niteliklerin self.__dict__adlarına göre depolandığını ve mevcut olduklarını varsayalım (gerçeğe yeterince yakın) . Çizgi
f.a
aözelliğine erişmeye çalışır f. Bu çağırıyor f.__getattribute__('a'). __getattribute__sonra yüklemeye çalışır self.__dict__. __dict__bir özniteliktir self == fve bu nedenle f.__getattribute__('__dict__')yine özniteliğe erişmeye çalışan python çağrılarıdır '__dict__'. Bu sonsuz özyineleme.
Eğer __getattr__o zaman yerine kullanılmıştır vardı
- Asla koşmazdı çünkü
fbir aniteliği var.
- Çalışmış olsaydı, (diyelim ki siz istediniz
f.b), o zaman __dict__zaten orada olduğu ve __getattr__yalnızca özniteliği bulmanın diğer tüm yöntemleri başarısız olduğunda çağrıldığı için bulmak için çağrılmazdı .
Kullanarak yukarıdaki sınıfını yazmaya 'doğru' yolu __getattribute__olduğunu
class Foo(object):
# Same __init__
def __getattribute__(self, attr):
return super(Foo, self).__getattribute__(attr)
super(Foo, self).__getattribute__(attr)__getattribute__'en yakın' üst sınıf yöntemini (resmi olarak, sınıfın Yöntem Çözüm Sırası veya MRO'daki bir sonraki sınıf) geçerli nesneye bağlar selfve sonra çağırır ve bunu yapmasına izin verir.
Tüm bu sorun, bir öznitelik bulunana kadar __getattr__Python'un normal bir şey yapmasına izin veren kullanarak önlenir . Bu noktada, Python __getattr__yönteminizi kontrol eder ve bir şey bulmasına izin verir.
Ayrıca sonsuz özyineleme ile karşılaşabileceğinizi belirtmek gerekir __getattr__.
class Foo(object):
def __getattr__(self, attr):
return self.attr
Bunu egzersiz olarak bırakacağım.