如何更改实例的dict()行为

Cea*_*sta 18 python dictionary overriding autovivification

所以我正在编写一个扩展字典的类,该字典现在使用一种方法"dictify"将自身转换为字典.我想做的是改变它,以便在对象上调用dict()导致相同的行为,但我不知道要覆盖哪个方法.这是不可能的,还是我错过了一些完全明显的东西?(是的,我知道下面的代码不起作用,但我希望它能说明我正在尝试做什么.)

from collections import defaultdict

class RecursiveDict(defaultdict):
    '''
    A recursive default dict.

    >>> a = RecursiveDict()
    >>> a[1][2][3] = 4
    >>> a.dictify()
    {1: {2: {3: 4}}}
    '''
    def __init__(self):
        super(RecursiveDict, self).__init__(RecursiveDict)

    def dictify(self):
        '''Get a standard dictionary of the items in the tree.'''
        return dict([(k, (v.dictify() if isinstance(v, dict) else v))
                     for (k, v) in self.items()])

    def __dict__(self):
        '''Get a standard dictionary of the items in the tree.'''
        print [(k, v) for (k, v) in self.items()]
        return dict([(k, (dict(v) if isinstance(v, dict) else v))
                     for (k, v) in self.items()])
Run Code Online (Sandbox Code Playgroud)

编辑:更清楚地显示问题:

>>> b = RecursiveDict()
>>> b[1][2][3] = 4
>>> b
defaultdict(<class '__main__.RecursiveDict'>, {1: defaultdict(<class '__main__.RecursiveDict'>, {2: defaultdict(<class '__main__.RecursiveDict'>, {3: 4})})})
>>> dict(b)
{1: defaultdict(<class '__main__.RecursiveDict'>, {2: defaultdict(<class '__main__.RecursiveDict'>, {3: 4})})}
>>> b.dictify()
{1: {2: {3: 4}}}
Run Code Online (Sandbox Code Playgroud)

我希望dict(b)与b.dictify()相同

Rob*_*wie 28

您的方法没有任何问题,但这类似于Perl的Autovivification功能,在此问题中已经在Python 实现.为此向@nosklo道具.

class RecursiveDict(dict):
    """Implementation of perl's autovivification feature."""
    def __getitem__(self, item):
        try:
            return dict.__getitem__(self, item)
        except KeyError:
            value = self[item] = type(self)()
            return value

>>> a = RecursiveDict()
>>> a[1][2][3] = 4
>>> dict(a)
{1: {2: {3: 4}}}
Run Code Online (Sandbox Code Playgroud)

编辑

正如@Rosh Oxymoron所建议的那样,使用__missing__更简洁的实现结果.需要Python> = 2.5

class RecursiveDict(dict):
    """Implementation of perl's autovivification feature."""
    def __missing__(self, key):
        value = self[key] = type(self)()
        return value
Run Code Online (Sandbox Code Playgroud)

  • 如果你只是定义`__missing __(self,item)`,你可以将它缩短为except子句的代码. (5认同)