Calling super from parent class [duplicate] - python

This question already has answers here:
using super without inheritance class in python3
(3 answers)
Closed 2 years ago.
I was looking at a code which a Parent class calls super:
class ParentClass:
def __init__(self):
super(ParentClass, self).__init__()
I don't understand why would someone call super on itself and how does this not get stuck on a recursive loop. Is there something in the background of Python mechanisms that I'm missing?

In python, all classes are implicitly a subclass of object. super will always follow a Method Resolution Order (mro) to determine which function to call. This is explained well in the super docs.
So, for a class like-
class ParentClass:
def __init__(self):
super(ParentClass, self).__init__()
The mro follows - ParentClass -> object
Which means super(ParentClass, self) (or the shorthand, super()) translates to object and object.__init__() is indeed a very valid call.

Related

Is overriding a parent class method with a different signature a good practice? [duplicate]

This question already has answers here:
Python Method overriding, does signature matter?
(5 answers)
Closed 2 years ago.
I have this small example with parent/child classes. I know the code will run without problem, but is it a good practice to override a parent's method with a method which has a different signature? PyCharm does not seem to think it is a good idea:
Signature of method 'Daughter.do()' does not match signature of base method in class 'Mother'
For information, calling Parent method do should execute do(self) not do(self, c).
Code example:
class Parent:
def __init__(self):
self._a = "a"
def do(self):
print("Parent: {}".format(self._a))
class Child(Parent):
def __init__(self):
Parent.__init__(self)
self._b = "b"
def do(self, c):
print("Child: {}".format(self._a))
print("Child: {}".format(self._b))
print("Child: {}".format(c))
It is a bad practice. It for example breaks Liskov substitution principle; If you have a function, that expects a Mother instance, and calls do() on it, it will fail when you pass a Daughter to it.
See this example:
def call_do(mother: Mother) -> None:
mother.do()
You should be able to pass an instance of Mother, or an instance of any of its subclasses into call_do.
But if you now do:
daughter = Daughter()
call_do(daughter)
you will get a TypeError.

Class inheriting itself? Question about inheritance and the super() method [duplicate]

This question already has answers here:
Understanding Python super() with __init__() methods [duplicate]
(7 answers)
Closed 2 years ago.
I have a question about classes, subclasses and inheritance in Python.
I've been using Tkinter for GUI development for some time and have decided to learn how to use Kivy. In the Kivy documentation I came across a line of code that didn't make any sense to me. It is as follows (note, GridLayout is a class I imported from the kivy module):
class LoginScreen(GridLayout):
def __init__(self, **kwargs):
super(LoginScreen, self).__init__(**kwargs)
The super call on LoginScreen and self instead of GridLayout really confuses me! Is the class inheriting itself? What is going on?
In Tkinter I would write something like (note again that, tk.Frame is a class imported from the Tkinter module):
class LoginScreen(tk.Frame)
def __init__(self, parent):
super().__init__(parent)
As I typed out these two examples I noticed that I am not passing anything into super(). Are the default parameters of the super method the name of the class and self? i.e. is the above akin to writing...
class LoginScreen(tk.Frame):
def __init__(self, parent):
super(LoginScreen, self).__init__(parent)
If they are different can you explain why they are different, but if they are the same can you explain a little more in-depth as to how super() does what it does (beyond simply it inherits the methods and attributes of the parent class)?
Yes, these are the default parameters to super as you can see in the example from the docs:
class C(B):
def method(self, arg):
super().method(arg) # This does the same thing as:
# super(C, self).method(arg)
(the comment is not mine, it appears like this in the original example)

What do super(MyObject, self).__init__() do in class MyObject __init__() function? [duplicate]

This question already has answers here:
Understanding Python super() with __init__() methods [duplicate]
(7 answers)
Closed 6 years ago.
class MyObject1(object):
def __init__(self):
super(MyObject1, self).__init__()
pass
class MyObject2(object):
def __init__(self, arg):
super(MyObject2, self).__init__()
pass
I have read a python27 code like this,
I know 'super' means father class constructor function,
but I cannot understand why these two classes call themselves' constructor function '__init__',
it seems don't have any practical effect.
These are some pretty basic OO methods in Python. Read here.
super and self are similar:
super() lets you avoid referring to the base class explicitly, which
can be nice. But the main advantage comes with multiple inheritance,
where all sorts of fun stuff can happen. See the standard docs on
super if you haven't already.
(from this answer)
Here's an example of super in action:
class Animal(object):
def __init__(self, speed, is_mammal):
self.speed = speed
self.is_mammal = is_mammal
class Cat(Animal):
def __init__(self, is_hungry):
super().__init__(10, True)
self.is_hungry = is_hungry
barry = Cat(True)
print(f"speed: {barry.speed}")
print(f"is a mammal: {barry.is_mammal}")
print(f"feed the cat?: {barry.is_hungry}")
You can see that super is calling the base class (the class that the current class inherits), followed by an access modifier, accessing the base class' .__init__() method. It's like self, but for the base class.

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 it is compulsory to give classname while using super() in Python [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why do I have to specify my own class when using super(), and is there a way to get around it?
I was reading this book - "Core Python Programming", and I really found it very nice I would say. But I got confused at a point while I was studying the topic Inheritance..
The book somewhere said that- we can use super() to invoke super class method which will find the base class method for us and also we don't need to pass self explicitly, like we do without super..
Here's the sample code: -
# Invoking super class method without super() .. Need to pass `self` as argument
class Child(Parent):
def foo(self):
Parent.foo(self)
# Invoking with super().
# No need to pass `self` as argument to foo()
class Child(Parent1, Parent2):
def foo(self):
super(Child, self).foo()
print 'Hi, I am Child-foo()'
My Question is - why we have to pass the classname to super() call.. As the classname can be inferred from the class from which super is invoked..
So, since super() is invoked from
class Child, classname should be implicit there.. So why do we need that??
*EDIT: - Giving Child as a parameter to super() doesn't make sense, because it doesn't give any information.. We could have used super(self).. And the method would have been searched in the super classes in the order they are given inside parenthesis..
By providing the class name as first argument you provide redundant information. Yes. That's a bit stupid* and that's why the behavior of super is changed in Python 3 to:
super().__init__()
*With my answer I actually contradict the answer by John Carter. Only one of us is right, of course. I don't want to offend him and others and I am happy to see a meaningful example where super(C, self).method(arg) is not actually used within class C :-).

Categories

Resources