she*_*per 33 python python-3.x
我有以下代码:
s = [1,2,3]
t = reversed(s)
for i in t:
print(i)
# output: 3,2,1
Run Code Online (Sandbox Code Playgroud)
如果我从s(原始)中弹出一个元素,那么t(反向)将被清空:
s = [1,2,3]
t = reversed(s)
s.pop()
for i in t:
print(i)
# expected output: 2, 1
# actual output (nothing):
Run Code Online (Sandbox Code Playgroud)
为什么会发生这种情况?
M Z*_*M Z 30
看看GitHub上的cpython代码,我们可以直观地了解为什么它不再起作用。
返回的迭代器本质上需要知道最后一个索引的位置和数组的长度。如果数组的大小发生变化,迭代器将不再工作。
这也不会产生正确的结果,但迭代器确实运行:
s = [1,2,3]
t = reversed(s)
s.append(4)
for i in t:
print(i)
# output: [3, 2, 1]
Run Code Online (Sandbox Code Playgroud)
s = [1,2,3]
t = reversed(s)
s.pop()
s.append(4)
for i in t:
print(i)
# output: [4, 2, 1]
Run Code Online (Sandbox Code Playgroud)
它仍然有效!
所以有一个内部检查来查看最后一个索引是否仍然有效,如果是,它是一个简单的 for 循环到索引 0。
如果它不起作用,迭代器返回空。
在该列表上调用reversed返回一个迭代器,它是一个特殊的对象,允许您在原始列表上以相反的顺序迭代,它不是一个新列表,只能一次性使用
>>> s= [1,2,3]
>>> t = reversed(s)
>>> t
<list_reverseiterator object at 0x00000261BE8F0C40>
>>> list(t)
[3, 2, 1]
>>> list(t)
[]
>>>
Run Code Online (Sandbox Code Playgroud)
并且因为这个迭代器引用了原始列表,所以当您稍后迭代迭代器时,它的任何更改都会反映出来。
更新
特别是正如 MZ 所解释的那样,如果这种变化使得列表的状态与创建迭代器时的状态不同,如果大小减小,您将一无所获,或者如果增加则列表的不完整版本
>>> s= [1,2,3]
>>> t = reversed(s)
>>> s.insert(0,23)
>>> s
[23, 1, 2, 3]
>>> list(t)
[2, 1, 23]
>>> t = reversed(s)
>>> s.append(32)
>>> list(t)
[3, 2, 1, 23]
>>> s
[23, 1, 2, 3, 32]
>>> t = reversed(s)
>>> s.pop()
32
>>> list(t)
[]
>>>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1535 次 |
| 最近记录: |