【问题标题】:Inheriting and aggregating class attributes继承和聚合类属性
【发布时间】:2015-08-21 19:52:54
【问题描述】:

一个简单的例子:

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

    这必须明确引用A有什么方法可以通过super 得到这个吗?)。它还需要手动应用这种微继承。

  3. 这也是元类可以实现的。我看过done in DeclarativeFieldsMetaclass in django。 这个想法是让元类处理字典合并特定属性。

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

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

还有其他方法吗?

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

在我的例子中,我使用的是MultiModelForm from django-betterforms,并且有一个只有几个ModelForms 的基本形式,但我想扩展它。我认为继承的类不需要从父类复制form_classes 属性中的ModelForms。

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

【问题讨论】:

标签: python django inheritance metaclass


【解决方案1】:

您可以使用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
    

    我们最终将更新 A 类的 attr,而不是 B 类。

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

【讨论】:

    【解决方案2】:

    这对我有用:

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

    【讨论】:

    • 你是对的,它也是。我一直认为那只是python 3。虽然它会颠倒添加的顺序。
    • @jozxyqk:实际上只是 Python 2;在 Python 3 中,items 返回一个视图,而 dict 视图不支持加法。如果您真的愿意,可以进行一些更改以使其适应 Python 3。
    猜你喜欢
    • 2012-12-08
    • 2014-08-09
    • 1970-01-01
    • 1970-01-01
    • 2016-10-17
    • 2015-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多