【发布时间】:2018-03-09 22:41:56
【问题描述】:
我已经创建了字典d。我只想更改某种类型的值。例如,我想用它们的长度替换字符串。
执行此操作的无聊方法是使用 for 循环:
for k,v in d.items():
if isinstance(v, str):
d[k] = len(v)
但是循环不是很慢吗?
它可以通过理解来完成。我认为这相当于上面的:
d = {k: len(v) if isinstance(v, str) else v for k,v in d.items()}
我用地图试过了,但这些都不起作用(显然是因为我不懂something about tuple unpacking in Python 3):
d = dict(map(lambda k,v: (k, len(v) if isinstance(v, str) else v), d.items()))
d = dict(map(lambda (k,v): (k, len(v) if isinstance(v, str) else v), d.items()))
这似乎可行,但它变得又大又丑:
dict(map(lambda kv: (kv[0], len(kv[1]) if isinstance(kv[1], str) else kv[1]), d.items()))
这种操作好像很常见,但是我找不到具体的答案。
什么是正确、Pythonic 和高性能的方法?
【问题讨论】:
-
您的
dict理解是正确的,恕我直言是实现这一目标的pythonic 方式。 -
for 循环不会创建新字典,只会替换那些以字符串为值的项目。理解创建一个新字典并设置每个元素,包括那些具有非字符串作为值的元素。您问循环是否很慢,但是当您需要处理一组值中的每个项目时,别无选择。理解不是魔术。它也是一个循环。
-
@PaulCornelius 哇,不是魔术吗?不,我只是想也许它在幕后更优化。所以
for循环可能更快?还是使用更少的内存? -
在其他条件相同的情况下,您总是更喜欢理解而不是 for 循环。但是,如果您的字典中有一百万个项目并且其中只有两个是字符串,则推导式将执行 999,998 个不必要的副本,而 for 循环只会替换 2 个值。所以像 comprehension=fast, for loop=slow 这样的规则太简单了。
-
@P1h3r1e3d13 在这种情况下,for-loop 肯定会使用更少的内存,实际上,它使用的内存量是恒定的,而不是需要 O(n) 内存的理解。但即使你的循环完全等同于理解,即它会构建一个新的dict而不是修改一个现有的,那么你也只能期望边际速度增益。理解应该是首选,主要是为了可读性。
标签: python dictionary for-loop dictionary-comprehension