python – 通过类层次结构合并dict类属性

我正在尝试使以下代码工作.我想创建一个class属性,它是一个默认值的字典,通过类层次结构自动从子级更新为父级.理想情况下,我想在父对象中使用魔术来执行此操作,以便子对象可以根据需要简单地覆盖值.如果对这类事情有成语,我也愿意接受如何重新设计的建议.

class A(object):
  DEFAULTS = {'a': 'default a', 'd': 'test d'}

  def __init__(self, *args, **kwargs):
    pass
    # but can i do something with super? this fails but is the
    # approximate idea of what I want...
    # self.DEFAULTS.update(super(self.__class__, self).DEFAULTS)

class B(A):
  DEFAULTS = {'b': 'default b'}

class C(A):
  DEFAULTS = {'a': 'a overridden in C'}

class D(C):
  DEFAULTS = {'d': 'd overridden in D'}

def test():
  a = A()
  b = B()
  c = C()
  d = D()
  print a.DEFAULTS
  print b.DEFAULTS
  print c.DEFAULTS
  print d.DEFAULTS
  assert (a.DEFAULTS == {'a': 'default a', 'd': 'test d'})
  assert (b.DEFAULTS == {'a': 'default a', 'b': 'default b', 'd': 'test d'})
  assert (c.DEFAULTS == {'a': 'overridden in c', 'd': 'test d'})
  assert (d.DEFAULTS == {'a': 'overridden in c', 'd': 'd overridden in D'})

test()

当然,现在这导致以下输出:

{'a': 'default a', 'd': 'test d'}
{'b': 'default b'}
{'a': 'a overridden in C'}
{'d': 'd overridden in D'}
Traceback (most recent call last):
  File "experimental/users/edw/python/class_magic.py", line 36, in <module>
    test()
  File "experimental/users/edw/python/class_magic.py", line 32, in test
    assert (b.DEFAULTS == {'a': 'default a', 'b': 'default b', 'd': 'test d'})
AssertionError

最佳答案 这适合您的需求吗?

方法示例:

class A(object):
    _DEFAULTS = {'a': 'a value'}

    @classmethod
    def get_defaults(cls):
        return cls._DEFAULTS

class B(A):
    _B_DEFAULTS = {'b': 'b value'}

    @classmethod
    def get_defaults(cls):
        defaults = super(B, cls).get_defaults()
        defaults.update(cls._B_DEFAULTS)
        return defaults

元类例子:

# Some data-structure (it should be refactored): 
_DEFAULTS = {'A': {'a': 'a_value'}, 'B': {'b': 'b_value'}}

class DefaultsInitializer(type):
     def __call__(self, *args, **kwargs):
          obj = type.__call__(self)
          obj.defaults = _DEFAULTS[obj.__class__.__name__]
          for klass in obj.__class__.__bases__:
               if klass.__name__ in _DEFAULTS:
                    obj.defaults.update(_DEFAULTS[klass.__name__])
          return obj

还有一些课程:

>>> class A(object):
...      __metaclass__ = DefaultsInitializer
... 
>>> a = A()
>>> a.defaults
{'a': 'a_value'}
>>> class B(A):
...      pass
... 
>>> b = B()
>>> b.defaults
{'a': 'a_value', 'b': 'b_value'}
点赞