Вызов метода переменной суперкласса - PullRequest
1 голос
/ 03 октября 2010

Я пытаюсь вызвать метод суперкласса, используя имя метода переменной. Обычно я вижу следующие две строки кода как эквивалентные:

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

И на самом деле я верю, что это именно то, что происходит, когда я использую первую строку. Однако в следующем примере вторая строка вызывает странную проблему.

Я использую super для создания суперобъекта и вызова метода суперкласса. Выполнение этого напрямую работает, как и ожидалось, но использование __getattribute__ для первого получения метода приводит к неопределенному циклу, который снова и снова вызывает метод подкласса.

См. Следующий код:

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

Если вы запускаете этот код, все работает, как ожидалось, и вы должны получить вывод, подобный следующему:

<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

Таким образом, оба метода, один с прямым доступом и один через __getattribute__, выглядят одинаково. Однако если вы замените вызов метода закомментированной строкой, вы получите ошибку времени выполнения рекурсии.

Почему это происходит, и, что более важно, как я могу получить доступ к методу таким же образом, как это делает Python внутри, когда я использую рабочую строку?

редактировать

Когда я подумал, что уже все перепробовал, я обнаружил, что это работает:

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

Это на самом деле равно super( B, self ).example.

Ответы [ 2 ]

5 голосов
/ 03 октября 2010

Не используйте __getattribute__ для этого: он не делает то, что вы думаете, он делает.(Это специализированная часть механизма Python, в основном для использования, если вы реализуете новую магию доступа к атрибутам.)

Для нормального доступа к атрибутам используйте встроенные функции getattr / setattr / delattr:

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

(Если вы хотите понять, что делает __getattribute__, прочитайте руководство по Descriptor и Python Модель данных справочник.)

0 голосов
/ 03 октября 2010

Получение атрибута example объекта B приводит к созданию связанной копии B.example.Вызов этого приведет к ошибке рекурсии.То, что вы называете A.__getattribute__(), не имеет значения;у вас все еще есть B объект.

...