[英]Why does popping from the original list make reversed(original_list) empty?
我有以下代碼:
s = [1,2,3]
t = reversed(s)
for i in t:
print(i)
# output: 3,2,1
如果我從s
(原始)中彈出一個元素,則t
(反轉)被清空:
s = [1,2,3]
t = reversed(s)
s.pop()
for i in t:
print(i)
# expected output: 2, 1
# actual output (nothing):
為什么會這樣?
看一下GitHub上的cpython
代碼,我們可以直觀地了解它為什么不再起作用。
返回的迭代器本質上需要知道最后一個索引的 position 和數組的長度。 如果數組的大小發生變化,迭代器將不再工作。
這也不會產生正確的結果,但迭代器會運行:
s = [1,2,3]
t = reversed(s)
s.append(4)
for i in t:
print(i)
# output: [3, 2, 1]
s = [1,2,3]
t = reversed(s)
s.pop()
s.append(4)
for i in t:
print(i)
# output: [4, 2, 1]
它仍然有效!
所以有一個內部檢查來查看最后一個索引是否仍然有效,如果是,它是一個簡單的 for 循環到索引 0。
如果它不起作用,則迭代器返回空。
調用reversed
返回該列表的迭代器,這是一個特殊的 object 允許您以相反的順序迭代原始列表,它不是一個新列表,只能一次性使用
>>> s= [1,2,3]
>>> t = reversed(s)
>>> t
<list_reverseiterator object at 0x00000261BE8F0C40>
>>> list(t)
[3, 2, 1]
>>> list(t)
[]
>>>
並且因為這個迭代器引用了原始列表,所以當您稍后迭代迭代器時,它的任何更改都會反映出來。
更新
特別是正如 MZ 解釋的那樣,如果這種變化使得列表的 state 與創建迭代器時不同,如果大小減小或列表的不完整版本增加,您將一無所獲
>>> 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)
[]
>>>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.