如何对类进行装饰

时间:2019-06-24 21:40:02

标签: python python-2.7 class static python-decorators

我为继承SuperClass的子类TestClass使用类装饰器。我在SuperClass中有一个叫做what(cls)的类方法,它可以接收一个类。我希望能够在我的子类TestClass中装饰该类,但是它并没有像我所说的那样。

TypeError: unbound method wrapper() must be called with TestClass instance as first argument (got nothing instead)

我尝试对我的TestClass对象进行实例化,然后使用该实例来调用方法testclass.what(cls),它可以工作,但是当我执行TestClass.what()时,它给了我上面的错误。

def class_decorator(cls):
    for attr_name in dir(cls):
        attr_value = getattr(cls, attr_name)
        if hasattr(attr_value, '__call__'):  # check if attr is a function
            # apply the function_decorator to your function
            # and replace the original one with your new one
            setattr(cls, attr_name, ball(attr_value))
    return cls


def ball(func):
    def wrapper(*args, **kwargs):
        print("hello")
        return func(*args, **kwargs)

    return wrapper



class SuperClass:
    def __init__(self):
        pass

    @classmethod
    def what(cls):
        print("testing")


@class_decorator
class TestClass(SuperClass):

    def what(cls):
        super().what()


TestClass.what()

预期:

"hello"
"testing"
"hello"
"testing"

Actual: TypeError: unbound method wrapper() must be called with TestClass instance as first argument (got nothing instead)

1 个答案:

答案 0 :(得分:0)

您的程序存在一些问题;而不是去讨论所有细节,我将指出获得所需输出的方法。

由于您已覆盖what中的类方法TestClass,而现在引发了错误,该类方法现在使用单个参数cls,即cna是任何东西。换句话说,您还需要使用classmethod装饰器来装饰子类中的类方法。

如果要保留当前代码,则需要显式提供cls自变量,应该执行以下操作:

from functools import partial

def class_decorator(cls): 
    for attr_name in vars(cls): 
        attr_value = getattr(cls, attr_name) 
        if callable(attr_value):  # check if attr is a function 
            if attr_name == 'what': 
                setattr(cls, attr_name, partial(ball(attr_value), cls=cls)) 
            else: 
                setattr(cls, attr_name, ball(attr_value)) 

使用partial将类作为第一个参数传递。

此外,我已经使用vars(cls)来获取cls.__dict__,因为dir会基于基递归(您在这里不需要)。另外,不要检查__call__属性,而要使用callable