why super always need to be called in the __init__ - python

See the screenshot of the code below. In the code block, it can be seen from the class definition part that the ResNet is a subclass of nn.Module, and when we define the __init__ function, we still call the super().__init__(). I am really confused about that, I have already look a stack overflow explanation but the accept answer is too brief so I don't get it (for example, if super().__init__() always need to be called why python don't just integrate it inside the __init__()), I was hoping a more easy to understand explanation with some examples.

The Python super() method lets you access methods from a parent class from within a child class. In other words this will work only if you are working in a child class inherited from another. This helps reduce repetition in your code. super() does not accept any arguments.
class Parent():
def __init__(self, name):
self.hair = 'blonde'
self.full_name = name + ' kurt'
class Child(Parent):
def __init__(self, brand):
super().__init__('franz')
print(self.fullname) # franz kurt
# inherited blonde but the phenotype of the hair in child is different
# so the attribute was overwrited
self.hair = 'dark hair'
One core feature of object-oriented programming languages like Python is inheritance. Inheritance is when a new class uses code from another class to create the new class.
When you’re inheriting classes, you may want to gain access to methods from a parent class. That’s where the super() function comes in.
Reference: https://realpython.com/python-super/

Related

Trying to understand the fundamental difference on something simple here with python inheritance vs i don't even know what to call this

I am trying to understand multiple inheritance vs this other thing i am doing.
I don't even know what to call it. First let me explain this other thing. What is this even called? It seems to work really well without giving me a headache unlike inheritance.
class my_pets():
def __init__():
pass
self.mycat = cats()
class cats():
def __init__():
self.cats_name = bruno
So i dont know what that is called but it works well. I have been calling it a sub_objected incorrectly in my head. I know that is not inheritance.
I am utterly mystified with inheritance. Mainly the when to use it verse when to do what i did above. If i wrote the above with inheritance i would of done.
class my_pets(cats):
def __init__():
super(cats,self).__init__(cats_name)
class cats():
def __init__(cats_name):
self.cats_name = cats_name
So i don't understand the difference and when to do one or the other.
Can someone even tell me what this is called?
I appreciate the suggested thread and i had seen that previously. So that post is specific to UML drawings. Is composition what it is called then? That seems very specific to UML
Also, the answer still baffles me
If you google any search on inheritance all the examples lead to something that can be easily done with this other approach. The typical examples.
Mom, dad , child
pet, cat , dog etc
Its called super function which is used to give access to the methods of a parent class .Returns a temporary object of a parent class when used .its is mostly used where we overriding (a class drive from another class) like in your code catsis a parent class of a my catstake a look in my example:
class pa_rent:
classvar1 = "I am a class variable in class A"
def __init__(self):
self.var1 = "I am inside class A's constructor"
self.classvar1 = "Instance var in class A"
self.special = "Special"
class Child(pa_rent):
classvar1 = "I am in class B"
def __init__(self):
self.var1 = "I am inside class B's constructor"
self.classvar1 = "Instance var in class B"
super().__init__()
print(super().classvar1)
a = A()
b = B()
print(b.special, b.var1, b.classvar1)
so when we call classvar1, interpreter first checks in instance child'schild`` variable if its not found then its checks in parent classpa_rent`` instance variable .but in this case we have override and when we call callssvar1 its gives Instance var in class B so, in taht case if we want parent class variable classvar1 super function super().__init__ will be used,
I hope its enough for your understanding

Inheriting form two classes in python with super. can you call parent init methods with super()? [duplicate]

