【发布时间】:2015-09-28 10:08:26
【问题描述】:
为什么 setdefault 不会在字典推导中 a 中的每次出现都增加 1,但它会在循环中增加?这里发生了什么?
替代解决方案很棒。我最感兴趣的是了解为什么这不起作用。
带有 setdefault 的循环工作
a = [1,1,2,2,2,3,3]
b = {}
for x in a:
b[x] = b.setdefault(x, 0) + 1
b
Out[4]: {1: 2, 2: 3, 3: 2}
使用 setdefault 的字典理解不起作用
b = {k: b.setdefault(k, 0) + 1 for k in a}
b
Out[7]: {1: 1, 2: 1, 3: 1}
更新
感谢您的回答,我想尝试为解决方案计时。
def using_get(a):
b = {}
for x in a:
b[x] = b.get(x, 0) + 1
return b
def using_setdefault(a):
b = {}
for x in a:
b[x] = b.setdefault(x, 0) + 1
return b
timeit.timeit(lambda: Counter(a), number=1000000)
Out[3]: 15.19974103783569
timeit.timeit(lambda: using_get(a), number=1000000)
Out[4]: 3.1597984457950474
timeit.timeit(lambda: using_setdefault(a), number=1000000)
Out[5]: 3.231248461129759
【问题讨论】:
-
因为
b在执行理解时没有定义。顺便说一句,你试过b = collections.Counter(a)吗? -
dict.setdefault无论如何都是一种奇怪的方法——你通常会将它与可变值一起使用,而不是不可变值(例如d.setdefault[x, []].append(...))。我会写b[x] = b.get(x, 0) + 1。 -
不起作用。实际上,这非常有效。如果
b = {}。最初,您将获得一个新字典(新分配给b),其中包含a的所有键值和= 0 + 1的所有值。然而,原来的b已经消失了。不过,这可能不是您所期望的。如果b没有在理解之前定义,你会得到NameError。
标签: python python-2.7 dictionary-comprehension setdefault