在 Python 中装饰方法签名中没有 self 的类

Posted

技术标签:

【中文标题】在 Python 中装饰方法签名中没有 self 的类【英文标题】:Decorate class that has no self in method signature in Python 【发布时间】:2016-04-23 12:42:00 【问题描述】:

我正在尝试将装饰器动态应用于类。 如果我有一个在方法签名中包含 self 的类方法,它就可以工作。

工作示例:

from functools import wraps

def debug(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print('awesome')
        f = func(*args, **kwargs)
        return f
    return wrapper

def debugclass(cls):
    # cls is a class
    for key, val in vars(cls).items():
        if callable(val):
            setattr(cls, key, debug(val))
    return cls

class Dude:
    def test(self):
    #def test(): # this does not work
        pass

debugclass(Dude)
dude = Dude()
dude.test()

如何更改 Dude 类方法签名,使其在 self 不参与签名的情况下也能正常工作?

class Dude:
    def test(): # without self
        pass
debugclass(Dude)
dude = Dude()
dude.test()

出现错误:

Traceback (most recent call last):
File "withoutself.py", line 33, in <module>
dude.test()
File "withoutself.py", line 7, in wrapper
f = func(*args, **kwargs)
TypeError: test() takes no arguments (1 given)

【问题讨论】:

【参考方案1】:

要使您的 test() 方法在没有 selfcls 参数的情况下可调用,您需要将其设为 staticmethod

class Dude:
    @staticmethod
    def test():
        pass

然后您还需要更新 debugclass 以包装 staticmethod 对象,因为它们不是可调用对象。不幸的是,您需要一种不同的方式来包装 staticmethod 对象:

def debugclass(cls):
    # cls is a class
    for key, val in vars(cls).items():
        if callable(val):
            setattr(cls, key, debug(val))
        elif isinstance(val, staticmethod):
            setattr(cls, key, staticmethod(debug(val.__func__)))
    return cls

>>> class Dude:
    def test(self):
        pass
    @staticmethod
    def test1():
        pass


>>> debugclass(Dude)
<class __main__.Dude at 0x7ff731842f58>
>>> Dude().test()
awesome
>>> Dude.test1()
awesome

【讨论】:

谢谢!解释得很好。【参考方案2】:

很快,你不能。 详细地说,python 在调用方法时将对象实例作为第一个参数传递。因此,如果您定义一个没有参数的方法,您将获得执行。给定的 1 个参数是您的“老兄”对象。

更多信息请查看https://docs.python.org/2/tutorial/classes.html#method-objects

【讨论】:

以上是关于在 Python 中装饰方法签名中没有 self 的类的主要内容,如果未能解决你的问题,请参考以下文章

python中装饰器装饰类中的方法

Python3-2020-测试开发-20- Python中装饰器@property

8.Python中装饰器是什么?

在类中装饰 @property.setter 装饰器 [重复]

python中装饰器修复技术

在 SwiftUI 中装饰文本片段的最佳方法是啥?