继承和聚合类属性

4
一个简单的例子:
class A:
    attr = {'a': 1}

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

我想要的是一种聚合字典的方法。我能想到的选项只有以下几种:

  1. Ignore that disconcerting feeling and copy everything by hand.
  2. Manually adding the dictionaries:

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

    Note 'b': 2 must come second so its keys shadow A's.

    This must reference A explicitly (is there some way to get this with super?). It also needs this kind of micro inheritance to be applied manually.

  3. This is also something that could be achieved with metaclasses. I've seen it done in DeclarativeFieldsMetaclass in django. The idea is to have the metaclass handle dictionary merging for a specific attribute.

    This is far more work. Also, as it introduces magic that doesn't normally happen in python, this might be considered a poor option. I also prefer to not use metaclasses unless necessary to avoid conflicts.

    One major advantage is the user doesn't need to manually aggregate the attribute data.

还有其他的方法吗?

我想知道其他人对每种方法在良好的编程实践方面的看法。

在我的情况下,我正在使用django-betterforms中的MultiModelForm,有一个基础表单,只包含几个ModelForm,但想要扩展它。 我不认为继承类应该需要在父类的form_classes属性中复制ModelForm

是应该由用户来管理继承,如选项2,还是应该由MultiModelForm使用元类自动处理,如选项3?每个选项是否存在其他未讨论的问题?


1
在Python 3.5中,您可以执行attr = {**A.attr, 'b': 2} - user2357112
2个回答

7
你可以使用 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) returns a new dictionary from A.attr. This is important because if we write

    attr = A.attr
    

    we will end up updating the attr of A class instead of B class.

  • attr.update({'b' : 2 }) Updates the B.attr by adding the new dictionary {'b' : 2 }.


4
这对我行之有效:
class A:
    attr = {'a': 1}

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

你说得对,确实如此。我一直以为这只适用于Python 3。虽然它会颠倒加法的顺序。 - jozxyqk
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - user2357112

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接