gpt4 book ai didi

python 反向迭代器与生成器行为

转载 作者:太空宇宙 更新时间:2023-11-03 13:40:39 24 4
gpt4 key购买 nike

为什么删除列表中的项目会破坏 reversed 对象?它不会破坏 gen-exprs,追加或修改列表不会破坏 reversed 对象,而且它显然指向原始对象,所以为什么不能给出截断版本?也许一些例子可以说明:

l = [1, 2, 3, 4]
r = reversed(l)
g = (i for i in l)
l.pop() # returns 4
l # returns [1, 2, 3]

for i in g:print(i) # prints 1 2 3 (on separate lines)
for i in r:print(i) # prints ...nothing

r = reverse(l)
g = (i for i in l)
l[1] = 4
for i in g:print(i) # prints 1 4 3 (on separate lines)
for i in r:print(i) # prints 3 4 1 (on separate lines)

r = reversed(l)
g = (i for i in l)
l.append(5)
l # returns [1, 4, 3, 5] just to keep you on your toes

for i in g:print(i) # prints 1 4 3 5 (on separate lines)
for i in r:print(i) # prints 3 4 1 (on separate lines)

所以 - 如果 genexpr 足够聪明,可以指向对象,并且只响应对象发生的变化,为什么不反转?它显然不会制作副本,否则它不会在第一种情况下“失败”,也不会在第二种情况下选择 4。所以它必须指向对象。为什么它不能从索引 -1 开始并向后工作?

最佳答案

当您调用 reversed() 时在列表对象上,创建一个专用的反向列表迭代器对象;此对象“知道”如何以相反的顺序有效地遍历列表一次

为此,当创建对象时,存储列表中的最后一个索引。对于您的列表 l , 即 3 (第 4 个元素,从 0 开始计数)。当您随后进行迭代时,会生成该索引处的元素,并且索引会递减,直到 IndexError。被提出*

该对象的 Python 实现如下所示:

class reversed_list_iterator(object):
def __init__(self, lst):
self.index = len(lst) - 1
self.lst = lst

def __iter__(self):
return self

def __next__(self):
try:
result = self.lst[self.index]
except IndexError:
self.lst = [] # switch to permanently stopped state
raise StopIteration
self.index -= 1
return result

现在,当您删除 该元素时,迭代器会退出,因为没有l[3]。 , 一个 IndexError 在那里然后被提升,迭代结束。

在您的第二个示例中,在创建反向迭代器时,最后一个索引是 2 .然后您添加 到列表中,但迭代从 l[2] 开始,它仍然存在。

反向列表迭代器不能使用相对索引,因为正如您所发现的,迭代器相对容忍添加到列表中的元素。相对索引将重复值。


* actual C implementation边界测试 0 <= index < len(self.lst)而不是捕获 IndexError , 但原理是一样的。

关于python 反向迭代器与生成器行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32000312/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com