Как объединить объекты, хранящиеся в цепочке наследования в Python?

Я реализую пользовательский интерфейс. Многие объекты предоставляют различные свойства пользовательскому интерфейсу. Каждый из них имеет объект "ExposedProperties", который содержит, помимо прочего, список доступных свойств (и их типы, как они должны отображаться, способ проверки входных данных и т. Д.). Этот объект ExposedProperties рассчитывается один раз для каждого класса.

Я хотел бы получить объединение всех открытых свойств объекта. Один из способов сделать это - передать каждому объекту свои "ExposedProperties" по цепочке наследования в __init__ и для каждого суперкласса соединить это со своими собственными ExposedProperties. Базовый класс будет устанавливать сцепленные ExposedProperties для объекта.

Другой способ - дождаться, пока у объекта будут запрошены все открытые свойства. Затем метод базового класса, который сканирует каждый класс в mro за exposed_properties атрибуты объединяют их в то время.

Какой самый Pythonic способ объединить эти объекты, хранящиеся в цепочке наследования в Python?

1 ответ

Решение

Поскольку предоставляемые свойства являются атрибутами класса, имеет смысл создать требуемый список (открытых свойств класса вместе со свойствами его предков) во время создания класса, для которого вы можете использовать метакласс. (Изменить: я вижу, что то же предложение было сделано в комментариях.)

Вот пример этого:

class ExposedMeta(type):

    def __init__(cls, name, bases, attrs):
        if not "exposed_properties" in attrs:
            cls.exposed_properties = []
        all_props = set(cls.exposed_properties)
        for base in bases:
            all_props.update(getattr(base, "all_exposed_properties", []))
        cls.all_exposed_properties = list(all_props)
        super(ExposedMeta, cls).__init__(name, bases, attrs)

class A(object):
    __metaclass__ = ExposedMeta
    exposed_properties = ['A1', 'A2']

class B(A):
    exposed_properties = ['B']

class C(A):
    pass

class D(object):
    __metaclass__ = ExposedMeta
    exposed_properties = ['D']

class E(B, D):
    exposed_properties = ['E1', 'E2']

for cls in [A, B, C, D, E]:
    print "Class %s, exposed: %s, all exposed: %s" % (cls.__name__, cls.exposed_properties, cls.all_exposed_properties)
Другие вопросы по тегам