簡體   English   中英

為什么從原始列表中彈出會使 reversed(original_list) 為空?

[英]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 和數組的長度。 如果數組的大小發生變化,迭代器將不再工作。

測試 1:增加數組長度

這也不會產生正確的結果,但迭代器會運行:

s = [1,2,3]
t = reversed(s)
s.append(4)

for i in t:
    print(i)
# output: [3, 2, 1]

測試 2:減少,然后增加長度

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM