[英]Why does the Pythons __call__ return the same Decorator instance?
[英]In a descriptor, does __call__ have access to the class where the decorator is being used?
考虑以下代码:
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 voodoo”,这意味着它正在访问Python的功能,这些功能不应在常规编程中使用。 因此,在执行此操作之前请仔细考虑 。 它也依赖于实现,因此如果您希望代码可移植到其他Python解释器(CPython除外),请不要依赖于此。 话虽如此:
调用描述符的__call__
方法时,可以使用inspect.stack()
访问解释器堆栈。 返回列表中的第二个堆栈帧表示从中__call__
的上下文。 该堆栈框架中包含的部分信息是上下文名称,该名称通常是一个函数名称,但是在这种情况下__call__
不是从函数内部调用的,而是从类内部调用的,因此上下文名称将是班级名称。
import inspect
class MyCustomDescriptor:
def __call__(self,decorated_method):
self.caller_name = inspect.stack()[1][3]
return self
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.