【发布时间】:2020-04-11 07:39:56
【问题描述】:
装饰器@wrapper 正在使用wrapt 库来访问包装函数的类以获取类的名称。在Animal.method() 和foo() 上使用它可以按预期工作。
问题: 但是,用@classmethod 装饰的方法Animal.classy 将type 作为其类名,而用@staticmethod 装饰的方法Animal.static 无法检索其类。
@wrapper装饰器函数是否可以获取Animal.classy()和Animal.static()的类名Animal?
预期输出
foo
Animal.method
Animal.classy
Animal.static
获得的输出
foo
Animal.method
type.classy
static
重现代码
import wrapt
import time
@wrapt.decorator
def wrapper(wrapped, instance, args, kw):
if instance is not None:
print(f'\n{instance.__class__.__name__}.{wrapped.__name__}')
else:
print('\n' + wrapped.__name__)
result = wrapped(*args, **kw)
return result
@wrapper
def foo():
time.sleep(0.1)
class Animal:
@wrapper
def method(self):
time.sleep(0.1)
@wrapper
@classmethod
def classy(cls):
time.sleep(0.1)
@wrapper
@staticmethod
def static():
time.sleep(0.1)
if __name__ == '__main__':
foo() # foo
Animal().method() # Animal.method
Animal.classy() # type.classy
Animal.static() # static
【问题讨论】:
-
为什么你在类而不是实例上调用classy和static,就像你对方法所做的那样?尝试做
Animal().classy()和Animal().static() -
我不确定您将如何检测您正在寻找的区别。
method正在获取Animal的实例作为参数,但classy只是获取type的实例。static当然,没有得到任何争论。这三个对象都不知道它们被用作Animal的类属性,因此通常在wrapper的主体中没有可用的信息。 -
也就是说,
Animal.method引用了一个函数对象,但该函数对象不知道它是作为Animal类属性引用的。绑定到Animal.classy和Animal.static的函数也是如此。 -
@Pynchia 无论您使用
Animal.classy()还是Animal().classy(),classy仍然只是获得对Animal(type的实例)的引用作为参数。 -
@chepner 我认为
Animal.method确实知道类名。因为它知道它所属的实例,它可以通过instance.__class__来获取实例的类,因此instance.__class__.__name__来获取类名。我的例子能够证明这一点。
标签: python python-3.x decorator wrapt