Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Explicit passing of Self when calling super class's __init__ in python

This question is in relation to posts at What does 'super' do in Python? , How do I initialize the base (super) class? , and Python: How do I make a subclass from a superclass? which describes two ways to initialize a SuperClass from within a SubClass as

class SuperClass:
    def __init__(self):
        return
    def superMethod(self):
        return


## One version of Initiation
class SubClass(SuperClass):
    def __init__(self):
        SuperClass.__init__(self)
    def subMethod(self):
        return

or

class SuperClass:
    def __init__(self):
        return
    def superMethod(self):
        return

## Another version of Initiation
class SubClass(SuperClass):
    def __init__(self):
        super(SubClass, self).__init__()
    def subMethod(self):
        return

So I'm a little confused about needing to explicitly pass self as a parameter in SuperClass.__init__(self) and super(SubClass, self).__init__(). (In fact if I call SuperClass.__init__() I get the error

TypeError: __init__() missing 1 required positional argument: 'self'

). But when calling constructors or any other class method (ie :

## Calling class constructor / initiation
c = SuperClass()
k = SubClass()

## Calling class methods
c.superMethod()
k.superMethod()
k.subMethod()

), The self parameter is passed implicitly .

My understanding of the self keyword is it is not unlike the this pointer in C++, whereas it provides a reference to the class instance. Is this correct?

If there would always be a current instance (in this case SubClass), then why does self need to be explicitly included in the call to SuperClass.__init__(self)?

Thanks

like image 602
WoodMath Avatar asked Apr 11 '16 18:04

WoodMath


People also ask

What is the effect of calling super () __ Init__?

__init__() of the superclass ( Square ) will be called automatically. super() returns a delegate object to a parent class, so you call the method you want directly on it: super(). area() . Not only does this save us from having to rewrite the area calculations, but it also allows us to change the internal .

What does super () __ Init__ do in Python?

When you initialize a child class in Python, you can call the super(). __init__() method. This initializes the parent class object into the child class. In addition to this, you can add child-specific information to the child object as well.

What is __ init __( self in Python?

The self in keyword in Python is used to all the instances in a class. By using the self keyword, one can easily access all the instances defined within a class, including its methods and attributes. init. __init__ is one of the reserved methods in Python. In object oriented programming, it is known as a constructor.

What does passing self do in Python?

self represents the instance of the class. By using the “self” we can access the attributes and methods of the class in python. It binds the attributes with the given arguments. The reason you need to use self. is because Python does not use the @ syntax to refer to instance attributes.


3 Answers

This is simply method binding, and has very little to do with super. When you can x.method(*args), Python checks the type of x for a method named method. If it finds one, it "binds" the function to x, so that when you call it, x will be passed as the first parameter, before the rest of the arguments.

When you call a (normal) method via its class, no such binding occurs. If the method expects its first argument to be an instance (e.g. self), you need to pass it in yourself.

The actual implementation of this binding behavior is pretty neat. Python objects are "descriptors" if they have a __get__ method (and/or __set__ or __delete__ methods, but those don't matter for methods). When you look up an attribute like a.b, Python checks the class of a to see if it has a attribute b that is a descriptor. If it does, it translates a.b into type(a).b.__get__(a, type(a)). If b is a function, it will have a __get__ method that implements the binding behavior I described above. Other kinds of descriptors can have different behaviors. For instance, the classmethod decorator replaces a method with a special descriptor that binds the function the class, rather than the instance.

Python's super creates special objects that handle attribute lookups differently than normal objects, but the details don't matter too much for this issue. The binding behavior of methods called through super is just like what I described in the first paragraph, so self gets passed automatically to the bound method when it is called. The only thing special about super is that it may bind a different function than you'd get lookup up the same method name on self (that's the whole point of using it).

like image 123
Blckknght Avatar answered Sep 19 '22 13:09

Blckknght


The following example might elucidate things:

class Example:
    def method(self):
        pass

>>> print(Example.method)
<unbound method Example.method>

>>> print(Example().method)
<bound method Example.method of <__main__.Example instance at 0x01EDCDF0>>

When a method is bound, the instance is passed implicitly. When a method is unbound, the instance needs to be passed explicitly.

The other answers will definitely offer some more detail on the binding process, but I think it's worth showing the above snippet.

like image 25
Jared Goguen Avatar answered Sep 19 '22 13:09

Jared Goguen


The answer is non-trivial and would probably warrant a good article. A very good explanation of how super() works is brilliantly given by Raymond Hettinger in a Pycon 2015 talk, available here and a related article. I will attempt a short answer and if it is not sufficient I (and hopefully the community) will expand on it. The answer has two key pieces:

  • Python's super() needs to have an object on which the method being overridden is called, so it is explicitly passed with self. This is not the only possible implementation and in fact, in Python 3, it is no longer required that you pass the self instance.

  • Python super() is not like Java, or other compiled languages, super. Python's implementation is designed to support the multiple collaborative inheritance paradigm, as explained in Hettinger's talk. This has an interesting consequence in Python: the method resolution in super() depends not only on the parent class, but on the children classes as well (consequence of multiple inheritance). Note that Hettinger is using Python 3.

The official Python 2.7 documentation on super is also a good source of information (better understood after watching the talk, in my opinion).

like image 33
Cyb3rFly3r Avatar answered Sep 22 '22 13:09

Cyb3rFly3r