__getattribute__属性アクセスが発生するたびに呼び出されます。
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
これにより、無限の再帰が発生します。ここでの犯人はラインreturn self.__dict__[attr]です。self.__dict__すべての属性が名前で格納され、使用可能であると偽ってみましょう(真実に十分近いです) 。この線
f.a
aの属性にアクセスしようとしますf。これはを呼び出しますf.__getattribute__('a')。__getattribute__次に、をロードしようとしますself.__dict__。__dict__はの属性であるself == fため、Pythonは属性'f.__getattribute__('__dict__')に再度アクセスしようとします。'__dict__これは無限再帰です。
__getattr__代わりに使用された場合
- 属性
fがあるため、実行されなかったでしょう。a
- それが実行された場合(あなたが要求したとしましょう
f.b)、それは__dict__すでにそこにあり、属性を見つける他のすべてのメソッドが失敗した__getattr__場合にのみ呼び出されるため、検索するために呼び出されませんでした。
上記のクラスを使用して書く「正しい」方法は次のとおり__getattribute__です。
class Foo(object):
# Same __init__
def __getattribute__(self, attr):
return super(Foo, self).__getattribute__(attr)
super(Foo, self).__getattribute__(attr)__getattribute__'最も近い'スーパークラス(正式には、クラスのメソッド解決順序(MRO)の次のクラス)のメソッドを現在のオブジェクトにバインドし、selfそれを呼び出して、それが作業を実行できるようにします。
この問題はすべて、属性が見つからなくなるまで__getattr__Pythonが通常どおりに実行できるようにすることで回避されます。その時点で、Pythonはメソッドに制御を渡し__getattr__、何かを考え出すことができます。
で無限再帰に遭遇する可能性があることにも注意してください__getattr__。
class Foo(object):
def __getattr__(self, attr):
return self.attr
それは演習として残しておきます。