[英]Why is the Python version of itertools.islice not working?
我注意到itertools
文档中的Recipes部分有一些有用的代码,比如consume
,但我发现了一个问题。
from itertools import islice
numbers = iter(range(10))
for i in numbers:
print i
next(islice(numbers, 3, 3), None)
上面的代码工作正常,打印[0,4,8]
, next(islice(numbers, 3, 3), None)
技巧取自consume
配方。
我们可以看到islice
在这里发挥了重要作用。 但是,当我用该函数的python文档中提供的代码替换itertools.islice
时,代码无法正常工作:
#from itertools import islice
def islice(iterable, *args):
# islice('ABCDEFG', 2) --> A B
# islice('ABCDEFG', 2, 4) --> C D
# islice('ABCDEFG', 2, None) --> C D E F G
# islice('ABCDEFG', 0, None, 2) --> A C E G
s = slice(*args)
it = iter(xrange(s.start or 0, s.stop or 200, s.step or 1))
nexti = next(it)
for i, element in enumerate(iterable):
if i == nexti:
yield element
nexti = next(it)
numbers = iter(range(10))
for i in numbers:
print i
next(islice(numbers, 3, 3), None)
输出与上面的输出不同; 打印范围内的所有数字,并且islice()
消耗行似乎不执行任何操作。
任何人都可以解释为什么这是和islice
在这里工作的方式?
切片的start和stop参数相等,因此对xrange的next(it)
调用会引发StopIteration
:
>>> s = slice(3, 3, None)
>>> it = iter(xrange(s.start or 0, s.stop or 200, s.step or 1))
>>> next(it)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
并且slice()
生成器函数立即终止。 这只是合乎逻辑的,在这种情况下, xrange()
函数不会产生任何数字。
itertools
文档是说明性的 ,并不意味着完整。 您已经找到了一个边缘例,其中示例Python代码的工作方式与C实现的工作方式不同。
为了使Python代码也适用于这种情况,请捕获StopIteration
异常,并在循环中显式测试edgecase:
def islice(iterable, *args):
s = slice(*args)
it = iter(xrange(s.start or 0, s.stop or 200, s.step or 1))
try:
nexti = next(it)
consume = False
except StopIteration:
if s.start < 1:
return
nexti = s.start - 1
consume = True
for i, element in enumerate(iterable):
if i == nexti:
if consume:
return
yield element
nexti = next(it)
Python示例代码使用slice()
对象使代码更紧凑,更易于阅读; C代码执行自己的启动,停止和步骤解析,并处理计数本身而不是委托给xrange()
,因此不会遇到此边缘情况。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.