Переменная класса V3 зависит от V1 и V2. Как определить V3 в детских классах
Parent
Класс наследуется несколькими другими классами.
class Parent(object):
V_1 = set()
V_2 = set()
ALL_V_ELEMENTS = V_1 | V_2
class Child1(Parent):
V_1 = {1, }
V_2 = {4, 7, 10}
class Child2(Parent):
V_1 = {'a', 'b'}
V_2 = {'a', 'c'}
V_1
а также V_2
различны у каждого ребенка (также они не меняются после создания класса).
Используя код ниже, я получаю то же значение для ALL_V_ELEMENTS
:
print(Parent.ALL_V_ELEMENTS) # prints: set()
print(Child1.ALL_V_ELEMENTS) # prints: set()
print(Child2.ALL_V_ELEMENTS) # prints: set()
Что-то, чего я не хочу. Что мне нужно, это:
print(Parent.ALL_V_ELEMENTS) # prints: set()
print(Child1.ALL_V_ELEMENTS) # prints: {1, 10, 4, 7}
print(Child2.ALL_V_ELEMENTS) # prints: {'a', 'c', 'b'}
Для достижения моей цели я могу определить классы следующим образом:
class Child1(Parent):
V_1 = {1, }
V_2 = {4, 7, 10}
ALL_V_ELEMENTS = V_1 | V_2
class Child2(Parent):
V_1 = {'a', 'b'}
V_2 = {'a', 'c'}
ALL_V_ELEMENTS = V_1 | V_2
Однако копирование-вставка ALL_V_ELEMENTS = V_1 | V_2
на каждого ребенка Parent
не кажется хорошей идеей
Другой альтернативой будет определение Parent
по-другому:
class Parent(object):
V_1 = set()
V_2 = set()
def __init__(self):
self.ALL_V_ELEMENTS = self.V_1 | self.V_2
Это сделало бы |
операция на каждом экземпляре, который является избыточным.
Есть ли лучший способ достичь моей цели?
1 ответ
Вы можете определить это как свойство:
class Parent(object):
V_1 = set()
V_2 = set()
@property
def ALL_V_ELEMENTS(self):
return V_1 | V_2
Это, однако, будет пересчитывать набор каждый раз. Имея __init__
создать набор означает, что он будет создан для каждого экземпляра.
Вы можете вычислить набор в метаклассе, поэтому он создается только тогда, когда создается объект класса:
class AllVMeta(type):
def __new__(typ, name, bases, attrs):
cls = super(AllVMeta, typ).__new__(typ, name, bases, attrs)
cls.ALL_V_ELEMENTS = cls.V_1 | cls.V_2
return cls
Этот метакласс добавляет ALL_V_ELEMENTS
объединение в любой подкласс; используйте это так:
class Parent(object, metaclass=AllVMeta):
V_1 = set()
V_2 = set()
class Child1(Parent):
V_1 = {1, }
V_2 = {4, 7, 10}
class Child2(Parent):
V_1 = {'a', 'b'}
V_2 = {'a', 'c'}
Демо-версия:
>>> class AllVMeta(type):
... def __new__(typ, name, bases, attrs):
... cls = super(AllVMeta, typ).__new__(typ, name, bases, attrs)
... cls.ALL_V_ELEMENTS = cls.V_1 | cls.V_2
... return cls
...
>>> class Parent(object, metaclass=AllVMeta):
... V_1 = set()
... V_2 = set()
...
>>> class Child1(Parent):
... V_1 = {1, }
... V_2 = {4, 7, 10}
...
>>> class Child2(Parent):
... V_1 = {'a', 'b'}
... V_2 = {'a', 'c'}
...
>>> Child1.ALL_V_ELEMENTS
{1, 10, 4, 7}
>>> Child2.ALL_V_ELEMENTS
{'a', 'c', 'b'}