继承和聚合类属性

joz*_*yqk 3 python django inheritance metaclass

一个简单的例子:

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

class B(A):
    attr = {'b': 2} #overrides A.attr
Run Code Online (Sandbox Code Playgroud)

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

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

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

    注意'b': 2必须是第二个,所以它的键影A.

    这必须A明确引用(有什么方法可以得到它super).它还需要手动应用这种微继承.

  3. 这也是元类可以实现的.我已经看到了它在完成DeclarativeFieldsMetaclass在Django.我们的想法是让元类句柄字典合并为特定属性.

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

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

还有另外一种方法吗?

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

在我的情况下,我使用的MultiModelForm是django-betterforms,并且只有几个ModelForms 的基本形式,但想要扩展它.我不认为继承的类应该需要从父类复制属性中的ModelForms form_classes.

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

nu1*_*73R 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}
Run Code Online (Sandbox Code Playgroud)

它能做什么?

  • attr = dict(A.attr)从中返回一个新字典A.attr.这很重要,因为如果我们写的话

    attr = A.attr
    
    Run Code Online (Sandbox Code Playgroud)

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

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