Les Crash-Devs d'un Passionné

Self controle

/Catégorie/python

Temps de lecture : 2 minutes

Quand vous utilisez python vous avez surement remarqué qu'il faut sans cesse mettre self en premier paramètre. Il correspond à l'instance en cours. Son nom n'est pas restrictif on pourrait bien avoir

clipboard
Copier le code
1
2
def method(instance):
      print instance.attribut

La philosophie en Python est de dire "l’explicite plutôt que l’implicite". On préfère répéter l'instance sur laquelle on travail pour rendre plus clair le code.

Un autre avantage est que Python permet l'héritage multiple et d'avoir self permet d'appeler une méthode de classe (self) ou de son parent (avec le nom de la classe parente)

clipboard
Copier le code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class Homme:
  age = 50
  def __init__(self):
    print "Homme"
  def anniversaire(self): 
    return self.age + 1   

class Femme: 
  age= 60
  def __init__(self):
    print "Femme"
  def anniversaire(self): 
    return self.age + 1   

class Personne(Homme, Femme):      
  def anniv(self): 
    age_hom = Homme.anniversaire(Homme()) 
    fem = Femme()
    age_fem = Femme.anniversaire(fem) 
    return (age_hom + age_fem) / 2

>>> inst = Personne()
Homme #Hérite de Homme en 1er
>>> inst
<__main__.Personne instance at 0xb68fd98c>
>>> inst.anniv
<bound method Personne.anniv of <__main__.Personne instance at 0xb68fd98c>>
>>> inst.anniv()
Homme
Femme
56
>>> Personne.anniv(Personne())
Homme
Homme
Femme
56
>>> Personne.anniv
<unbound method Personne.anniv>
>>> pers.anniversaire()
51 # Hérite de Homme en 1er donc 50+1

Pour hériter de toutes les classes parentes on change notre code avec super() et en héritant de object

clipboard
Copier le code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Homme(object):
  age = 50
  def __init__(self):
    print "Homme"
    super(Homme, self).__init__()
  def anniversaire(self): 
    return self.age + 1   

class Femme(object): 
  age= 60
  def __init__(self):
    print "Femme"
    super(Femme, self).__init__()
  def anniversaire(self): 
    return self.age + 1   

class Personne(Homme, Femme):    
  def __init__(self):
    print "Personne"
    super(Personne, self).__init__()

  def anniv(self): 
    age_hom = Homme.anniversaire(Homme()) 
    fem = Femme()
    age_fem = Femme.anniversaire(fem) 
    return (age_hom + age_fem) / 2

>>> p = Personne()
Personne
Homme
Femme

On remarque que dans la méthode anniv() de Personne on utilise 2 manières de créer une instance, mais ces 2 façons sont équivalentes. Car quand on fait :

instance = UneClasse()

instance.une_methode()

En réalité vous faites sans le savoir :

instance = UneClasse()

UneClasse.une_methode(instance)

Donc Python a besoin de connaitre l'instance en cours pour appeler la méthode. C'est la philosophie de Python.

On peut comparer à Java qui lui utilise "this." pour se référer à l'instance. Et nous allons voir la différence

instance.b

>> <bound method UneClasse.b of <__main__.UneCLasse instance at 0xb687a5ac>>

UneClasse.b

>> <unbound method UneClasse.b>

Bound voulant dire "lié" on remarque que instance.b est un raccourci (est lié) à UneClasse.b !

Pour ne pas passer l'instance il faut utiliser les méthodes statiques avec @staticmethod sur la méthode de la classe pour faire cela

clipboard
Copier le code
1
2
3
4
5
6
7
8
9
class Carre:
  @staticmethod
  def get(x): 
  return x*x
>>> c = Carre()
>>> c.get(2)
4
>>> Carre.get(2)
4