如果您希望 Wrapper 类控制对包装类属性的访问,您可以使用__getattr__
魔法方法。
假设我们有一堂课Foo
:
class Foo(object):
def bar(self):
return 'bar'
def baz(self):
return 'baz'
假设我们正在与一些我们无法控制的代码进行交互,这些代码要求输出为Foo.bar()
大写,并且我们不想.upper()
在代码中显式调用。
我们可以创建一个包装类来拦截对 的调用Foo.bar()
,但透明地允许访问Foo
的其他方法(这本质上是适配器模式)。
class Wrapper(object):
def __init__(self, wrapped):
self._wrapped = wrapped
def __getattr__(self, name):
# If 'name' isn't an attribute of this class,
# get it from the wrapped instance.
return getattr(self._wrapped, name)
def bar(self):
# Intercept calls to the wrapped instance's bar() method.
return self._wrapped.bar().upper()
>>> wrapper = Wrapper(Foo())
>>> print wrapper.baz()
baz
>>> print wrapper.bar()
BAR
这个 Wrapper 类不会被报告为Foo
bytype
或检查,但只要调用代码依赖于鸭子类型而不是(非pythonic)显式类型isinstance
检查,它就可以代替它使用。Foo
拦截诸如__str__
必须显式完成的魔术方法。这是因为这些方法总是直接在实例的类上查找__getattr__
,因此__getattribute__
被绕过。
因此,要覆盖Foo.__str__
您需要执行以下操作:
class Foo(object):
...
def __str__(self):
return 'I am a Foo'
class Wrapper(object):
...
def __str__(self):
return str(self._wrapped)
>>> wrapper = Wrapper(Foo())
>>> print wrapper
I am a Foo