Pergunta

Estou tentando chamar um método da superclasse usando um nome de método variável. Normalmente, eu via as duas linhas de código a seguir como equivalentes:

someObj.method()
someObj.__getattribute__( 'method' )()

E, de fato, acredito, também é isso que realmente acontece quando eu uso a primeira linha. No entanto, no exemplo a seguir, a segunda linha produz um problema estranho.

eu uso super Para construir um super objeto e chamar o método da super classe. Fazer isso funciona diretamente como esperado, mas usando __getattribute__ Para obter o método primeiro, resulta em um loop indefinido que chama o método da subclasse repetidamente.

Veja o seguinte código:

class A:
    def example ( self ):
        print( 'example in A' )

class B ( A ):
    def example ( self ):
        print( super( B, self ).example )
        print( super( B, self ).__getattribute__( 'example' ) )
        super( B, self ).example()
        #super( B, self ).__getattribute__( 'example' )()

        print( 'example in B' )

x = B()
x.example()

Se você executar esse código, tudo funciona como esperado e você deve obter uma saída semelhante a isso:

<bound method B.example of <__main__.B object at 0x01CF6C90>>
<bound method B.example of <__main__.B object at 0x01CF6C90>>
example in A
example in B

Então, ambos os métodos, aquele com o acesso direto e o via via __getattribute__, parece idêntico. Se você substituir a chamada do método pela linha comentada, acabará com um erro de tempo de execução de recursão.

Por que isso acontece e, mais importante, como posso realmente acessar o método da mesma maneira que o Python, quando uso a linha de trabalho?

editar

Quando pensei que já tentei de tudo, achei que isso estava funcionando:

super.__getattribute__( super( B, self ), 'example' )()

Na verdade é igual a super( B, self ).example.

Foi útil?

Solução

Não usar __getattribute__ Para isso: não faz o que você acha que faz. (É uma parte especializada da maquinaria do Python, principalmente para uso se você estiver implementando o novo atributo Access Magic.)

Para acesso normal ao atributo, use o getattr / setattr / delattr Buildins:

self.example           == getattr(self, 'example')
super(B, self).example == getattr(super(B, self), 'example')

(Se você quiser entender o que __getattribute__ Leia o Guia do descritor Howto e python Modelo de dados referência.)

Outras dicas

Obtendo o example atributo de a B objeto resulta em uma cópia encadernada de B.example. Chamar isso resultará em um erro de recursão. Que você liga A.__getattribute__() é irrelevante; você ainda tem um B objeto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top