使用 self 而不是类名调用包装的静态方法会将 self 作为 arg 传递

问题描述 投票:0回答:1

这个问题与使用自身与类名调用静态方法有关,但我试图理解包装静态方法时的行为,以便我可以修复我的包装器。

例如:

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

我很想了解正在发生的事情以及该问题的潜在解决方案!

python python-decorators
1个回答
0
投票

我会修改包装器以接受一个附加参数,指示要包装的方法是否是静态的。也许像:

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()
© www.soinside.com 2019 - 2024. All rights reserved.