This question already has an answer here:
这个问题在这里已有答案:
- What is the best way to implement nested dictionaries? 20 answers
- 实现嵌套字典的最佳方法是什么? 20个答案
A lot of times in Perl, I'll do something like this:
在Perl很多次,我会做这样的事情:
$myhash{foo}{bar}{baz} = 1
How would I translate this to Python? So far I have:
我怎么把它翻译成Python?到目前为止我有:
if not 'foo' in myhash:
myhash['foo'] = {}
if not 'bar' in myhash['foo']:
myhash['foo']['bar'] = {}
myhash['foo']['bar']['baz'] = 1
Is there a better way?
有没有更好的办法?
5 个解决方案
#1
83
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
Testing:
测试:
a = AutoVivification()
a[1][2][3] = 4
a[1][3][3] = 5
a[1][2]['test'] = 6
print a
Output:
输出:
{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}
#2
87
If the amount of nesting you need is fixed, collections.defaultdict
is wonderful.
如果你需要的嵌套量是固定的,那么collections.defaultdict很棒。
e.g. nesting two deep:
例如嵌套两个深:
myhash = collections.defaultdict(dict)
myhash[1][2] = 3
myhash[1][3] = 13
myhash[2][4] = 9
If you want to go another level of nesting, you'll need to do something like:
如果你想进行另一层嵌套,你需要做类似的事情:
myhash = collections.defaultdict(lambda : collections.defaultdict(dict))
myhash[1][2][3] = 4
myhash[1][3][3] = 5
myhash[1][2]['test'] = 6
edit: MizardX points out that we can get full genericity with a simple function:
编辑:MizardX指出我们可以通过一个简单的函数获得完全的通用性:
import collections
def makehash():
return collections.defaultdict(makehash)
Now we can do:
现在我们可以做到:
myhash = makehash()
myhash[1][2] = 4
myhash[1][3] = 8
myhash[2][5][8] = 17
# etc
#3
12
Is there a reason it needs to be a dict of dicts? If there's no compelling reason for that particular structure, you could simply index the dict with a tuple:
是否有理由需要成为决定词?如果这个特定结构没有令人信服的理由,你可以简单地用一个元组索引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
The parentheses are required if you initialize the dict with a tuple key, but you can omit them when setting/getting values using []:
如果使用元组键初始化dict,则需要括号,但在使用[]设置/获取值时可以省略它们:
mydict = {} # Initialized the dict
mydict['foo', 'bar', 'baz'] = 1 # Sets a value
mydict['foo', 'bar', 'baz'] # Returns 1
#4
2
I guess the literal translation would be:
我想直译将是:
mydict = {'foo' : { 'bar' : { 'baz':1}}}
Calling:
呼叫:
>>> mydict['foo']['bar']['baz']
gives you 1.
给你1。
That looks a little gross to me, though.
不过,这看起来有点严重。
(I'm no perl guy, though, so I'm guessing at what your perl does)
(不过,我不是perl家伙,所以我猜你的perl会做什么)
#5
2
Nested dictionaries like that are (often) called a poor mans objects. Yes, there is an implication and it might correlate with pythons object oriented nature.
像这样的嵌套字典(通常)被称为可怜的勒芒对象。是的,有一个含义,它可能与蟒蛇面向对象的性质有关。
#1
83
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
Testing:
测试:
a = AutoVivification()
a[1][2][3] = 4
a[1][3][3] = 5
a[1][2]['test'] = 6
print a
Output:
输出:
{1: {2: {'test': 6, 3: 4}, 3: {3: 5}}}
#2
87
If the amount of nesting you need is fixed, collections.defaultdict
is wonderful.
如果你需要的嵌套量是固定的,那么collections.defaultdict很棒。
e.g. nesting two deep:
例如嵌套两个深:
myhash = collections.defaultdict(dict)
myhash[1][2] = 3
myhash[1][3] = 13
myhash[2][4] = 9
If you want to go another level of nesting, you'll need to do something like:
如果你想进行另一层嵌套,你需要做类似的事情:
myhash = collections.defaultdict(lambda : collections.defaultdict(dict))
myhash[1][2][3] = 4
myhash[1][3][3] = 5
myhash[1][2]['test'] = 6
edit: MizardX points out that we can get full genericity with a simple function:
编辑:MizardX指出我们可以通过一个简单的函数获得完全的通用性:
import collections
def makehash():
return collections.defaultdict(makehash)
Now we can do:
现在我们可以做到:
myhash = makehash()
myhash[1][2] = 4
myhash[1][3] = 8
myhash[2][5][8] = 17
# etc
#3
12
Is there a reason it needs to be a dict of dicts? If there's no compelling reason for that particular structure, you could simply index the dict with a tuple:
是否有理由需要成为决定词?如果这个特定结构没有令人信服的理由,你可以简单地用一个元组索引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
The parentheses are required if you initialize the dict with a tuple key, but you can omit them when setting/getting values using []:
如果使用元组键初始化dict,则需要括号,但在使用[]设置/获取值时可以省略它们:
mydict = {} # Initialized the dict
mydict['foo', 'bar', 'baz'] = 1 # Sets a value
mydict['foo', 'bar', 'baz'] # Returns 1
#4
2
I guess the literal translation would be:
我想直译将是:
mydict = {'foo' : { 'bar' : { 'baz':1}}}
Calling:
呼叫:
>>> mydict['foo']['bar']['baz']
gives you 1.
给你1。
That looks a little gross to me, though.
不过,这看起来有点严重。
(I'm no perl guy, though, so I'm guessing at what your perl does)
(不过,我不是perl家伙,所以我猜你的perl会做什么)
#5
2
Nested dictionaries like that are (often) called a poor mans objects. Yes, there is an implication and it might correlate with pythons object oriented nature.
像这样的嵌套字典(通常)被称为可怜的勒芒对象。是的,有一个含义,它可能与蟒蛇面向对象的性质有关。