[英]Getting a map() to return a list instead of map object in Python 3.x
[英]Why does map return a map object instead of a list in Python 3?
我對了解Python 3.x的新語言設計感興趣。
我確實喜歡Python 2.7中的功能map
:
Python 2.7.12
In[2]: map(lambda x: x+1, [1,2,3])
Out[2]: [2, 3, 4]
但是,在Python 3.x中,情況發生了變化:
Python 3.5.1
In[2]: map(lambda x: x+1, [1,2,3])
Out[2]: <map at 0x4218390>
我了解操作方法,但是找不到原因。 語言設計師為什么要做出這種選擇,我認為這會帶來很多痛苦。 這是否會困擾開發人員堅持列出理解?
IMO,清單自然可以認為是函子 ; 有人以某種方式想到了我:
fmap :: (a -> b) -> f a -> f b
我想,為什么地圖仍然存在的話 ,當理由發電機表情也是存在的,是它可以采取多個迭代論點,都環繞在並傳遞給函數:
>>> list(map(min, [1,2,3,4], [0,10,0,10]))
[0,2,0,4]
這比使用zip稍微容易一些:
>>> list(min(x, y) for x, y in zip([1,2,3,4], [0,10,0,10]))
否則,它根本不會在生成器表達式上添加任何內容。
由於它返回一個迭代器,因此省略了將完整大小列表存儲在內存中的操作。 這樣您以后就可以輕松地遍歷它,而不會給內存造成任何痛苦。 在滿足您的條件之前,您甚至可能不需要完整的列表,但只需要一部分即可。
您會發現此文檔很有用,迭代器很棒。
表示數據流的對象。 重復調用迭代器的
__next__()
方法(或將其傳遞給內置函數next()
)將返回流中的后續項。 如果沒有更多數據可用,則會引發StopIteration
異常。 此時,迭代器對象已用盡,對其__next__()
方法的任何進一步調用都只會再次引發StopIteration
。 迭代器必須具有返回迭代器對象本身的__iter__()
方法,因此每個迭代器也是可迭代的,並且可以在接受其他可迭代的大多數地方使用。 一個值得注意的例外是嘗試多次迭代遍歷的代碼。 每當您將容器對象(例如list
)傳遞給iter()
函數或在for循環中使用它時,都會產生一個新的新迭代器。 使用迭代器嘗試執行此操作將僅返回上一次迭代過程中使用的相同的耗盡迭代器對象,使其看起來像一個空容器。
Guido 在這里回答這個問題:“ 因為創建列表只是浪費 ”。
他還說正確的轉換是使用常規的for
循環。
將map()
從2轉換為3可能不僅僅是在其周圍貼上list( )
的簡單情況。 圭多還說:
“如果輸入序列的長度不相等,則map()
將在最短序列的終止處停止。要與Python 2.x中的map()
完全兼容,請將序列包裝在itertools.zip_longest()
,例如
map(func, *sequences)
變成
list(map(func, itertools.zip_longest(*sequences)))
”
在Python 3中,許多函數(不僅是map
還包括zip
, range
和其他函數)返回一個迭代器而不是完整列表。 您可能想要一個迭代器(例如,避免將整個列表保存在內存中),或者您想要一個列表(例如,能夠建立索引)。
但是,我認為更改Python 3的主要原因是,雖然使用list(some_iterator)
將迭代器轉換為列表很簡單,但反向等效iter(some_list)
卻無法達到預期的結果,因為完整列表已經被建立並保存在內存中。
例如,在Python 3中list(range(n))
可以很好地工作,因為構建range
對象然后將其轉換為列表幾乎不需要花費什么。 但是,在Python 2中, iter(range(n))
不會保存任何內存,因為完整列表是在構建迭代器之前由range()
構造的。
因此,在Python 2中,需要使用單獨的函數來創建迭代器而不是列表,例如imap
表示map
(盡管不是很等效 ), xrange
表示range
, izip
表示zip
。 相比之下,Python 3僅需要一個函數,因為list()
調用會在需要時創建完整列表。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.