Python Class Decorator
I am trying to decorate an actual class, using this code:
def my_decorator(cls):
def wrap(*args, **kw):
return object.__new__(cls)
return wrap
@my_decorator
class TestClass(object):
def __init__(self):
print "__init__ should run if object.__new__ correctly returns an instance of cls"
test = TestClass() # shouldn't TestClass.__init__() be run here?
I get no errors, but I also don't see the message from TestClass.__init__()
.
According to the docs for new-style classes:
Typical implementations create a new instance of the class by invoking the superclass’s
__new__()
method usingsuper(currentclass, cls).__new__(cls[, ...])
with appropriate arguments and then modifying the newly-created instance as necessary before returning it.If
__new__()
returns an instance of cls, then the new instance’s__init__()
method will be invoked like__init__(self[, ...])
, where self开发者_开发百科 is the new instance and the remaining arguments are the same as were passed to__new__()
.
Any ideas why __init__
isn't running?
Also, I have tried to call __new__
like this:
return super(cls.__bases__[0], cls).__new__(cls)
but it would return a TypeError
:
TypeError: super.__new__(TestClass): TestClass is not a subtype of super
__init__
isn't running because object.__new__
doesn't know to call it. If you change it to
cls.__call__(*args, **kwargs)
, or better, cls(*args, **kwargs)
, it should work. Remember that a class is a callable: calling it produces a new instance. Just calling __new__
returns an instance but doesn't go through the initialization. An alternative would be to call __new__
and then manually call __init__
but this is just replacing the logic that is already embodied in __call__
.
The documentation that you quote is referring to calling super
from within the __new__
method of the class. Here, you are calling it from the outside and not in the usual way as I've already discussed.
Couldn't tell you the reason but this hack does run __init__
def my_decorator(cls):
print "In my_decorator()"
def wrap(*args, **kw):
print "In wrap()"
return cls.__init__(object.__new__(cls), *args, **kw)
return wrap
@my_decorator
class TestClass(object):
def __init__(self):
print "__init__ should run if object.__new__ correctly returns an instance of cls"
精彩评论