7

I am trying to create (not exactly restore) an object which has its attributes saved in a database. Therefore, I do not want to call __init__. This desire appears to be inline with Guido's intended use for __new__. I do not understand why __init__ is not getting called.

Take the following snippet for example, it returns an instance of class User without calling __init__.

class User(object):
    def __init__(self, arg1, arg2):
        raise Exception

user = User.__new__(User)

print user
<project.models.User object at 0x9e2dfac>

This is the exact behavior I want. However, my question is that I do not understand why?

According to the python docs __init__ is supposed to be called when __new__ "returns an instance of cls."

So why is __init__ not being even called, even though __new__ returns a class instance?

  • 1
    Please post code that actually runs. Did you mean `def __init__`? – Daniel Roseman Aug 01 '11 at 19:32
  • I came across this same thing and get that python doesn't do this. However the docs clearly say "If __new__() returns an instance of cls, then the new instance’s __init__() method will be invoked like __init__(self[, ...])". Is that a doc bug or am I misinterpreting it? – UsAaR33 Aug 02 '12 at 22:12
  • 1
    @UsAaR33 You're misinterpreting it. Calling `SomeClass(args)` will (normally) do `instance = SomeClass.__new__(SomeClass, args)`, and then invoke `instance.__init__(args)` if `instance` was an instance of `SomeClass`. The docs are talking about `__new__` in the context of that sequence, not any time it's invoked, since calling `__new__` directly is even rarer than needing to define it in the first place. – Ben Sep 28 '12 at 10:59

2 Answers2

13

The constructor (User()) is responsible for calling the allocator (User.__new__()) and the initializer (User.__init__()) in turn. Since the constructor is never invoked, the initializer is never called.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
10

Because you're bypassing the usual construction mechanism, by calling __new__ directly. The __init__-after-__new__ logic is in type.__call__ (in CPython see typeobject.c, type_call function), so it happens only when you'd do User(...).

Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224