【问题标题】:How to class decorate a class method如何类装饰类方法
【发布时间】:2019-11-06 17:10:21
【问题描述】:

我正在为继承 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)

【问题讨论】:

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


【解决方案1】:

您的程序存在一些问题;我将指出获得所需输出的方法,而不是详细说明。

由于您在TestClass 中覆盖了类方法what,因此引发了该错误,该方法现在接受一个参数cls,它可以是任何东西。换句话说,您还需要使用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

【讨论】:

  • 现在它说 TestClass 是一个 Nonetype 对象
猜你喜欢
  • 2014-01-14
  • 1970-01-01
  • 1970-01-01
  • 2019-02-03
相关资源
最近更新 更多