1

使用__get__描述符我想实现这样的目标:

class Wrapper:
    def __init__(self, wrapped_value):
        self._wrapped_value = wrapped_value

    def __get__(self, instance, owner):
        return self._wrapped_value

wrapper = Wrapper('foo')
assert type(wrapper) == type('foo')

事实证明,__get__只有当实例是某个其他类的类属性时才会调用该描述符,而当实例是独立对象(未绑定到任何类属性)Wrapper时,它不会被调用。Wrapper

有没有办法让__get__描述符在非类属性中工作?

主要目标是实现包装器,它在使用时就像包装的值一样(我知道乍一看这听起来没什么用,但在某些用例中这会有所帮助)。那么也许有其他方法可以在不使用__get__描述符的情况下实现这一点?

4

1 回答 1

2

如果您希望 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 类不会被报告为Foobytype或检查,但只要调用代码依赖于鸭子类型而不是(非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
于 2018-12-31T10:36:34.817 回答