【问题标题】:Class variable V3 dependent on V1 and V2. How to define V3 in children classes类变量 V3 取决于 V1 和 V2。如何在子类中定义 V3
【发布时间】:2016-04-02 12:06:42
【问题描述】:

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_1V_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

这将对每个冗余实例执行| 操作。


有没有更好的方法来实现我的目标?

【问题讨论】:

  • (我想不出更合适的标题;如果您找到更好的问题标题,请随时提出建议或编辑)

标签: python inheritance python-3.4 class-variables


【解决方案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'}

【讨论】:

    猜你喜欢
    • 2016-11-22
    • 2015-09-25
    • 2010-10-16
    • 2017-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    相关资源
    最近更新 更多