继承和聚合类属性

时间:2015-06-07 06:20:48

标签: python django inheritance metaclass

一个简单的例子:

class A:
    attr = {'a': 1}

class B(A):
    attr = {'b': 2} #overrides A.attr

我想要的是一种聚合字典的方法。我可以想到这些选项:

  1. 忽略那种令人不安的感觉,并手工复制一切。
  2. 手动添加词典:

    class B(a):
        attr = dict(list(six.iteritems(A.attr)) + list(six.iteritems({
            'b': 2
        })))
    

    注意'b': 2必须排在第二位,因此其密钥为A&#39}。

    这必须明确引用A是否有某种方法可以通过super 来获得此功能)。它还需要手动应用这种微继承。

  3. 这也是元类可以实现的。我见过done in DeclarativeFieldsMetaclass in django。 我们的想法是让元类句柄字典合并为特定属性。

    这是更多的工作。此外,由于它引入了在python中通常不会发生的魔法,这可能被认为是一个糟糕的选择。除非有必要避免冲突,否则我也不想使用元类。

    一个主要优点是用户不需要手动聚合属性数据。

  4. 还有其他办法吗?

    我想知道其他人对优秀编程实践的每种方法的看法。

    在我的情况下,我使用MultiModelForm from django-betterforms,并且只有几个ModelForm的基本表单,但想要扩展它。我不认为继承的类需要从父级复制ModelForm属性中的form_classes

    是否应该由用户来管理继承,如选项2中所示,或者MultiModelForm是否应该使用选项3中的元类自动处理它?我还没有讨论过每个选项还有其他问题吗?

2 个答案:

答案 0 :(得分:6)

您可以使用dictionary.update()函数执行此操作,该函数会向现有字典添加新字典

示例

>>> class A:
...     attr = {'a': 1}
... 
>>> class B(A):
...     attr = dict(A.attr)
...     attr.update({'b' : 2 })
... 
>>> 
>>> A.attr
{'a': 1}
>>> B.attr
{'a': 1, 'b': 2}

它的作用是什么?

  • attr = dict(A.attr)A.attr返回一个新词典。这很重要,因为如果我们写

    attr = A.attr
    

    我们最终会更新attrA而不是B类。

  • attr.update({'b' : 2 })通过添加新词典B.attr来更新{'b' : 2 }

答案 1 :(得分:4)

这对我有用:

class A:
    attr = {'a': 1}

class B(A):
    attr = dict({'b': 2}.items() + A.attr.items())