In python, what is super(classItSelf) doing? - python

In python, what is super(classItSelf) doing?
I have a project to work on has code such as this:
class Tele(TcInterface):
_signal = signal.SIGUSR1
def __init__(self):
super(Tele, self).__init__()
self._c = None
What is this line doing?
super(Tele, self).__init__()
I am a cpp java code, Really got confused about python stuff.

This calls the __init__() function (constructor) of the super/parent class (TclInterface). This is often necessary, as the superclass constructor is otherwise overridden by __init__() in the subclass.

you need to pass at least self to __init__.
python is different from some traditional OOP languages, which will handle self or this or whatever name you give to the current instance automatically for you.
in python, self is exposed, even in constructor, so that you need to pass in and reference it yourself. and this super(...) here, it basically looks for a proxy, which represents all super classes, and super(...).__init__ is referencing the constructors from the super classes. it's the same concept as you call super() in C++ or Java.
please reference doc for more: https://docs.python.org/2/library/functions.html#super

Related

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
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).
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.
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).
Because in SuperClass.__init__(self), you're calling the method on the class, not the instance, so it cannot be passed implicitly. Similarly you cannot just call SubClass.subMethod(), but you can call SubClass.subMethod(k) and it'll be equivalent to k.subMethod(). Similarly if self refers to a SubClass then self.__init__() means SubClass.__init__(self), so if you want to call SuperClass.__init you have to call it directly.

Is there a purpose in calling super() from a basic python class?

I have somewhat of a strange question here. Let's say I'm making a simple, basic class as follows:
class MyClass(object):
def __init__(self):
super(MyClass, self).__init__()
Is there any purpose in calling super()? My class only has the default object parent class. The reason why I'm asking this is because my IDE automagically gives me this snippet when I create a new class. I usually remove the super() function because I don't see any purpose in leaving it. But maybe I'm missing something ?
You're not obliged to call object.__init__ (via super or otherwise). It does nothing.
However, the purpose of writing that snippet in that way in an __init__ function (or any function that calls the superclass) is to give you some flexibility to change the superclass without modifying that code.
So it doesn't buy you much, but it does buy you the ability to change the superclass of MyClass to a different class whose __init__ likewise accepts no-args, but which perhaps does do something and does need to be called by subclass __init__ functions. All without modifying your MyClass.__init__.
Your call whether that's worth having.
Also in this particular example you can leave out MyClass.__init__ entirely, because yours does nothing too.

Why is __init__ apparently optional?

While experimenting, I wrote:
class Bag:
pass
g = Bag()
print(g)
Which gave me:
<__main__.Bag object at 0x00000000036F0748>
Which surprised me. I expected an error when I tried to initialize it, since I didn't define __init___.
Why isn't this the case?
You only need to override the methods you want to change.
In other words:
If you don't override __init__, the __init__ method of the superclass will be called.
E.g.
class Bag:
pass
if equivalent to:
class Bag:
def __init__(self):
super(Bag, self).__init__()
Furthermore, __init__ is indeed optional. It is an initializer for an instance.
When you instantiate a class (by calling it) the constructor for the class (class method __new__) is called. The constructor returns an instance for which __init__ is called.
So in practice even:
class Bag:
def __init__(self):
pass
Will work just fine.
__init__ is an intializer not the constructor, If an __init__ method is defined it is used just to initialize the created object with the values provided as arguments. An object anyhow gets created even if an __init__ method is not defined for the class, however not initialized, as __init__ method is not overridden to customize as per your needs.
You do not need to include the __init__ method if you do not intend on adding/changing it's functionality. Everything in python is an object and python objects have a number of built in methods, some of which you may include when creating your own object and some of which you may not. This is not a bad reference for learning about built in methods.
http://www.rafekettler.com/magicmethods.html
I might add one thing. If you intend on using the super function, it is a good idea to define objects which inherit from object. Perhaps this is not required in python 3+ but it is certainly true for some of the older versions.
class Bag(object):
def __init__(self):
super(Bag, self).__init__()
# Adding extra functionality here.

Why are parent constructors not called when instantiating a class? [duplicate]

This question already has an answer here:
Why not constructor of super class invoked when we declare the object of sub class?
(1 answer)
Closed 9 years ago.
class A:
def __init__(self):
print 'A'
class B(A):
def __init__(self):
print 'B'
b = B()
B
In C++, I would have expected to see A B output, but in Python I am getting only B. I know that I can do super(B, self).__init__() to achieve the same in Python, but as this is apparently not the default (or is it - I am new to the syntax as well), I am worried that the paradigms for instatinating objects are completely different.
So what are objects in Python, what is their relation with classes and what is the standard way to initialize all data in all parent classes in Python?
Python rarely does anything automatically. As you say, if you want to invoke the superclass __init__, then you need to do it yourself, usually by calling super:
class B(A):
def __init__(self):
print 'B'
super(B, self).__init__()
The point to note is that instance attributes, like everything else in Python, are dynamic. __init__ is not the constructor, that's __new__ which you rarely need to meddle with. The object is fully constructed by the time __init__ is called, but since instance attributes are dynamic they are usually added by that method, which is only special in that it's called first once the object is created.
You can of course create instance attributes in any other method, or even from outside the class itself by simply doing something like myBobj.foo = 'bar'.
So what are objects in Python
Well, objects in python are like dictionaries of members and methods. It's no more sophisticated than that. You don't have visibility handling (if you want to hide a member, just do not talk about it in the public documentation, only with a comment).
what is their relation with classes
A class defines the method/member skeleton that will instantiate that dict/object. So you got the constructor __init__(), which is only a handler used when you create that object.
what is the standard way to initialize all data in all parent classes in Python?
Either you do not redefine the constructor, and then all parent classes will have their constructor initiated (like the default C++ behavior) or you do redefine the constructor, and then have to make an explicit call to your parent class's constructor.
Remember the zen of python: "Explicit is better than implicit". It totally applies here.
You need to invoke the base constructor in your inherited class constructor:
class B(A):
def __init__(self):
A.__init__(self)
# super(B, self).__init__() you can use this line as well
print 'B'

Why not constructor of super class invoked when we declare the object of sub class?

I am a Java programmer, beginner in Python programming. I have noticed unexpected behavior in python programming. I was expecting the print sequence as B class ,A Class constructors. But it's executing constructor of A only.
Output as "Its Constructor of A",Could you please help me to understand flow of execution. Thanks in advance
class B:
def __init__(self):
print 'Its constructor of B'
class A(B):
def __init__(self):
print 'Its constructor of A'
#B.__init__(self)
if __name__=='__main__':
obj=A()
In python you should call the parent's initializer (that's how the __init__ method is actually called, - "constructor" is something else) explicitly.
You can do it like you did in the commented out line. Better yet, you should use the super function, that figures out, which parent to access for you. It only works with new-style classes though (basically, that means, that the root of your class hierarchy must inherit from object).

Categories

Resources