我想使用装饰器对派生类做一些事情(例如注册类或其他东西)。这是我的代码:
from functools import wraps
class Basic(object):
def __init__(self):
print "Basic::init"
def myDeco(name):
# define the decorator function that acts on the actual class definition
def __decorator(myclass):
# do something here with the information
print name, myclass
# do the wrapping of the class
@wraps(myclass)
def __wrapper(*args, **kwargs):
return myclass( *args, **kwargs)
# return the actual wrapper here
return __wrapper
# return the decorator to act on the class definition
return __decorator
@myDeco("test")
class Derived(Basic):
def __init__(self):
super(Derived, self).__init__()
print "Derived::init"
instance = Derived()
会出现以下错误:
TypeError: must be type, not function
调用super
中的Derived
方法时。我假设变量Derived
不再是type
,而是函数__decorator
。
如何更改装饰器(仅限装饰器)来解决此问题?
答案 0 :(得分:3)
您正在用函数替换已修饰的类,因此类定义失败。
具体来说,super(Derived, self).__init__()
现在将函数传递给super()
:
>>> super(Derived, object())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: must be type, not function
>>> type(Derived)
<type 'function'>
类装饰器通常会更改类,添加,删除或更改它的属性,然后再次返回类对象。
您应该不用新班级替换Derived
,因为您的Derived.__init__()
通过名称引用自己。用另一个类替换该名称将导致痛苦(例如无限递归)。
工作的示例类装饰器:
def my_deco(name):
# define the decorator function that acts on the actual class definition
def decorator(cls):
# do something here with the information
print name, cls
setattr(class, name, 'Hello world!')
# return the original, augmented class
return cls
# return the decorator to act on the class definition
return decorator
答案 1 :(得分:0)
您的计划中有两个错误:
from functools import wraps
class Basic(object):
def __init__(self):
print "Basic::init"
def myDeco(name):
# define the decorator function that acts on the actual class definition
def __decorator(myclass):
# do something here with the information
print name, myclass
# do the wrapping of the class
class Wrap(myclass): # error 1
realSuper = myclass # I dislike this. has anyone an other aproach
def __new__(*args, **kwargs):
return myclass.__new__(*args, **kwargs)
# return the actual wrapper here
return Wrap
# return the decorator to act on the class definition
return __decorator
@myDeco("test")
class Derived(Basic):
def __init__(self):
super(Derived.realSuper, self).__init__() # error 2
print "Derived::init"
instance = Derived()
现在提供以下输出:
test <class '__main__.Derived'>
Basic::init
Derived::init
首先,你需要一个其他人指出的课程。
第二个super(Derived, self).__init__()
导致无休止的递归:
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
exec s
File "<string>", line 32, in <module>
File "<string>", line 28, in __init__
File "<string>", line 28, in __init__
File "<string>", line 28, in __init__
File "<string>", line 28, in __init__
由于这个原因,请参阅下面的讨论。