87

很多时候在 Perl 中,我会做这样的事情:

$myhash{foo}{bar}{baz} = 1

我如何将它翻译成 Python?到目前为止,我有:

if not 'foo' in myhash:
    myhash['foo'] = {}
if not 'bar' in myhash['foo']:
    myhash['foo']['bar'] = {}
myhash['foo']['bar']['baz'] = 1

有没有更好的办法?

4

4 回答 4

120

如果您需要的嵌套数量是固定的,那就collections.defaultdict太好了。

例如嵌套两个深:

myhash = collections.defaultdict(dict)
myhash[1][2] = 3
myhash[1][3] = 13
myhash[2][4] = 9

如果您想进行另一层嵌套,您需要执行以下操作:

myhash = collections.defaultdict(lambda : collections.defaultdict(dict))
myhash[1][2][3] = 4
myhash[1][3][3] = 5
myhash[1][2]['test'] = 6

编辑:MizardX 指出我们可以通过一个简单的函数获得完整的通用性:

import collections
def makehash():
    return collections.defaultdict(makehash)

现在我们可以这样做:

myhash = makehash()
myhash[1][2] = 4
myhash[1][3] = 8
myhash[2][5][8] = 17
# etc
于 2009-03-16T21:29:44.153 回答
108
class AutoVivification(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 = AutoVivification()

a[1][2][3] = 4
a[1][3][3] = 5
a[1][2]['test'] = 6

print a

输出:

{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}
于 2009-03-16T19:45:34.013 回答
15

是否有理由需要成为字典的字典?如果该特定结构没有令人信服的理由,您可以简单地使用元组索引 dict:

mydict = {('foo', 'bar', 'baz'):1} # Initializes dict with a key/value pair
mydict[('foo', 'bar', 'baz')]      # Returns 1

mydict[('foo', 'unbar')] = 2       # Sets a value for a new key

如果使用元组键初​​始化 dict,则需要括号,但在使用 [] 设置/获取值时可以省略它们:

mydict = {}                        # Initialized the dict
mydict['foo', 'bar', 'baz'] = 1    # Sets a value
mydict['foo', 'bar', 'baz']        # Returns 1
于 2009-03-16T19:56:21.773 回答
2

我猜直译应该是:

 mydict = {'foo' : { 'bar' : { 'baz':1}}}

来电:

 >>> mydict['foo']['bar']['baz']

给你1。

不过,这对我来说看起来有点恶心。

(不过,我不是 perl 人,所以我猜你的 perl 做了什么)

于 2009-03-16T19:28:00.373 回答