Как переопределить функцию, если родитель уже явно `setattr` для той же функции? - PullRequest
0 голосов
/ 17 июня 2020

Созданный мной «минимальный» пример:

class C:
    def wave(self):
        print("C waves")

class A:
    def __init__(self):
        c = C()
        setattr(self, 'wave', getattr(c, 'wave'))

class B(A):
    def wave(self):
        print("B waves")

>>> a = A()
>>> a.wave()
C waves # as expected
>>> b = B()
>>> b.wave()
C waves # why not 'B waves'?
>>> 

В этом примере класс A явно определил свой метод wave как метод wave класса C, хотя и не через более общее определение функции, но используя вместо него setattr. Затем у нас есть класс B, который наследует A, B пытается переопределить метод wave своим собственным методом, однако это невозможно, что происходит? как я могу это обойти?

Я хочу сохранить определение стиля setattr класса A, если это вообще возможно, посоветуйте, пожалуйста.

Я никогда не учил Python систематически, поэтому я думаю, что мне не хватает некоторое понимание того, как работают наследование Python и setattr.

1 Ответ

2 голосов
/ 17 июня 2020

Класс A устанавливает метод wave() как атрибут instance в __init__(). Это можно увидеть, проверив dict экземпляра:

>>> b.__dict__
{'wave': <bound method C.wave of <__main__.C object at 0x7ff0b32c63c8>>}

Вы можете обойти это, удалив член экземпляра из b

>>> del b.__dict__['wave']
>>> b.wave()
B waves

При удалении атрибута экземпляра wave() функция затем берется из класса dict:

>>> B.__dict__
mappingproxy({'__module__': '__main__',
              'wave': <function __main__.B.wave(self)>,
              '__doc__': None})

Здесь следует отметить, что, когда Python ищет атрибут, атрибуты экземпляра имеют приоритет над атрибутами класса (если только атрибут класса не данные дескриптор , но здесь это не так).

Я также написал сообщение в блоге , а затем объяснил, как работает поиск по атрибутам, более подробно .

...