是否有更复杂的语法写作方式?
gen = (i for i in xrange(10))
index = 5
for i, v in enumerate(gen):
if i is index:
return v
Run Code Online (Sandbox Code Playgroud)
生成器应该有一个gen[index]
表达式,作为一个列表,但在功能上与上面的代码完全相同似乎是很自然的.
cob*_*bal 55
一种方法是使用 itertools.islice
>>> gen = (x for x in range(10))
>>> index = 5
>>> next(itertools.islice(gen, index, None))
5
Run Code Online (Sandbox Code Playgroud)
Mar*_*ers 15
您可以使用count
作为示例生成器来执行此操作:
from itertools import islice, count
next(islice(count(), n, n+1))
Run Code Online (Sandbox Code Playgroud)
lov*_*soa 11
我认为最好的方法是:
next(x for i,x in enumerate(it) if i==n)
Run Code Online (Sandbox Code Playgroud)
(it
你的迭代器在哪里n
,索引在哪里)
它不需要您添加导入(如使用 的解决方案itertools
),也不需要一次性将迭代器的所有元素加载到内存中(如使用 的解决方案list
)。
注意 1:StopIteration
如果您的迭代器少于 n 个项目,此版本会引发错误。如果你想得到None
,你可以使用:
next((x for i,x in enumerate(it) if i==n), None)
Run Code Online (Sandbox Code Playgroud)
注 2: 调用中没有括号next
。这不是列表推导式,而是生成器推导式,它不会消耗原始迭代器超过其第 n 个元素。
我反对将生成器视为列表的诱惑。简单但幼稚的方法是简单的单行:
gen = (i for i in range(10))
list(gen)[3]
Run Code Online (Sandbox Code Playgroud)
但请记住,生成器不像列表。他们不会在任何地方存储他们的中间结果,所以你不能倒退。我将在 python repl 中用一个简单的例子来演示这个问题:
>>> gen = (i for i in range(10))
>>> list(gen)[3]
3
>>> list(gen)[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
Run Code Online (Sandbox Code Playgroud)
一旦您开始通过生成器获取序列中的第 n 个值,生成器现在处于不同的状态,再次尝试获取第 n 个值将返回不同的结果,这可能会导致您的错误代码。
让我们看另一个例子,基于问题中的代码。
人们最初会期望以下内容打印4
两次。
gen = (i for i in range(10))
index = 4
for i, v in enumerate(gen):
if i == index:
answer = v
break
print(answer)
for i, v in enumerate(gen):
if i == index:
answer = v
break
print(answer)
Run Code Online (Sandbox Code Playgroud)
但是在 repl 中输入这个,你会得到:
>>> gen = (i for i in range(10))
>>> index = 4
>>> for i, v in enumerate(gen):
... if i == index:
... answer = v
... break
...
>>> print(answer)
4
>>> for i, v in enumerate(gen):
... if i == index:
... answer = v
... break
...
>>> print(answer)
9
Run Code Online (Sandbox Code Playgroud)
祝你好运追踪那个错误。
编辑:
正如所指出的,如果生成器是无限长的,您甚至无法将其转换为列表。表达式list(gen)
永远不会结束。
有一种方法可以在无限生成器周围放置一个懒惰评估的缓存包装器,使其看起来像一个无限长的列表,您可以随意索引,但这值得它自己的问题和答案,并且会对性能产生重大影响。
归档时间: |
|
查看次数: |
25286 次 |
最近记录: |