Python更新继承类级别的字典

5
我正在寻找一种简洁明了的方法来更新从基类继承而来的类级别字典。例如:
class Foo(object):
    adict = {'a' : 1}

class Bar(Foo):
    adict.update({'b' : 2})  # this errors out since it can't find adict

以便于:

Foo.adict == {'a' : 1}
Bar.adict == {'a' : 1, 'b' : 2}

我希望这里不使用实例,如果可能的话也不要使用类方法。

4个回答

5
请注意,即使这样做可以工作,你也会更新相同的字典而不是创建一个新的(因此Foo.adict is Bar.adict,因此Foo.adict == Bar.adict)。
无论如何,最简单的方法是明确引用父类的字典(并复制它,见上文):
class Bar(Foo):
    adict = dict(Foo.adict)
    adict.update({'b': 2})

谢谢 - 这绝对有效 - 我希望我能找到一些更通用的东西(例如像super一样),除了继承之外不需要显式地引用父类。 - gnr
你在这里并没有真正使用太多的继承,因为你使用了类字典。你可以只使用一个全局字典来达到同样的效果。 - Lennart Regebro

2

我也遇到了这个问题。我通过使用元类来解决它,这种方法也适用于多重继承:

import six


class CheckerMeta(type):

    def __new__(cls, name, bases, attrs):
        new_class = super(CheckerMeta, cls).__new__(cls, name, bases, attrs)

        base_configs = [bc.config for bc in bases if hasattr(bc, 'config')]
        configs = base_configs + [new_class.config]

        new_class.config = {}
        for config in configs:
            new_class.config.update(config)

        return new_class


class BaseChecker(six.with_metaclass(CheckerMeta)):
    config = {}


class CheckerA(BaseChecker):
    config = {'a': 1}


class CheckerB(BaseChecker):
    config = {'b': 2}


class CheckerC(CheckerA, CheckerB):
    config = {'c': 3}


assert CheckerA.config == {'a': 1}
assert CheckerB.config == {'b': 2}
assert CheckerC.config == {'a': 1, 'b': 2, 'c':3}

0
Foo类中初始化adict,并在Bar中通过调用superinit方法,然后调用update来进行初始化。
class Foo(object):
    def __init__(self):
        self.adict = {'a': 1}


class Bar(Foo):
    def __init__(self):
        super(Bar, self).__init__()
        self.adict.update({'b': 2})

例子:

In [14]: b = Bar()
In [15]: b.adict
Out[15]: {'a': 1, 'b': 2}

0

“我宁愿不在这里使用实例,如果可能的话也不要使用类方法。”

“好的,那就不用。”

foo_adict =  {'a' : 1}

def B():
   foo_adict.update({'b': 2})

我不确定为什么你要使用类属性级别的字典,它很少以有用或预期的方式运作。

类成员有其用处。的确,它们很高级,但它们并不像全局变量那样糟糕,也不是等价的——你可以(就像我的代码片段中一样)在每个类中拥有单独的值。我正在处理的代码库在一些地方使用类成员,尽管可以承认这是为了重度元编程。除了使逻辑分组更明显外,“classmethod”还需要从某处获取它们所操作的数据。 - user395760
类成员有它们的用途。类成员字典(或其他可变对象)通常没有。 - Lennart Regebro
为了提供一些背景,我正在使用这种组织方法来构建API。例如,我希望Foo.adict['a']和Bar.adict['a']具有不同值的初始化能力,尽管对于大多数变量来说它们将是相同的。在类定义之后,这些字典将不会被修改。我还需要Foo和Bar具有静态属性,这些属性不会被继承。我不明白为什么使用类成员字典本质上是一个坏主意。 - gnr
@mlauria:“在类定义之后,字典将不会被修改。” - 在这种情况下,我再次建议您不要将它们作为类实例。特别是因为它是一个API。这对于API的用户来说是令人困惑的,他们将开始修改字典,而它将不像他们期望的那样运行。选项包括全局字典,根本没有字典,而只是直接使用类成员,以及某种只读字典。 - Lennart Regebro

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