Como inicializar a (super) classe base?


125

No Python, considere que tenho o seguinte código:

>>> 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?

Como inicializo o SuperClass __init__na subclasse? Estou seguindo o tutorial do Python e ele não cobre isso. Quando pesquisei no Google, encontrei mais de uma maneira de fazer. Qual é a maneira padrão de lidar com isso?

Respostas:


146

O Python (até a versão 3) suporta as classes "estilo antigo" e novo. As classes de novo estilo são derivadas objecte são o que você está usando e invocam a classe base por meio super(), por exemplo,

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)

Como o python conhece as classes de estilo antigo e novo, existem diferentes maneiras de chamar um método base, e é por isso que você encontrou várias maneiras de fazer isso.

Para completar, as classes de estilo antigo chamam métodos de base explicitamente usando a classe de base, ou seja,

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

Mas como você não deveria mais usar o estilo antigo, eu não me importaria muito com isso.

O Python 3 conhece apenas classes de novo estilo (não importa se você é derivado objectou não).


37

Ambos

SuperClass.__init__(self, x)

ou

super(SubClass,self).__init__( x )

funcionará (eu prefiro o segundo, pois adere mais ao princípio DRY).

Veja aqui: http://docs.python.org/reference/datamodel.html#basic-customization


8
errado. super funciona apenas com classes de novo estilo e é a única maneira adequada de chamar uma base ao usar classes de novo estilo. Além disso, você também precisa passar 'self' explicitamente usando a construção de estilo antigo.
Ivo van der Wijk

1
@Ivo - o OP deu uma classe de novo estilo no exemplo, e há pouco sentido em falar sobre a diferença entre o novo e o antigo, já que ninguém mais deve usar o antigo. O link que eu dei (para os documentos do Python) sugere que há mais de uma maneira "adequada" de chamar a superclasse __init__.
12138 adamk


21

Como inicializar a (super) classe base?

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

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

Use um superobjeto para garantir que você obtenha o próximo método (como método vinculado) na ordem de resolução do método. No Python 2, você precisa passar o nome da classe e selfsuper para pesquisar o __init__método bound :

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

No Python 3, há um pouco de mágica que torna os argumentos superdesnecessários - e, como benefício colateral, funciona um pouco mais rápido:

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

A codificação codificada do pai como esta abaixo impede que você use herança múltipla cooperativa:

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

Observe que __init__só pode retornarNone - ele pretende modificar o objeto no local.

Alguma coisa __new__

Há outra maneira de inicializar instâncias - e é a única maneira de subclasses de tipos imutáveis ​​no Python. Por isso é necessário se você quiser subclasse strou tupleou outro objeto imutável.

Você pode pensar que é um método de classe porque obtém um argumento implícito de classe. Mas na verdade é um método estático . Então, você precisa chamar __new__com clsexplicitamente.

Normalmente retornamos a instância de __new__, portanto, se você o fizer, também precisará chamar a __new__via superda sua base também na sua classe base. Portanto, se você usar os dois métodos:

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')

O Python 3 evita um pouco da estranheza das super chamadas causadas por __new__ser um método estático, mas você ainda precisa passar clspara o __new__método não vinculado :

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')
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.