【问题标题】:How to use a decorator of a descriptor within a sub class如何在子类中使用描述符的装饰器
【发布时间】:2017-07-10 07:36:09
【问题描述】:

我想知道是否可以在子类中使用描述符的装饰器。

class Descriptor():
    def __get__(self, instance_obj, objtype):
        raise Exception('ouch.')
    def decorate(self, f):
        print('decorate', f)
        return f

class A():
    my_attr = Descriptor()

class B():
    @my_attr.decorate
    def foo(self):
        print('hey, whatsup?')

# --> NameError: name 'my_attr' is not defined

这当然行不通,因为my_attrB 的类定义中是未定义的。

接下来我尝试了:

class B():
    @A.my_attr.decorate
    def foo(self):
        print('hey, whatsup?')

# --> Exception: ouch.

但是,这种方法会调用描述符__get__ 方法(其中instance_obj 参数是None),因此会触发测试异常。要访问装饰器,可以检查 instance_obj 是否为 None 并返回描述符本身:

def __get__(self, instance_obj, objtype):
    if instance_obj is None:
        return self
    raise Exception('avoid this')
# --> decorate <function B.foo at 0x1021dd7b8>

有效!但这是合理的还是有办法在B 的类定义中使用装饰器?

【问题讨论】:

    标签: python python-3.x descriptor python-descriptors


    【解决方案1】:

    您可以通过从类的__dict__ 映射中检索原始对象来完全绕过描述符协议:

    A.__dict__['my_attr'].decorate
    

    或更清洁,使用vars():

    vars(A)['my_attr'].decorate
    

    但是,@ 装饰器语法不允许订阅(您只能获得具有属性访问和最后一次调用的更简单的表达式),因此您必须先提取字典 :

    _A_my_attr = vars(A)['my_attr']
    @_A_my_attr.decorate
    def foo(self):
        # ...
    

    但是,除非您必须捕获到类的绑定,否则最好注意__get__ 的第一个参数是None,正如您发现的那样。这正是property 对象或函数所做的。

    【讨论】:

    • 如果他想要一个全局的,我们不会把装饰器放在一个类中
    猜你喜欢
    • 2019-08-01
    • 2013-03-12
    • 2012-07-10
    • 2020-07-24
    • 2017-10-05
    • 2011-11-20
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多