我为继承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)
答案 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
。