web-dev-qa-db-fra.com

Héritage et annulation __init__ dans python

Je lisais 'Dive Into Python' et dans le chapitre sur les classes, il donne cet exemple:

class FileInfo(UserDict):
    "store file metadata"
    def __init__(self, filename=None):
        UserDict.__init__(self)
        self["name"] = filename

L’auteur dit ensuite que si vous voulez remplacer le __init__ méthode, vous devez appeler explicitement le parent __init__ avec les paramètres corrects.

  1. Et si cette classe FileInfo avait plus d’une classe ancêtre?
    • Dois-je appeler explicitement toutes les classes __init__ méthodes?
  2. De plus, dois-je le faire pour toute autre méthode que je veux remplacer?
120
liewl

Le livre est un peu daté en ce qui concerne les appels de sous-classes. C'est aussi un peu daté en ce qui concerne les classes intégrées de sous-classe.

Cela ressemble à ceci de nos jours.

class FileInfo(dict):
    """store file metadata"""
    def __init__(self, filename=None):
        super( FileInfo, self ).__init__()
        self["name"] = filename

Notez ce qui suit.

  1. Nous pouvons directement sous-classer des classes intégrées, comme dict, list, Tuple, etc.

  2. La fonction super gère la recherche des super-classes de cette classe et les fonctions d’appel correspondantes.

147
S.Lott

Dans chaque classe dont vous devez hériter, vous pouvez exécuter une boucle de chaque classe à initier lors de l'initiation de la classe enfant ... un exemple pouvant être copié pourrait être mieux compris ...

class Female_Grandparent:
    def __init__(self):
        self.grandma_name = 'Grandma'

class Male_Grandparent:
    def __init__(self):
        self.grandpa_name = 'Grandpa'

class Parent(Female_Grandparent, Male_Grandparent):
    def __init__(self):
        Female_Grandparent.__init__(self)
        Male_Grandparent.__init__(self)

        self.parent_name = 'Parent Class'

class Child(Parent):
    def __init__(self):
        Parent.__init__(self)
#---------------------------------------------------------------------------------------#
        for cls in Parent.__bases__: # This block grabs the classes of the child
             cls.__init__(self)      # class (which is named 'Parent' in this case), 
                                     # and iterates through them, initiating each one.
                                     # The result is that each parent, of each child,
                                     # is automatically handled upon initiation of the 
                                     # dependent class. WOOT WOOT! :D
#---------------------------------------------------------------------------------------#



g = Female_Grandparent()
print g.grandma_name

p = Parent()
print p.grandma_name

child = Child()

print child.grandma_name
16
Code Bug

Vous n'avez pas vraiment à d'appeler le __init__ méthodes de la (des) classe (s) de base, mais vous le souhaitez généralement , car les classes de base y effectueront des initialisations importantes nécessaires au reste des méthodes travail.

Pour d'autres méthodes, cela dépend de vos intentions. Si vous voulez juste ajouter quelque chose au comportement des classes de base, vous voudrez appeler la méthode des classes de base en plus de votre propre code. Si vous souhaitez modifier fondamentalement le comportement, vous pouvez ne pas appeler la méthode de la classe de base et implémenter toutes les fonctionnalités directement dans la classe dérivée.

14
sth

Si la classe FileInfo a plus d'une classe ancêtre, vous devez absolument appeler toutes leurs fonctions __init __ (). Vous devriez également faire la même chose pour la fonction __del __ (), qui est un destructeur.

4
marcog

Oui, vous devez appeler __init__ pour chaque classe parente. Il en va de même pour les fonctions, si vous substituez une fonction qui existe dans les deux parents.

2
vezult