Why doesn't Python call instance method __init__() on instance creation but calls class-provided __init__() instead?

Viewed 1515

I'm overring the __new__() method of a class to return a class instance which has a specific __init__() set. Python seems to call the class-provided __init__() method instead of the instance-specific method, although the Python documentation at

http://docs.python.org/reference/datamodel.html

says:

Typical implementations create a new instance of the class by invoking the superclass’s __new__() method using super(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__().

Here's my test code:

#!/usr/bin/env python

import new

def myinit(self, *args, **kwargs):
    print "myinit called, args = %s, kwargs = %s" % (args, kwargs)


class myclass(object):
    def __new__(cls, *args, **kwargs):
        ret = object.__new__(cls)

        ret.__init__ = new.instancemethod(myinit, ret, cls)
        return ret

    def __init__(self, *args, **kwargs):
        print "myclass.__init__ called, self.__init__ is %s" % self.__init__
        self.__init__(*args, **kwargs)

a = myclass()

which outputs

$ python --version
Python 2.6.6
$ ./mytest.py
myclass.__init__ called, self.__init__ is <bound method myclass.myinit of <__main__.myclass object at 0x7fa72155c790>>
myinit called, args = (), kwargs = {}

It seems the only way to get myinit() to run, is to call it explicitly as self.__init__() inside myclass.__init__().

3 Answers

Why doesn't Python call instance method init() on instance creation but calls class-provided init() instead?

Check out this example.

class C:
   one = 42
   def __init__(self,val):
        self.two=val
ci=C(50)
print(ci.__dict__)
print(C.__dict__)

The result will be like this:

{'two': 50}
{'__module__': '__main__', 'one': 42, '__init__': <function C.__init__ at 0x00000213069BF6A8>, '__dict__': <attribute '__dict__' of 'C' objects>, '__weakref__': <attribute '__weakref__' of 'C' objects>, '__doc__': None}

Note that only the value {'two': 50} is part of the instance dict.

'one': 42 belongs to a class C dict. The same is with the __init__ method.

This is per design.

Related