装饰程序@wrapper
正在使用wrapt
库访问包装函数的类以获取类的名称。在Animal.method()
和foo()
上使用它可以按预期工作。你知道吗
问题:但是,用@classmethod
修饰的方法Animal.classy
将type
作为其类名,而用@staticmethod
修饰的方法Animal.static
无法检索其类。你知道吗
@wrapper
decorator函数是否可以获得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
问题是arg
instance
是任何方法的第一个参数的值。所以对于一个常规方法,这将是它的self
值,对于一个类方法,这将是cls
值。对于静态方法,您没有第一个/实例参数,因此它的行为就像它是一个函数,instance
是None
。你知道吗我们来看看你的代码。调用
foo
,包装器检查是否设置了instance
,因为函数没有获得实例参数,所以它会打印出函数的名称。你知道吗接下来调用
method
的实例Animal
。包装器检查是否设置了instance
,这是因为方法得到一个实例参数,所以它会打印出instance
的类名和方法名。你知道吗接下来调用类
Animal
上的classy
。包装器检查是否设置了instance
,这是因为类方法获取实例参数,所以它会打印出instance
的类名称和类方法的名称。但是,在本例中,instance
是在其上定义方法的类,因此在执行instance.__class__
操作时,它将检索Animal
类的元类,即type
。所以在这种情况下,您实际需要的是添加一个检查if isinstance(instance, type)
,在这种情况下,您需要执行print(f"{instance.__name__}.{wrapped.__name__}")
,因为在这种情况下,instance是您的类。你知道吗最后,调用类
Animal
上的静态方法static
。当您声明一个静态方法时,它的行为就像一个普通函数。因此,包装器检查instance
是否已设置,并发现未设置,因为函数不获取实例参数,所以继续并只打印函数名。据我所知,没有标准的方法来检测静态方法。你知道吗所以总结一下,回答你的确切问题。是否可以获取
classy
的类名?对。有没有可能得到static
的类名?我不知道。你知道吗有关实现可在不同上下文中应用的装饰器的更多信息,请参见:
特别是它提供了一个例子:
这可能有助于理解在每种情况下需要采取哪些步骤来计算名称。你知道吗
希望这有道理。你知道吗
相关问题 更多 >
编程相关推荐