这个问题与使用自身与类名调用静态方法有关,但我试图理解包装静态方法时的行为,以便我可以修复我的包装器。
例如:
import functools
def wrap(f):
@functools.wraps(f)
def wrapped(*args, **kwargs):
print(f"{f.__name__} called with args: {args}, kwargs: {kwargs}")
return f(*args, **kwargs)
return wrapped
class Test:
@staticmethod
def static():
print("hello")
def method(self):
self.static()
Test.static = wrap(Test.static)
Test().method()
将产生:
static called with args: (<__main__.Test object at 0x1050b3fd0>,), kwargs: {}
Traceback (most recent call last):
File "/Users/aiguofer/decorator_example.py", line 20, in <module>
Test().meth()
File "/Users/aiguofer/decorator_example.py", line 16, in meth
self.static()
File "/Users/aiguofer/decorator_example.py", line 7, in wrapped
return f(*args, **kwargs)
TypeError: Test.static() takes 0 positional arguments but 1 was given
但是,如果我更改
self.static()
-> Test.static()
,我们会得到预期的输出:
static called with args: (), kwargs: {}
hello
我的用例是我需要包装外部库中的一些方法,包括类上的
staticmethod
。在该类中,他们使用 self.<method_name>
从实例方法调用静态方法,这导致了我的包装器中出现上述问题。我以为我可以用 isinstance(f, staticmethod)
来解决这个问题,但这似乎又回来了 False
。
我很想了解正在发生的事情以及该问题的潜在解决方案!
我会修改包装器以接受一个附加参数,指示要包装的方法是否是静态的。也许像:
import functools
def wrap(f, is_static=False):
@functools.wraps(f)
def wrapped(*args, **kwargs):
print(f"{f.__name__} called with args: {args}, kwargs: {kwargs}")
if is_static:
args = args[1:]
return f(*args, **kwargs)
return wrapped
class Test:
@staticmethod
def static():
print("hello")
def method(self):
self.static()
Test.static = wrap(Test.static, is_static=True)
Test().method()