Herança do Python: TypeError: object .__ init __ () não leva parâmetros

92

Eu recebo este erro:

TypeError: object.__init__() takes no parameters 

ao executar meu código, eu realmente não vejo o que estou fazendo de errado aqui:

class IRCReplyModule(object):

    activated=True
    moduleHandlerResultList=None
    moduleHandlerCommandlist=None
    modulename=""

    def __init__(self,modulename):
        self.modulename = modulename


class SimpleHelloWorld(IRCReplyModule):

     def __init__(self):
            super(IRCReplyModule,self).__init__('hello world')
Lucas Kauffman
fonte

Respostas:

118

Você está chamando o nome de classe errado em sua super () chamada:

class SimpleHelloWorld(IRCReplyModule):

     def __init__(self):
            #super(IRCReplyModule,self).__init__('hello world')
            super(SimpleHelloWorld,self).__init__('hello world')

Essencialmente, o que você está resolvendo é o __init__da classe base do objeto que não leva parâmetros.

É um pouco redundante, eu sei, ter que especificar a classe da qual você já está dentro, e é por isso que em python3 você pode apenas fazer: super().__init__()

jdi
fonte
4
@LucasKauffman: Na verdade, não acho isso muito bobo da sua parte. Pode ser facilmente um conceito confuso. Eu não te culpo.
jdi
4
Correndo o risco de ofender muitos Pythonians: Isso - imho - é um design de linguagem terrível. Obrigado pela ajuda @jdi!
Johannes Fahrenkrug
4
@JohannesFahrenkrug - Não acho que você ofenderia ninguém, porque isso foi identificado como um design ruim e corrigido em python3: docs.python.org/3/library/functions.html#super
jdi
3

Isso me incomodou duas vezes recentemente (sei que deveria ter aprendido com meu erro da primeira vez) e a resposta aceita não me ajudou em nenhuma das vezes, então, enquanto ainda está fresca em minha mente, pensei em enviar minha própria resposta para o caso Alguém mais está correndo para isso (ou eu preciso disso novamente no futuro).

No meu caso, o problema era que eu estava passando um kwarg para a inicialização da subclasse, mas na superclasse essa palavra-chave arg estava sendo passada para a chamada super ().

Sempre acho que esses tipos de coisas são melhores com um exemplo:

class Foo(object):
  def __init__(self, required_param_1, *args, **kwargs):
    super(Foo, self).__init__(*args, **kwargs)
    self.required_param = required_param_1
    self.some_named_optional_param = kwargs.pop('named_optional_param', None)

  def some_other_method(self):
    raise NotImplementedException

class Bar(Foo):
  def some_other_method(self):
    print('Do some magic')


Bar(42) # no error
Bar(42, named_optional_param={'xyz': 123}) # raises TypeError: object.__init__() takes no parameters

Então, para resolver isso, eu só preciso alterar a ordem em que faço as coisas no método Foo .__ init__; por exemplo:

class Foo(object):
  def __init__(self, required_param_1, *args, **kwargs):
    self.some_named_optional_param = kwargs.pop('named_optional_param', None)
    # call super only AFTER poping the kwargs
    super(Foo, self).__init__(*args, **kwargs)
    self.required_param = required_param_1
John
fonte