web-dev-qa-db-fra.com

Comment initialiser la (super) classe de base?

En Python, considérez que j'ai le code suivant:

>>> class SuperClass(object):
    def __init__(self, x):
        self.x = x

>>> class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y
        # how do I initialize the SuperClass __init__ here?

Comment initialiser le SuperClass __init__ dans la sous-classe? Je suis le Python et il ne couvre pas cela. Lorsque j'ai effectué une recherche sur Google, j'ai trouvé plus d'une façon de le faire. Quelle est la manière habituelle de gérer cela?

111
Jeremy

Python (jusqu'à la version 3) supporte les classes "old-style" et new-style. Les classes de style nouveau sont dérivées de object et sont ce que vous utilisez. Elles invoquent leur classe de base par le biais de super(), par exemple.

class X(object):
  def __init__(self, x):
    pass

  def doit(self, bar):
    pass

class Y(X):
  def __init__(self):
    super(Y, self).__init__(123)

  def doit(self, foo):
    return super(Y, self).doit(foo)

Parce que python connaît les classes de style ancien et nouveau, il existe différentes façons d'invoquer une méthode de base, c'est pourquoi vous avez trouvé plusieurs façons de le faire.

Par souci d'exhaustivité, les classes de style ancien appellent des méthodes de base explicitement à l'aide de la classe de base, c'est-à-dire.

def doit(self, foo):
  return X.doit(self, foo)

Mais comme vous ne devriez plus utiliser d'ancien style, cela ne m'intéresserait pas trop.

Python 3 ne connaît que les classes de style nouveau (peu importe si vous dérivez de object ou pas).

133
Ivo van der Wijk

Tous les deux

SuperClass.__init__(self, x)

ou

super(SubClass,self).__init__( x )

fonctionnera (je préfère le deuxième, car il adhère davantage au principe DRY)).

Voir ici: http://docs.python.org/reference/datamodel.html#basic-customization

37
adamk

À partir de python 3.5.2, vous pouvez utiliser:

class C(B):
def method(self, arg):
    super().method(arg)    # This does the same thing as:
                           # super(C, self).method(arg)

https://docs.python.org/3/library/functions.html#super

16
Bob Jordan

Comment initialiser la (super) classe de base?

class SuperClass(object):
    def __init__(self, x):
        self.x = x

class SubClass(SuperClass):
    def __init__(self, y):
        self.y = y

Utilisez un objet super pour vous assurer d’obtenir la méthode suivante (en tant que méthode liée) dans l’ordre de résolution des méthodes. Dans Python 2, vous devez transmettre le nom de la classe et self à super pour rechercher la méthode __init__ Liée:

 class SubClass(SuperClass):
      def __init__(self, y):
          super(SubClass, self).__init__('x')
          self.y = y

Dans Python 3, il y a une petite magie qui rend les arguments de super inutiles - et qui présente l'avantage d'être un peu plus rapide:

 class SubClass(SuperClass):
      def __init__(self, y):
          super().__init__('x')
          self.y = y

Le codage en dur du parent comme ci-dessous vous empêche d'utiliser un héritage multiple coopératif:

 class SubClass(SuperClass):
      def __init__(self, y):
          SuperClass.__init__(self, 'x') # don't do this
          self.y = y

Notez que __init__ Peut uniquement renvoyer None - il est destiné à modifier l'objet sur place.

Quelque chose __new__

Il existe un autre moyen d'initialiser les instances - et c'est le seul moyen pour les sous-classes de types immuables en Python. C'est donc nécessaire si vous voulez sous-classer str ou Tuple ou un autre objet immuable.

Vous pourriez penser que c'est une méthode de classe parce qu'elle obtient un argument de classe implicite. Mais c’est en fait, une méthode statique . Vous devez donc appeler explicitement __new__ Avec cls.

Nous renvoyons habituellement l'instance de __new__, Si vous le faites, vous devez également appeler le __new__ De votre base via super également dans votre classe de base. Donc, si vous utilisez les deux méthodes:

class SuperClass(object):
    def __new__(cls, x):
        return super(SuperClass, cls).__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super(SubClass, cls).__new__(cls)

    def __init__(self, y):
        self.y = y
        super(SubClass, self).__init__('x')

Python 3 évite un peu l'étrangeté des super-appels causés par le fait que __new__ Est une méthode statique, mais vous devez toujours passer cls à la méthode non liée __new__:

class SuperClass(object):
    def __new__(cls, x):
        return super().__new__(cls)
    def __init__(self, x):
        self.x = x

class SubClass(object):
    def __new__(cls, y):
        return super().__new__(cls)
    def __init__(self, y):
        self.y = y
        super().__init__('x')
15
Aaron Hall