Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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__().

like image 401
vkoukis Avatar asked Jul 24 '12 16:07

vkoukis


People also ask

How do you call an instance method from a class in Python?

Calling An Instance Method operator to execute the block of code or action defined in the instance method. First, create instance variables name and age in the Student class. Next, create an instance method display() to print student name and age. Next, create object of a Student class to call the instance method.

What does __ call __ do in Python?

The __call__ method enables Python programmers to write classes where the instances behave like functions and can be called like a function. When the instance is called as a function; if this method is defined, x(arg1, arg2, ...) is a shorthand for x.

How do you call a method from an instance of a class?

To call an object's method, you must use the object name and the dot (.) operator followed by the method name, for example object.

Is __ init __ an instance method?

As for your first question, __init__ is neither a staticmethod nor a classmethod; it is an ordinary instance method.


1 Answers

Special methods on new-style classes are looked up on the instance's type, not on the instance itself. This is documented behaviour:

For new-style classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary. That behaviour is the reason why the following code raises an exception (unlike the equivalent example with old-style classes):

>>> class C(object):
...     pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
like image 86
Sven Marnach Avatar answered Sep 20 '22 09:09

Sven Marnach