Class 变量 V3 依赖于 V1 和 V2。如何在 children 类 中定义 V3
Class variable V3 dependent on V1 and V2. How to define V3 in children classes
Parent
class 被其他多个 class 继承。
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
在每个 child 中都是不同的(而且一旦 class 创建后它们就不会改变)。
使用下面的代码,我得到了 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'}
为了实现我的目标,我可以定义 classes 如下:
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
然而,copy-pasting ALL_V_ELEMENTS = V_1 | V_2
在 Parent
的每个 child 上似乎不是一个好主意。
另一种选择是以不同的方式定义 Parent
:
class Parent(object):
V_1 = set()
V_2 = set()
def __init__(self):
self.ALL_V_ELEMENTS = self.V_1 | self.V_2
这会对每个冗余实例执行 |
操作。
有没有更好的方法来实现我的目标?
您可以将其定义为 属性:
class Parent(object):
V_1 = set()
V_2 = set()
@property
def ALL_V_ELEMENTS(self):
return V_1 | V_2
但是,这将每次重新计算集合。让 __init__
创建集意味着将为每个实例创建它。
您可以在 metaclass 中计算集合,因此它仅在生成 class 对象时生成:
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 将ALL_V_ELEMENTS
联合添加到任何子class;像这样使用它:
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'}
Parent
class 被其他多个 class 继承。
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
在每个 child 中都是不同的(而且一旦 class 创建后它们就不会改变)。
使用下面的代码,我得到了 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'}
为了实现我的目标,我可以定义 classes 如下:
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
然而,copy-pasting ALL_V_ELEMENTS = V_1 | V_2
在 Parent
的每个 child 上似乎不是一个好主意。
另一种选择是以不同的方式定义 Parent
:
class Parent(object):
V_1 = set()
V_2 = set()
def __init__(self):
self.ALL_V_ELEMENTS = self.V_1 | self.V_2
这会对每个冗余实例执行 |
操作。
有没有更好的方法来实现我的目标?
您可以将其定义为 属性:
class Parent(object):
V_1 = set()
V_2 = set()
@property
def ALL_V_ELEMENTS(self):
return V_1 | V_2
但是,这将每次重新计算集合。让 __init__
创建集意味着将为每个实例创建它。
您可以在 metaclass 中计算集合,因此它仅在生成 class 对象时生成:
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 将ALL_V_ELEMENTS
联合添加到任何子class;像这样使用它:
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'}