python dict的子类中的RecursionError

时间:2018-02-05 23:21:19

标签: python dictionary

我编写了一个继承dict builtin类型的python类。我想用其他检查方法编写一种容器。

如果我创建该类的实例,我得到了一个RecursionError。我不明白这个错误。

class Params(dict):
    """ A convenient container of all paramters """

    # list of authorized keywords with default values
    keywords = {"k1": 1, "k2": 2, "k3": 3}

    def __init__(self, *args, **kwargs):
        # self.update(self.keywords)
        for k, v in self.keywords.items():
            self[k] = v
        self.update(*args, **kwargs)

    def update(self, *args, **kwargs):
        for k, v in dict(*args, **kwargs).items():
            self[k] = v

    def __setitem__(self, name, value):
        """ set a parameters following dict syntax """
        name = name.lower()
        if name in self.keywords:
            self[name] = value
        else:
            raise KeyError("Keywords %s does not exist." % name)

    def __getattr__(self, name):
        """ get paramters as an attribute of the class """
        return self.__getitem__(name)

1 个答案:

答案 0 :(得分:1)

因此,正如我在评论中暗示的那样,您的递归错误正在发生,因为您在self.__setitem__中隐含地调用self.__setitem__,因此您应该调用超类 {{1相反。这是一种方式:

__setitem__

注意,我使用了{3}的Python 3版本  Python 2需要:In [6]: class Params(dict): ...: """ A convenient container of all paramters """ ...: ...: # list of authorized keywords with default values ...: keywords = {"k1": 1, "k2": 2, "k3": 3} ...: ...: def __init__(self, *args, **kwargs): ...: # self.update(self.keywords) ...: for k, v in self.keywords.items(): ...: self[k] = v ...: self.update(*args, **kwargs) ...: ...: def update(self, *args, **kwargs): ...: for k, v in dict(*args, **kwargs).items(): ...: self[k] = v ...: ...: def __setitem__(self, name, value): ...: """ set a parameters following dict syntax """ ...: name = name.lower() ...: if name in self.keywords: ...: # note: dict.__setitem__(self, name, value) would also work ...: super().__setitem__(name, value) ...: else: ...: raise KeyError("Keywords %s does not exist." % name) ...: ...: def __getattr__(self, name): ...: """ get paramters as an attribute of the class """ ...: return self.__getitem__(name) ...: In [7]: p = Params(k1=10) In [8]: p Out[8]: {'k1': 10, 'k2': 2, 'k3': 3}

注意,一般来说,我更喜欢组合而不是继承。拥有一个super对象,其中包含您通过公共接口管理的内部super(Params, self).__setitem__(name, value)属性。这将更加强大,并避免继承内置类型带来的麻烦。