次のように一般的に最も簡単なアクセスコードエージェントのプロパティの継承の代替クラスとして使用される属性アクセスエージェント:
class A:
def spam(self, x):
pass
def foo(self):
pass
class B:
def __init__(self):
self._a = A()
def spam(self, x):
# Delegate to the internal self._a instance
return self._a.spam(x)
def foo(self):
# Delegate to the internal self._a instance
return self._a.foo()
def bar(self):
pass
この方法は、少数のエージェントを必要とする場合は、次のように、__getattr__クラスメソッドを実装できます。
class A:
def spam(self, x):
pass
def foo(self):
pass
class B:
def __init__(self):
self._a = A()
def bar(self):
pass
# Expose all of the methods defined on class A
def __getattr__(self, name):
return getattr(self._a, name)
>>> b = B()
>>> b.bar()
>>> b.spam(42)
別の例:
class Proxy:
def __init__(self, obj):
self._obj = obj
# Delegate attribute lookup to internal obj
def __getattr__(self, name):
print('getattr', name)
return getattr(self._obj, name)
# Delegate attribute assignment
def __setattr__(self, name, value):
if name.startswith('_'):
super().__setattr__(name, value)
else:
print('setattr:', name, value)
setattr(self._obj, name, value)
# Delegate attribute deletion
def __delattr__(self, name):
if name.startswith('_'):
super().__delattr__(name)
else:
print('delattr:', name)
delattr(self._obj, name)
class Spam:
def __init__(self, x):
self.x = x
def bar(self, y):
print('Spam.bar:', self.x, y)
>>> s = Spam(2)
>>> p = Proxy(s)
>>> print(p.x)
getattr x
2
>>> p.bar(3)
getattr bar
Spam.bar: 2 3
>>> p.x = 37
setattr: x 37
一般的な規則は、エージェントが有力アンダースコアを属性に委任することができないということである(つまり、プロキシが公開「パブリック」プロパティの唯一のリザーブドインスタンス)。
__getattr __()メソッドは、通常、二重下線の始まりと終わりに最も特別な方法には適していません強調することも重要です。次のとおりです。
class ListLike:
def __init__(self):
self._items = []
def __getattr__(self, name):
return getattr(self._items, name)
>>> a = ListLike()
>>> a.append(2)
>>> a.insert(0, 1)
>>> a.sort()
>>> len(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'ListLike' has no len()
>>> a[0]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'ListLike' object does not support indexing
>>>
このようLENを達成するために、メソッドのインデックスを作成、あなたが__len __、__ __ GetItem関数、__ __ SetItem関数、__ delitem__他の方法として実装する必要があります。