このメソッドは、両方のクラスのオブジェクトを交換可能に使用できるため、非常に便利です。これには重大な問題があるので、最後に説明します。
class A:
def MethodA(self):
return "Inside MethodA"
def __init__ (self, Friend=None):
self.__dict__['a'] = "I am a"
self.__dict__['Friend'] = Friend
if Friend is not None: self.__dict__['Friend'].__dict__['Friend'] = self
def __getattr__(self, name):
if self.Friend is not None: return getattr(self.Friend, name)
raise AttributeError ("Unknown Attribute `" + name + "`")
def __setattr__(self, name, value):
if self.Friend is not None: setattr(self.Friend, name, value)
raise AttributeError ("Unknown Attribute `" + name + "`")
class B:
def MethodB(self):
return "Inside MethodB"
def __init__ (self, Friend=None):
self.__dict__['b'] = "I am b"
self.__dict__['Friend'] = Friend
if Friend is not None: self.__dict__['Friend'].__dict__['Friend'] = self
def __getattr__(self, name):
if self.Friend is not None: return getattr(self.Friend, name)
raise AttributeError ("Unknown Attribute `" + name + "`")
def __setattr__(self, name, value):
if self.Friend is not None: setattr(self.Friend, name, value)
raise AttributeError ("Unknown Attribute `" + name + "`")
説明:
このページに従って、要求された属性が特定のオブジェクトのスペースに見つからない場合にのみ、python オブジェクトで呼び出されます__getattr__
。__setattr__
したがって、コンストラクターでは、両方のクラス間の関係を確立しています。そして、__getattr__
orが呼び出されるたびに、メソッド__setattr__
を使用して他のオブジェクトを参照します。getattr
( getattr、setattr )または__dict__
を呼び出さないように、コンストラクターで値を割り当てるために使用します。__setattr__
__getattr__
サンプルラン:
b = B()
# print b.a # Throws AttributeError, as A and B are not related yet
a = A(b)
print a.a
print a.b
print b.a # Works fine here, as 'a' is not found b, returns A's a
print b.b
print a.MethodA()
print a.MethodB()
print b.MethodA()
print b.MethodB()
I am a
I am b
I am a
I am b
Inside MethodA
Inside MethodB
Inside MethodA
Inside MethodB
さて、深刻な問題:
これらの両方のオブジェクトに存在しない属性にアクセスしようとすると、無限再帰になります。「a」から「C」にアクセスしたいとしましょう。C は a にないので、呼び出し__getattr__
て b オブジェクトを参照します。b オブジェクトは C を持たないので、__getattr__
オブジェクト a を参照する呼び出しを行います。したがって、無限再帰になります。したがって、両方のオブジェクトに不明なものにアクセスしない場合、このアプローチはうまく機能します。