Доступ к атрибутам класса от родителей в методах экземпляра - PullRequest
0 голосов
/ 27 сентября 2018

Я хотел бы прочитать атрибуты класса из каждого класса по всей цепочке наследования классов.

Что-то вроде следующего:

class Base(object):
    def smart_word_reader(self):
        for word in self.words:
            print(word)

class A(Base):
    words = ['foo', 'bar']

class B(A):
    words = ['baz']

if __name__ == '__main__':
    a = A()
    a.smart_word_reader()  # prints foo, bar as expected
    b = B()
    b.smart_word_reader()  # prints baz - how I can I make it print foo, bar, baz?

Очевидно, каждый атрибут wordsпереопределение других, как и должно быть.Как я могу сделать что-то подобное, что позволит мне прочитать атрибут words из каждого класса в цепочке наследования?

Есть ли лучший способ решить эту проблему?

Бонусные баллы зачто-то, что будет работать с несколькими цепочками наследования (в форме ромба со всем, что наследуется от Base в конце).

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Я бы сделал smart_word_reader a classmethod и перебрал бы reversed(cls.__mro__).

class Base:
    @classmethod
    def smart_word_reader(cls):
        the_words = (word for X in reversed(cls.__mro__)
                          for word in vars(X).get('words', []))
        print('\n'.join(the_words))

Демо:

>>> a = A()
>>> b = B()
>>> a.smart_word_reader()
foo
bar
>>> b.smart_word_reader()
foo
bar
baz

edit

незначительная ошибка: мы не хотим, чтобы getattr (рассмотрим class C(B): pass) искали отсутствующий атрибут в дочерних классах.Изменил getattr вызов на vars(X).get('words', []).

0 голосов
/ 27 сентября 2018

Полагаю, вы могли бы проанализировать mro вручную, что-то вроде:

In [8]: class Base(object):
   ...:     def smart_word_reader(self):
   ...:         for cls in type(self).mro():
   ...:             for word in getattr(cls, 'words', ()):
   ...:                 print(word)
   ...:
   ...: class A(Base):
   ...:     words = ['foo', 'bar']
   ...:
   ...: class B(A):
   ...:     words = ['baz']
   ...:

In [9]: a = A()

In [10]: a.smart_word_reader()
foo
bar

In [11]: b = B()

In [12]: b.smart_word_reader()
baz
foo
bar

Или, возможно, в reversed порядке:

In [13]: class Base(object):
    ...:     def smart_word_reader(self):
    ...:         for cls in reversed(type(self).mro()):
    ...:             for word in getattr(cls, 'words', ()):
    ...:                 print(word)
    ...:
    ...: class A(Base):
    ...:     words = ['foo', 'bar']
    ...:
    ...: class B(A):
    ...:     words = ['baz']
    ...:

In [14]: a = A()

In [15]: a.smart_word_reader()
foo
bar

In [16]: b = B()

In [17]: b.smart_word_reader()
foo
bar
baz

Или более сложныйрисунок:

In [21]: class Base(object):
    ...:     def smart_word_reader(self):
    ...:         for cls in reversed(type(self).mro()):
    ...:             for word in getattr(cls, 'words', ()):
    ...:                 print(word)
    ...:
    ...: class A(Base):
    ...:     words = ['foo', 'bar']
    ...:
    ...: class B(Base):
    ...:     words = ['baz']
    ...:
    ...: class C(A,B):
    ...:     words = ['fizz','pop']
    ...:

In [22]: c = C()

In [23]: c.smart_word_reader()
baz
foo
bar
fizz
pop

In [24]: C.mro()
Out[24]: [__main__.C, __main__.A, __main__.B, __main__.Base, object]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...