python - 对非类属性使用 Python 的 __get__ 描述符

标签 python class attributes python-descriptors

使用 __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')

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

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

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

最佳答案

如果您希望包装类控制对包装类属性的访问,您可以使用 __getattr__ 魔术方法。

假设我们有一个类 Foo:

class Foo(object):

    def bar(self):
        return 'bar'

    def baz(self):
        return 'baz'

假设我们正在与一些我们无法控制的代码进行交互,这些代码要求 Foo.bar() 的输出为大写,并且我们不想显式调用 .upper() 在我们的代码中。

我们可以创建一个包装类来拦截对 Foo.bar() 的调用,但透明地允许访问 Foo 的其他方法(这本质上是 Adapter pattern ) .

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

此包装类不会被 typeisinstance 检查报告为 Foo,但除此之外它可以用来代替 Foo 只要调用代码依赖于 duck-typing 而不是(非Pythonic)显式类型检查。

必须显式拦截诸如 __str__ 之类的魔术方法。这是因为这些方法始终直接在实例的类上为 looked up,因此 __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

关于python - 对非类属性使用 Python 的 __get__ 描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53958030/

相关文章:

python - 递增列表索引 if 条件

python - 有没有办法在 Python Flask-RESTFUL 中配置路由层次结构?

c# - 如何在不实例化另一个类的情况下引用该方法?

asp.net-mvc-2 - ASP.NET MVC2 - 在服务器端验证之前从表单提交中修剪空白?

c - GNU C 中的 __attribute__((const)) 与 __attribute__((pure))

python - Bokeh 中的自动图例放置

python - 使 Python-Telegram-Bot 持久化

c++ - 结构与类的性能

c++ - 私有(private)成员的作用是什么?

jquery - 如何将父元素的属性设置为子元素的属性?