python - 在描述符中,__call__ 是否可以访问使用装饰器的类?

标签 python decorator

考虑以下代码:

class MyCustomDescriptor:
    def __init__(self,foo):
        self._foo = foo

    def __call__(self,decorated_method):
        # Here's my question...  Is there any way to get a reference to the
        # type (ClassA or ClassB) here?
        return self

    def __get__(self,instance,type):
        # Clearly at this point I can get the type of the class.
        # But it's too late, I would have liked
        # to get it back in __call__.
        return 10

class ClassA:
    @MyCustomDescriptor(foo=1)
    def some_value(self): pass

class ClassB:
    @MyCustomDescriptor(foo=1)
    def some_value(self): pass

我想要获得对该类的引用的原因是我想使用装饰函数/方法向该类添加一些静态数据。我意识到这有点不典型,但对于我正在做的事情,它会有所帮助。

回答 - 无法完成。根据下面的响应之一,我从调用中检查了堆栈,并能够获得使用描述符的完全限定类(在我的示例中为 ClassA 或 ClassB)。但是您不能将其转换为类型/类,因为类型/类仍在被解析(或者 python 中的任何正确术语)。换句话说,python 遇到 ClassA 并开始解析它。在解析它时,它会遇到描述符并调用 init 并调用描述符。 ClassA 仍未完成解析。因此,尽管您可以从调用中获得完全限定的模块/类名称,但您无法将其转换为类型。

最佳答案

在应用装饰器的地方,some_value 只是一个函数,而不是方法。所以,不,函数无法知道它与特定类相关联。

两种选择是:

  • 将类名传递给 MyCustomDescriptor(连同 foo),或者
  • 使用类装饰器创建描述符 some_value

类装饰器可能看起来像这样:

def register(method_name,foo):
    def class_decorator(cls):
        method=getattr(cls,method_name)
        class MyCustomDescriptor(object):
            def __get__(self,instance,type):
                result=method(instance)
                return '{c}: {r}'.format(c=cls.__name__,r=result)
        setattr(cls,method_name,MyCustomDescriptor())
        return cls
    return class_decorator

@register('some_value',foo=1)
class ClassA:
    def some_value(self):
        return 10

比如运行

a=ClassA()
print(a.some_value)

产量

ClassA: 10

关于python - 在描述符中,__call__ 是否可以访问使用装饰器的类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8438987/

相关文章:

python - 类 Python 中的装饰器

python - 对 python 修饰方法的内省(introspection)

oop - builder 与装饰者模式

python - 交叉验证和模型选择

python - 限制Unity ML-Agents/Tensorflow中的 Action 值

java - 改进的集合迭代器

c# - 如何在 C# 中删除无序的装饰器

python - 导入错误 : cannot import name 'trace' from 'tensorflow.python.profiler'

python - 具有历史记录的唯一观看次数

python - 理解 Python asyncio profiler 输出