This question already has answers here:
How does Python's super() work with multiple inheritance?
(18 answers)
Python - Calling __init__ for multiple parent classes
(2 answers)
Python Multiple Inheritance: call super on all
(4 answers)
Closed 1 year ago.
Assuming this:
class Father():
def __init__(self,fathername):
self.papa = f"The father is {fathername.upper()}"
class Mother():
# Mother class is COMPLETELY DIFFERENT AS Father.
# The important thing is that they both built an attribute each.
def __init__(self,mothername):
self.mama = f"the mother is {mothername.lower()}"
class Child3(Father,Mother):
def __init__(self,name,fathername,mothername):
Father.__init__(self,fathername)
Mother.__init__(self,mothername)
self.name=name
both of the following works:
c = Child3('Noa',fathername='J',mothername='M')
c = Child3('Noa','J','M')
So far so good.
But assuming I want to inherit from several classes (not multiple nesting inheritances but just one class inheriting from several ones that don't inherit from anything else)
How can I use super() to initialise the parent classes?
The following does not work:
class Child4(Father,Mother):
def __init__(self,name,fathername,mothername):
super().__init__(self,fathername=fathername,mothername=mothername)
self.name=name
TypeError: init() got multiple values for argument 'fathername'
Some previous consultations:
How does Python's super() work with multiple inheritance?
This is a very complete with very nice answers which I already voted up some time ago. Nevertheless this question is a bit different and not entirely the case I am asking here, i.e. MRO (Method resolution order) is of no importance here. I would like to achieve a way to hard code initialise the parent classes to access all of the attributes. In the mentioned question the answer with the most votes does not have attributes in the parent classes. In the second most voted answer the parent classes DO NOT HAVE ATTRIBUTES neither. Yet in another of the answers there is a very complete explanation of MRO with multi inheritance, which again, is not the point here since there is one one level of inheritance.
In this other question with a lot of positive up votes there is no attributes of the parents classes neither: Calling parent class __init__ with multiple inheritance, what's the right way?
This is the one coming closer, but not implementing a solution with super() Python - Calling __init__ for multiple parent classes
actually suggesting going away from inheritance paradigm
This is a close one: calling init for multiple parent classes with super? but I see there there is super() in the parent classes which is counter productive since the aim is not having to modify the parent classes.
In order to understand the use of this example and why I HAVE TO USE inheritance think that the first parent class calls an API and performs a couple of 1000s code NLP process to extract data of the API response. The same goes for the second parent class. Then the child class will try to get insights comparing both further using NLP.
The classes Mother and Father are given. They are not coded by me. I don't have a chance to modify them. They don't depend on any other class.
A child has a mother and a father and would best be designed to have mother and father attributes contained within. I think the following class definitions make more sense for your case:
class Person():
def __init__(self, name):
self._name = name
def get_name(self):
return self._name
class Child(Person):
def __init__(self, name, father_name, mother_name):
super().__init__(name)
self._father = Person(father_name)
self._mother = Person(mother_name)
def get_father_name(self):
return self._father.get_name()
def get_mother_name(self):
return self._mother.get_name()
child = Child('Peter', 'Joseph', 'Mary')
print(child.get_name(), child.get_father_name(), child.get_mother_name())
Prints:
Peter Joseph Mary

what is the difference between super and inheritance by passing it alone as an object?

in the below example I want to know when I should use one of them for inherits? I think both are valid so, why sometimes I have to use super if the other way is workable to work with?
class User:
def __init__(self):
self._user = "User A"
pass
class UserA(User):
_user = "User B"
def __init__(self):
super().__init__()
class UserB(User):
pass
You are correct, both are valid. The difference is:
UserA: you are overwriting the __init__ method of the ancestor. This is practical if you want to add something during the initialization process. However, you still want to initialize the ancestor, and this can be done via super().__init__(), despite having overwritten the __init__ method.
UserB: you are fully using the __init__ of the ancestor you are inheriting from (by not overwriting the __init__ method). This can be used if nothing extra needs to be done during initialization.
The super() builtin returns a proxy object (temporary object of the superclass) that allows us to access methods of the base class. For example:
class Mammal(object):
def __init__(self, mammalName):
print(mammalName, 'is a warm-blooded animal.')
class Dog(Mammal):
def __init__(self):
print('Dog has four legs.')
super().__init__('Dog')
self represents the instance of the class. By using the “self” keyword we can access the attributes and methods of the class in python

How to access class variable of super class without explicit super class name

As the title stated, I want to get how to accessing class variable of super class without explicit super class name. Or whether that is possible.
I am NOT talking about accessing instance variable, but class variable.
For example, if i want to override a class variable in the following example, I have to explicitly use Parent.class_variable.
class Parent():
class_variable = 'this_is_class_variable'
class Child(Parent):
class_variable = Parent.class_variable + ' in child class'
Thank you in advance.
You can't easily do what you want to do, because Child isn't a class until after you're done defining it. Since it's not a class yet, it doesn't have any parents.
Potentially you could do it with some kind of metaprogramming; could be fun to hack on. The approach I'd take is to write a proxy object that represents an attribute of the parent class. It needs to accumulate the operations that are to be performed on it (such as concatenation using + as in your example) rather than performing them immediately. A metaclass or decorator then goes through the finalized class looking for attributes that are instances of this class and forces their evaluation in the context of the parent class (which can be determined from the class's __mro__ attribute).
This is lot of work, so I'll leave an actual implementation as an exercise for the reader. ;-)

Python multiple inheritance, calling second base class method, if both base classes holding same method

class A:
def amethod(self): print("Base1")
class B():
def amethod(self): print("Base3")
class Derived(A,B):
pass
instance = Derived()
instance.amethod()
#Now i want to call B method amethod().. please let me know the way.**
Python multiple inheritance, calling second base class method, if both base classes holding same method
try to use composition
+Avoid multiple inheritance at all costs, as it's too complex to be reliable. If you're stuck with it, then be prepared to know the class hierarchy and spend time finding where everything is coming from.
+Use composition to package code into modules that are used in many different unrelated places and situations.
+Use inheritance only when there are clearly related reusable pieces of code that fit under a single common concept or if you have to because of something you're using.
class A:
def amethod(self): print("Base1")
class B:
def amethod(self): print("Base3")
class Derived2:
def __init__(self):
self.a = A()
self.b = B()
def amthodBase1(self):
self.a.amethod()
def amthodBase3(self):
self.b.amethod()
instance2 = Derived2()
instance2.amthodBase1()
instance2.amthodBase3()
galaxyan's answer suggesting composition is probably the best one. Multiple inheritance is often complicated to design and debug, and unless you know what you're doing, it can be difficult to get right. But if you really do want it, here's an answer explaining how you can make it work:
For multiple inheritance to work properly, the base classes will often need to cooperate with their children. Python's super function makes this not too difficult to set up. You often will need a common base for the classes involved in the inheritance (to stop the inheritance chain):
class CommonBase:
def amethod(self):
print("CommonBase")
# don't call `super` here, we're the end of the inheritance chain
class Base1(CommonBase):
def amethod(self):
print("Base1")
super().amethod()
class Base2(CommonBase):
def amethod(self):
print("Base2")
super().amethod()
class Derived(Base1, Base2):
def amethod(self):
print("Derived")
super().amethod()
Now calling Derived().amethod() will print Derived, Base1, Base2, and finally CommonBase. The trick is that super passes each call on to the the next class in the MRO of self, even if that's not the in the current class's inheritance hierarchy. So Base1.amethod ends up calling Base2.amethod via super since they're being run on an instance of Derived.
If you don't need any behavior in the common base class, its method body just be pass. And of course, the Derived class can just inherit the method without writing its own version and calling super to get the rest.

Categories

Resources