使用列表理解和生成器理解时,我得到不同的输出。这是预期的行为还是错误?
请考虑以下设置:
all_configs = [
{'a': 1, 'b':3},
{'a': 2, 'b':2}
]
unique_keys = ['a','b']
如果再运行以下代码,则会得到:
print(list(zip(*( [c[k] for k in unique_keys] for c in all_configs))))
>>> [(1, 2), (3, 2)]
# note the ( vs [
print(list(zip(*( (c[k] for k in unique_keys) for c in all_configs))))
>>> [(2, 2), (2, 2)]
这是在python 3.6.0上:
Python 3.6.0 (default, Dec 24 2016, 08:01:42)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
在列表理解中,对表达式进行热切评估。在生成器表达式中,仅根据需要查找它们。
因此,当生成器表达式遍历时for c in all_configs
,它引用c[k]
但仅c
在循环完成后查找,因此它仅对两个元组使用最新值。相比之下,列表推导会立即进行评估,因此它将创建第一个值为的c
元组和第二个值为的元组c
。
考虑这个小例子:
>>> r = range(3)
>>> i = 0
>>> a = [i for _ in r]
>>> b = (i for _ in r)
>>> i = 3
>>> print(*a)
0 0 0
>>> print(*b)
3 3 3
创建时a
,解释器立即创建该列表,i
并在对其求值后立即查找其值。创建时b
,解释器只是设置了该生成器,实际上并没有对其进行迭代并查找i
。这些print
电话告诉解释器评估这些对象。a
已经作为完整列表存在于内存中,具有旧值i
,但是b
在那时进行了评估,当它查找的值时i
,便找到了新值。
问题内容: 什么时候应该使用生成器表达式,什么时候应该在中使用列表推导? 问题答案: John的答案很好(当你要迭代多次时,列表理解会更好)。但是,还应注意,如果要使用任何列表方法,都应使用列表。例如,以下代码将不起作用: 基本上,如果你要做的只是迭代一次,则使用生成器表达式。如果你要存储和使用生成的结果,那么列表理解可能会更好。 由于性能是选择彼此的最常见原因,所以我的建议是不要担心它,而只选择
问题内容: 我正在回答这个问题,在这里我更喜欢生成器表达式并使用了它,我认为这样做会更快,因为生成器不需要先创建整个列表: Levon在解决方案中使用了列表理解功能, 但是当我做这些LC的时间结果比生成器快时: 然后我增加了列表的大小,并再次计时: 这次搜索生成器的时间比LC快,但是当我搜索中间元素(11)和最后一个元素时,LC再次击败了生成器表达式,我不明白为什么? 问题答案: 扩展Paulo的
问题内容: 我碰巧发现自己有一个基本的过滤需求:我有一个列表,并且必须按项目的属性对其进行过滤。 我的代码如下所示: 但是后来我想,这样写会更好吗? 它更具可读性,并且如果需要性能,则可以取出以获得某些东西。 问题是:使用第二种方法是否有任何警告?有任何性能差异吗?我是否完全想念,应该以另一种方式来做到这一点(例如,使用而不是)吗? 问题答案: 我发现列表理解比 清晰得多,但请使用任何你更容易理解
问题内容: 我想编写一些测试来分析python中不同操作的效率,即字典理解和dict生成器的比较。 为了验证这一点,我想我会尝试一个简单的示例:使用字典计算列表中的单词数。 现在,我知道您可以使用(按照这里的答案:如何计算Python中列表项的出现?)进行此操作,但是我的目标是测试内存性能。 一种“长手”方法是在基本循环中进行操作。 结果: 然后我在字典理解中尝试执行相同操作时有点卡住: 我收到一
我使用的是Windows10i7第四代笔记本电脑,内存为8GB。 我想找出从1到100000000的数字之和可以被5整除。 我正在尝试在Raku REPL中运行此代码: 代码运行了45分钟,仍然没有输出。我该如何克服呢? 在这种情况下,如何应用并发呢?我认为以上问题可以通过并发或任务并行来解决!!
问题内容: 加入列表: join 必须采取迭代。 显然,join的论点是,这是一个列表理解。 看这个: 现在,join的参数为,但结果相同。 为什么?是否str还会产生列表或可迭代项? 问题答案: 这称为生成器表达式,并在PEP 289中进行了说明。 生成器表达式和列表理解之间的主要区别在于前者不在内存中创建列表。 请注意,还有第三种编写表达式的方法: