for循环和next方法迭代生成器,满足我的预期就OK了
Posted
技术标签:
【中文标题】for循环和next方法迭代生成器,满足我的预期就OK了【英文标题】:For loop and next method to iterate the generator, it is OK that fulfill my expectation 【发布时间】:2015-01-14 09:22:35 【问题描述】:我测试了这些方法的性能:
def gen_iter():
for _ in xrange(100000):
yield _
def for_perf():
it = gen_iter()
for _ in it:
pass
def next_perf():
it = gen_iter()
try:
while True:
_ = it.next()
except StopIteration:
pass
这些是测试结果(for_next_perf是模块名):
python -m timeit "from for_next_perf import for_perf; for_perf()"
100 loops, best of 3: 13.4 msec per loop
python -m timeit "from for_next_perf import next_perf; next_perf()"
10 loops, best of 3: 39 msec per loop
Line # Mem 使用增量行内容
7 8.527 MiB 0.000 MiB @profile
8 def for_perf():
9 8.531 MiB 0.004 MiB it = gen_iter()
10 8.582 MiB 0.051 MiB for _ in it:
11 8.582 MiB 0.000 MiB pass
Line # Mem 使用增量行内容
13 8.508 MiB 0.000 MiB @profile
14 def next_perf():
15 8.512 MiB 0.004 MiB it = gen_iter()
16 8.562 MiB 0.051 MiB while True:
17 8.562 MiB 0.000 MiB try:
18 8.562 MiB 0.000 MiB _ = it.next()
19 8.562 MiB 0.000 MiB pass
20 8.551 MiB -0.012 MiB except StopIteration:
21 8.551 MiB 0.000 MiB break
抱歉,我之前犯了一个错误,忘记为那个生成器循环。现在它满足了我的期望。
但是,我发现在我的工作中使用for_perf()
样式的运行时内存使用量正在增加。呵呵,可能是我的错,我应该再仔细测试一下我的代码。
【问题讨论】:
_ = it.next()
从生成器中获取第一个值,然后函数返回。当然它会比从生成器获取 all 值更快。
是的,您必须将while
带入try
【参考方案1】:
根据@vaultah 的评论,您正在比较两种不同的操作。您在第一个代码 sn-p 中完全使用了生成器,而在第二个代码中只从生成器对象中取出第一个元素。
def next_perf():
it = gen_iter()
while True:
try:
_ = it.next()
except StopIteration:
raise StopIteration
# In working code you will break rather than re-raise. Not sure how the time changes if you re-raise, I assumed it won't change too much (loop terminates either way), but that's a big assumption.
如果要执行与第一个相同的操作,第二个代码应该是这样的,并且几乎肯定会比其他版本花费更长的时间。
顺便说一句,yield _
的做法真的很糟糕。仅将 _
用于您实际上什么都不做的丢弃值。
【讨论】:
您希望while
循环在 try
或使用break
在StopIteration
被捕获时结束循环。无论哪种方式,您都不想再次引发异常。以上是关于for循环和next方法迭代生成器,满足我的预期就OK了的主要内容,如果未能解决你的问题,请参考以下文章