2013-01-24 106 views
289

是否有可能在Python中创建字典理解(用于键)?Python字典理解

没有列表解析,你可以使用这样的事情:

l = [] 
for n in range(1, 11): 
    l.append(n) 

我们可以缩短这一个列表理解:l = [n for n in range(1, 11)]

但是,假设我想将字典的键设置为相同的值。 我可以这样做:

d = {} 
for n in range(1, 11): 
    d[n] = True # same value for each 

我已经试过这样:

d = {} 
d[i for i in range(1, 11)] = True 

不过,我得到的for一个SyntaxError

另外(我不需要这部分,但只是想知道),可以设置一个字典的键一堆不同的值,例如:

d = {} 
for n in range(1, 11): 
    d[n] = n 

这是可能的字典解析?

d = {} 
d[i for i in range(1, 11)] = [x for x in range(1, 11)] 

这也引发了对for一个SyntaxError

+1

对于未来读者的信息:NumPy数组允许您将多个元素设置为单个值或值列表,这是您尝试执行的方式。虽然如果你还没有理由使用NumPy,那么这个功能可能不值得。 –

回答

390

dictionary comprehensions in Python 2.7+,但他们不像你想要的那样工作。像列表理解一样,他们创建了一个新的字典;您不能使用它们将键添加到现有字典。此外,您必须指定键和值,但当然如果您愿意,您也可以指定一个虚拟值。

>>> d = {n: n**2 for n in range(5)} 
>>> print d 
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16} 

如果你想将它们全部设置为True:

>>> d = {n: True for n in range(5)} 
>>> print d 
{0: True, 1: True, 2: True, 3: True, 4: True} 

你似乎在询问什么是一次对现有的字典来设置多个按键的方式。这没有直接的捷径。你可以像你已经显示的那样循环,或者你可以使用字典理解来创建一个带有新值的新字典,然后执行oldDict.update(newDict)将新值合并到旧字典中。

+10

FWIW,'dict.update'还可以接受可迭代的键值对,就像'dict'构造函数 – mgilson

+1

注意,如果您创建的字典中所有值都相同,请使用'dict.fromkeys()'。因此,要将所有值设置为“True”,请使用'dict.fromkeys(range(5),True)'。注意,值是*不复制*,所以你可能想避免这种情况,当你有一个可变的值;它将在所有密钥之间共享。 –

+1

注意:键也可以是方法的结果:'{n * 2:n在范围内(3)} => {0:0,2:1,4:2}。两者都可以在同一个表达式中完成:'{n * 2:n * 3在范围内(3)} => {0:0,2:3,4:6}'。 – Zaaier

136

可以使用dict.fromkeys类方法......

>>> dict.fromkeys(range(1, 11), True) 
{1: True, 2: True, 3: True, 4: True, 5: True, 6: True, 7: True, 8: True, 9: True, 10: True} 

这是创建一个字典,所有的按键映射到相同值的最快方法。

不过要小心使用这种带有可变对象:

d = dict.fromkeys(range(10), []) 
d[1].append(2) 
print(d[2]) # ??? 

如果你实际上并不需要初始化所有的按键,一个defaultdict可能是有用的:

from collections import defaultdict 
d = defaultdict(lambda: True) 

要回答第二部分,你需要一个字典理解:

{k: k for k in range(10)} 

或为python2.6的:

dict((k, k) for k in range(10)) 

您还可以创建字典的一个聪明的子类,工作有点像defaultdict如果重写__missing__

>>> class KeyDict(dict): 
... def __missing__(self, key): 
...  #self[key] = key # Maybe add this also??? 
...  return key 
... 
>>> d = KeyDict() 
>>> d[1] 
1 
>>> d[2] 
2 
>>> d[3] 
3 
>>> print(d) 
{} 

整洁。

+0

注意,在'd = defaultdict(lambda:True)'的情况下,lambda不是必需的,因为True是(或不应该)是可变的。 – rhbvkleef

21
>>> {i:i for i in range(1, 11)} 
{1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, 7: 7, 8: 8, 9: 9, 10: 10} 
10

使用字典()元组的名单上,该解决方案将允许你在每个列表中的任意值,只要它们是相同的长度

i_s = range(1, 11) 
x_s = range(1, 11) 
# x_s = range(11, 1, -1) # Also works 
d = dict([(i_s[index], x_s[index],) for index in range(len(i_s))]) 
+10

作为一个侧面说明,这是'd =字典(zip(i_s,x_s))' – mgilson

-2

你无法散列这样的列表。 试试这个,而是使用元组

d[tuple([i for i in range(1,11)])] = True 
+6

这是根本不会做什么的OP想要... –

6

列表理解的主要目的是创建一个基于另一个没有改变或破坏原始列表中的新名单。

而是写作的

l = [] 
    for n in range(1, 11): 
     l.append(n) 

l = [n for n in range(1, 11)] 

你应该只写

l = range(1, 11) 

在你创建一个新的列表中的两个顶级代码块,通过它遍历并返回每个元素。这只是创建列表副本的昂贵方式。

要获得与设置为基于另一字典相同值的所有密钥的新的字典,这样做:因为当你写

d = {} 
    d[i for i in range(1, 11)] = True 

old_dict = {'a': 1, 'c': 3, 'b': 2} 
    new_dict = { key:'your value here' for key in old_dict.keys()} 

你会收到一个SyntaxError '基本上是这样说的:'我为我在范围(1,11)'设置我的密钥'为真“和”我为我在范围内(1,11)“不是一个有效的密钥,它只是一个语法错误。如果类型的字典支持列表钥匙,你会做这样的事情

d[[i for i in range(1, 11)]] = True 

,而不是

d[i for i in range(1, 11)] = True 

但列表不是可哈希的,所以你不能把它们作为字典键。

16

我真的很喜欢@mgilson的评论,因为如果你有两个迭代器,一个对应键和另一个值,你也可以执行以下操作。

keys = ['a', 'b', 'c'] 
values = [1, 2, 3] 
d = dict(zip(keys, values)) 

给予

d = { 'A':1, 'B':2, 'C':3}

9

考虑计数词语的出现的该示例在列表中使用字典解析

my_list = ['hello', 'hi', 'hello', 'today', 'morning', 'again', 'hello'] 
my_dict = {k:my_list.count(k) for k in my_list} 
print(my_dict) 

,其结果是

{'again': 1, 'hi': 1, 'hello': 3, 'today': 1, 'morning': 1} 
+0

这是有趣的,但不是最有效的因为你会多次计算像'hello'这样的键 – FuriousGeorge