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
According to the docs for new-style classes:
Typical implementations create a new instance of the class by invoking the superclass’s
super(currentclass, cls).__new__(cls, ...)with appropriate arguments and then modifying the newly-created instance as necessary before returning it.
__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
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: 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
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
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"