小能豆

执行生成器表达式最具 Python 风格的方式是什么?

py

Python 的越来越多的功能都转向“惰性执行”,例如生成器表达式和其他类型的迭代器。然而,有时我发现自己想要运行一行“for”循环,只是为了执行一些操作。

要使循环真正执行,最具 Python 特色的事情是什么?

例如:

a = open("numbers.txt", "w")
(a.write ("%d " % i) for i in xrange(100))
a.close()

不是实际的代码,但你明白我的意思。如果我使用列表生成器,则会产生副作用,即创建一个填充有“无”的 N 长度列表。

目前我的做法是使用表达式作为调用“any”或“all”的参数。但我想找到一种不依赖于循环中执行的表达式结果的方法 - “any”和“all”都可以停止依赖于所求表达式的结果。

需要明确的是,这些是我已经知道的方法,每种方法都有其缺点:

[a.write ("%d " % i) for i in xrange(100))]

any((a.write ("%d " % i) for i in xrange(100)))

for item in (a.write ("%d " % i) for i in xrange(100)): pass

阅读 14

收藏
2024-11-17

共1个答案

小能豆

为了在不创建不必要数据结构的情况下执行循环,最“Pythonic”的方法是使用显式循环。但如果你希望一种更简洁的方法而避免副作用的列表生成式或过于冗长的显式循环,可以考虑以下方式:


推荐方法:使用 collections.deque

collections.deque 提供了一个很好的方式通过“消费”生成器表达式来执行操作而不创建额外数据。

from collections import deque

a = open("numbers.txt", "w")
deque((a.write("%d " % i) for i in range(100)), maxlen=0)
a.close()
  • 为什么使用 deque:
  • 它会消耗传递给它的迭代器,而不会创建额外的存储(maxlen=0 确保没有额外的存储)。
  • deque 的构造是高效的,适合这种模式。

方法解释

1. 使用 for 循环

这是最简单、直观的方法。

a = open("numbers.txt", "w")
for i in range(100):
    a.write("%d " % i)
a.close()
  • 优点:明确,易读。
  • 缺点:不够“短”。

2. 使用生成器表达式配合 anyall

虽然这是一个常见的技巧,但它依赖于表达式返回的布尔值,这可能不直观。

a = open("numbers.txt", "w")
any(a.write("%d " % i) for i in range(100))  # 或者 all()
a.close()
  • 缺点:anyall 在特定条件下会提前短路(例如遇到 TrueFalse),这可能导致某些生成器项没有被执行。

3. 使用 list(不推荐)

这会创建一个包含 None 的列表,浪费内存。

a = open("numbers.txt", "w")
[a.write("%d " % i) for i in range(100)]
a.close()
  • 缺点:生成了无用的列表。

最佳实践建议

如果代码的可读性优先,直接使用显式的 for 循环。如果你追求简洁和 Pythonic 的方法,collections.deque 是一个值得推荐的解决方案。

2024-11-17