Python 的迭代器與zip詳解
首先拋出一個困擾本人許久的問題:
nums = [1,2,3,4,5,6] numsIter = iter(nums) for _ in zip(*[numsIter]*3): print(_) print(list(numsIter))
則控制臺輸出如何?
關于迭代器
1.對于支持迭代的集合對象,可以創(chuàng)建其迭代器對象。迭代器對象儲存了可迭代對象的地址和遍歷的位置,迭代器對象從集合的第一個元素開始訪問,所有的元素被訪問完迭代器被消耗(仍然占地址),但清空儲存的信息(即地址和遍歷位置)。使用list()函數(shù)或 * 操作符可以獲取所有遍歷的內容,結束后迭代器被消耗。
nums = [1,2,3,4,5,6] numsIter = iter(nums) print(nums) print(list(nums)) print(nums) print(list(nums))
輸出為:
<list_iterator object at 0x00000205944619D0>
[1,2,3,4,5,6]
<list_iterator object at 0x00000205944619D0>
[]
第二次鍵入 print(list(nums)) 時輸出為空,因為迭代器對象已經找不到地址了。
2.復制迭代器對象,得到的是一個迭代器對象的引用,即地址,而不是新建一個迭代器。因此,遍歷位置是共同的。
nums = [1,2,3,4,5,6] numsIter = iter(nums) numsIter_list = [numsIter] * 2 print(numsIter) print(numsIter_list) for _ in numsIter_list: print(next(_))
輸出為:
<list_iterator object at 0x0000020594445A00>
[<list_iterator object at 0x0000020594445A00>, <list_iterator object at 0x0000020594445A00>]
1
2
關于zip
1.在創(chuàng)建zip對象時,并沒有直接生成新數(shù)據(jù),而是存儲了要操作對象的迭代器,當真正需要的時候,才通過迭代器遍歷數(shù)據(jù)。因此,當使用list()函數(shù)或 * 操作符解壓zip對象時,當然是會消耗掉儲存的迭代器,使得再一次解壓時返回為空。
P = [1,2,3] Q = [4,5,6] PQ_zip = zip(P,Q) print(PQ_zip) print(list(PQ_zip)) print(list(PQ_zip))
輸出為:
<zip object at 0x0000020594520140>
[(1, 4), (2, 5), (3, 6)]
[]
2.zip之所以能work,就是利用了迭代器儲存的遍歷位置,逐一地獲取數(shù)據(jù),直到其中一個迭代器被消耗掉。文首的問題就是最好的例子 。
nums = [1,2,3,4,5,6] numsIter = iter(nums) for _ in zip(*[numsIter]*3): print(_) print(list(numsIter))
輸出為:
(1, 2, 3)
(4, 5, 6)
[]
可以看見,實現(xiàn)的功能是把單行數(shù)據(jù)變成了3列2行。這是怎么做到的呢?執(zhí)行zip時,依次訪問三個同樣的迭代器,每次訪問,迭代器的遍歷位置都會加1,于是第一輪結束后zip獲取了(1,2,3),同理第二輪則獲取了(4,5,6),隨后迭代器被消耗。第三輪zip對象已經沒有迭代器可用,于是結束執(zhí)行。最后 print(list(numsIter)) 發(fā)現(xiàn)迭代器確實已經被消耗。
3.當使用 print 顯示迭代器或zip對象的內容時,list() 和 * 操作符幾乎沒有區(qū)別。但上述例子中,只能用 * 操作符來實現(xiàn),因為 * 操作符實際上是返回對象的地址和遍歷位置,而 list() 會直接遍歷完畢從而消耗掉迭代器。
nums = [1,2,3] numsIter = iter(nums) print(numsIter) for _ in zip(list(numsIter)*3): print(_) print(list(numsIter))
輸出為:
<list_iterator object at 0x0000020594445B80>
(1,)
(2,)
(3,)
(1,)
(2,)
(3,)
(1,)
(2,)
(3,)
[]
總結:
在熟悉迭代器和zip()函數(shù)的同時,掌握了一個將一維數(shù)據(jù)變?yōu)槎S數(shù)據(jù)的方法。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注本站的更多內容!
版權聲明:本站文章來源標注為YINGSOO的內容版權均為本站所有,歡迎引用、轉載,請保持原文完整并注明來源及原文鏈接。禁止復制或仿造本網(wǎng)站,禁止在非www.sddonglingsh.com所屬的服務器上建立鏡像,否則將依法追究法律責任。本站部分內容來源于網(wǎng)友推薦、互聯(lián)網(wǎng)收集整理而來,僅供學習參考,不代表本站立場,如有內容涉嫌侵權,請聯(lián)系alex-e#qq.com處理。