No Python 3.x, super()
pode ser chamado sem argumentos:
class A(object):
def x(self):
print("Hey now")
class B(A):
def x(self):
super().x()
>>> B().x()
Hey now
A fim de fazer este trabalho, um pouco de magia em tempo de compilação é executada, uma conseqüência do que é que o código a seguir (que religa super
a super_
) falha:
super_ = super
class A(object):
def x(self):
print("No flipping")
class B(A):
def x(self):
super_().x()
>>> B().x()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in x
RuntimeError: super(): __class__ cell not found
Por que super()
não é possível resolver a superclasse no tempo de execução sem a assistência do compilador? Existem situações práticas em que esse comportamento, ou a razão subjacente, poderia morder um programador incauto?
... e, como uma pergunta paralela: existem outros exemplos no Python de funções, métodos etc. que podem ser quebrados ao reconectá-los a um nome diferente?
python
python-3.x
super
Zero Pireu
fonte
fonte
Respostas:
O novo
super()
comportamento mágico foi adicionado para evitar violar o princípio DRY (Não se repita), veja PEP 3135 . Ter que nomear explicitamente a classe referenciando-a como global também é propenso aos mesmos problemas de religação que você descobriu consigosuper()
:O mesmo se aplica ao uso de decoradores de classe em que o decorador retorna um novo objeto, que religa o nome da classe:
A
super()
__class__
célula mágica evita esses problemas perfeitamente, fornecendo acesso ao objeto de classe original.O PEP foi iniciado por Guido, que inicialmente imaginou
super
se tornar uma palavra-chave , e a idéia de usar uma célula para pesquisar a classe atual também era dele . Certamente, a ideia de transformá-la em palavra-chave fazia parte do primeiro rascunho do PEP .No entanto, foi de fato o próprio Guido quem se afastou da ideia de palavra-chave como 'muito mágica' , propondo a implementação atual. Ele antecipou que usar um nome diferente para
super()
poderia ser um problema :Então, no final, foi o próprio Guido que proclamou que o uso de uma
super
palavra - chave não parecia certo e que fornecer uma__class__
célula mágica era um compromisso aceitável.Concordo que o comportamento implícito e mágico da implementação é um tanto surpreendente, mas
super()
é uma das funções mais mal aplicadas na linguagem. Basta dar uma olhada em todas as invençõessuper(type(self), self)
ou aplicações incorretassuper(self.__class__, self)
encontradas na Internet; se algum desses códigos fosse chamado de uma classe derivada, você acabaria com uma exceção de recursão infinita . No mínimo, asuper()
chamada simplificada , sem argumentos, evita esse problema.Quanto ao renomeado
super_
; referência apenas__class__
em seu método bem e ele vai trabalhar novamente. A célula é criada se você fizer referência aos nomessuper
ou__class__
no seu método:fonte
def super(of_class=magic __class__)
espécie deself.super(); def super(self): return self.__class__
?super()
funciona sem argumentos; trata principalmente do porquê existe.super()
, em um método de classe, é equivalente asuper(ReferenceToClassMethodIsBeingDefinedIn, self)
, ondeReferenceToClassMethodIsBeingDefinedIn
é determinado em tempo de compilação, anexado ao método como um fechamento nomeado__class__
esuper()
procurará ambos no quadro de chamada em tempo de execução. Mas você realmente não precisa saber tudo isso.super()
não chega nem perto de ser uma função instanciada automaticamente , não.__class__
no seu método . Você usou o nomesuper
em sua função. O compilador vê isso e adiciona o__class__
fechamento.type(self)
fornece o tipo atual , que não é igual ao tipo em que o método está definido. Portanto, uma classeFoo
com métodobaz
precisasuper(Foo, self).baz()
, porque pode ser subclassificada comoclass Ham(Foo):
, nesse momentotype(self)
éHam
esuper(type(self), self).baz()
daria a você um loop infinito. Veja o post ao qual vinculo minha resposta: Ao chamar super () em uma classe derivada, posso passar em self .__ class__?