be the following code of a simple app in kivy:
from kivy.config import Config
Config.set('kivy', 'keyboard_mode', 'system')
from kivy.app import App
from kivy.uix.boxlayout import BoxLayout
from kivy.lang import Builder
from kivy.properties import StringProperty
Builder.load_file('design2.kv')
class MyWidget(BoxLayout):
def __init__(self):
super(MyWidget, self).__init__()
self.showtext() #Llamamos al método desde el constructor
def showtext(self):
with open("Prueba.txt","r") as f:
self.ids['Label1'].text = f.read()
class myApp(App):
def build(self):
return MyWidget()
def on_pause(self):
return True
def on_resume(self):
pass
if __name__ in ('__main__', '__android__'):
myApp().run()
Let the .kv file be (not relevant here, though):
<MyWidget>:
BoxLayout:
Label:
id: Label1
I am wondering about the following code snippet from the first code:
class MyWidget(BoxLayout):
def __init__(self):
super(MyWidget, self).__init__()
self.showtext() #Llamamos al método desde el constructor
As I understand it, def __init__(self):
it is a constructor. What is a constructor for? The other question is about the line: super(MyWidget, self).__init__()
What is super
?
The question is not really specific to Kivy but to Python and the OOP (Object Oriented Programming) paradigm in general.
The short answer would be that although the method
__init__
is sometimes called a "constructor" it is really just an instance initializer, it is generally used to initialize the attributes of the object we create and is executed automatically as soon as the class is instantiated. In your case, since we call the method inside it,showtext
the text is already loaded in the label when our app starts.super
is used in this case to call the parent class's initializerBoxLayout
. In this case it is equivalent toBoxLayout.__init__(self, *args, **kwargs)
.The long answer goes below, all of it is geared towards Python 3, though it's all applicable to Python 2 new-style
object
classes (explicitly derived from ):Strictly speaking, the term 'constructor' in Python can be somewhat ambiguous. When we create an object, two special methods are involved, the first thing that is called is the method
__new__
and later the method is called__init__
:__new__
: basically what it does is return a valid instance of the class. It only constructs an object of its class and returns it, so this should be considered the true "constructor" of the class. Receives a reference to the class as the first argument (cls
).Overriding this method is not as common as in the case of
__init__
, generally, its use is to customize the instantiation of the class, for example it is one of the ways to create a singleton:If we override the method we must get the new instance by calling the
__new__
parent method (which comes from the classobject
from which all new-style classes derive ), for example:__init__
: if it__new__
returns an instance of its class (normally) then the method__init__
to which it passes the newly created instance as the first argument (self
by convention) is implicitly executed. If__new__
it does not return an instance of the class, it is not called and must be done explicitly. Some of its features are:In many languages both methods are merged into one and it is considered as a constructor. You can find dialectical fights about it out there, there is an important tendency to call the constructor
__init__
even though it is not strictly correct.The fundamental goal of
__init__
is to initialize the attributes of the object we create:The
__init__
in this case creates and initializes the instance attributeradio
, property of every objectCírculo
and that differentiates it from other circles.We can create an attribute outside of
__init__
or any method as you may have noticed, this is the casepi
in the example above. There is a substantial difference in both cases, the attributepi
is an attribute that belongs to the class and is shared by all the instances of the class that we make.radio
instead it is created by__init__
for the instance, it belongs exclusively to the object, initializing it by giving it differentiating properties. For more information the following question may be helpful:Difference Between Instance Attributes and Class Attributes
Now to finish this, talk about
super
what is commonly used in the class initializer, as in the example you show. This is because defining our own initializer overrides that__init__
of the parent class. For our class to inherit all the features of its parent implemented in its initializer (which we have overridden) it is therefore necessary to call it explicitly. This is precisely what it takes care ofsuper(MyWidget, self).__init__()
.In general, it allows explicit reference to the parent class , so it allows you to delegate the call of a method to the parent class (or classes).
Departure:
In cases of multiple inheritance this is where it
super
has its true potential as it is going to look for the method among the parent classes in a certain order ( Method Resolution Order ), but this is already a long way from the question.