您好,登錄后才能下訂單哦!
今天小編給大家分享一下Python迭代工具有哪些及怎么使用的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
它的功能比乍看起來要強大的多。
使用range()
的第一個要點是理解參數:range(start, stop)
. start
代表我們從start數字開始計數,包含start這個數字;stop
代表我們在到達stop數字后停止計數,但不包括stop數字!
所以,如果我們有range(1, 10)
,就會得到[1, 2, 3, 4, 5, 6, 7, 8, 9]
。開始于1
,但不能到10
。
如果我們想包含10
在我們的序列中,我們需要range(1, 11)
: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
。
順便說一句,如果我們只指定一個參數,例如range(10)
,它將假定范圍的開始是0
。在這種情況下,我們會得到[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
. 當range()
用于控制傳統的 for 循環時,你會經常看到以這種方式使用它。
我最喜歡range()
的技巧是它的可選第三個參數:當你指定 range(start, stop, step)
時,該step
參數允許你每次增加大于1
的值。
可以用在實現打印出 前100個7 的所有倍數,從7
自身到700
,包括在內:range(7, 701, 7)
會這樣做。(請注意,我最后指定了701
,以確保包括700
在內。)
也可以用在打印所有小于 100的奇數: range(1, 100, 2)
。
如果你正在嘗試使用range,打印出7的所有倍數,你可能會注意到結果并沒有達到你的預期:
sevens = range(7, 701, 7) print(sevens)
print 命令打印文字短語range(7, 701, 7)
。發現并不是我們想要的!
請記住,range()
返回一個類似于迭代器的對象(python 2x返回的是列表)。要將其完全存儲為列表,我們需要通過將其包裝在函數list()
中來將其轉換為列表:
sevens = list(range(7, 701, 7)) print(sevens)
現在輸出就是我們想要的——前100個 7 的倍數的列表!
在我們進入所有這些新的迭代優點之前,我想向你介紹擴展索引符號,它使我們能夠更強大地從有序容器中選擇元素,例如列表。
說到列表,來看看下面這個:
dossiers = ['Sir Vile', 'Dr. Belljar', 'Baron Grinnit', 'Medeva', 'General Mayhem', 'Buggs Zapper', 'Jacqueline Hyde', 'Jane Reaction', 'Dee Cryption']
不管你是否意識到,你已經知道正常的索引符號。
print(dossiers[1]) >>> Dr. Belljar
這返回了容器的第二個元素(索引1
) 。dossiers
很簡單,對吧?幾乎所有語言都提供這種行為。
那么,如果我們想要第二個和第三個元素呢?
print(dossiers[1:3]) >>> ['Dr. Belljar', 'Baron Grinnit']
剛才發生了什么?在擴展索引表示法中,我們有三個參數,用冒號分隔:start
、stop
和step
。嘿,看起來很熟悉對吧?這些是range()
使用的相同參數!它們的工作方式也完全相同。(當然,我們在上面的示例中省略了第三個參數 [ step
]。)
請注意,該示例打印出Dr. Belljar
(index 1
) 和Baron Grinnit
(index 2
),但不是 Medeva
,因為stop
參數被迫停止了。
千萬要注意,start
一定要小于 stop
,你才能得到結果!不過有一個例外,我們稍后會談到。
現在,如果你想要從第二個開始的所有其他元素怎么辦?
print(dossiers[1::2]) >>> ['Dr. Belljar', 'Medeva', 'Buggs Zapper', 'Jane Reaction']
你會注意到我們沒有指定stop
. 因為我們其實不需要!擴展索引符號允許你省略任何參數,只要你有冒號來分隔開。由于省略了第二個參數,我們只是將多余的:
放在它本來應該的位置之后。
擴展索引符號使(start, stop, step)
邏輯更進一步,允許你反向分割!一開始這有點繞腦筋,但是請堅持住……
print(dossiers[-1])
打印出列表中的最后一項。負數代表從列表末尾開始計數!這感覺有點奇怪,因為我們習慣于從0
索引開始計數,但負零并不是真正的有意義的數,所以我們從-1
開始。
鑒于此,我們如何打印最后三個項目?我們可能會這樣嘗試,但它實際上不起作用......
print(dossiers[-1:-4]) >>> []
這將返回一個空列表。為什么?請記住,start
必須小于 stop
,即使在使用負索引時也是如此。所以,我們必須把-4
作為我們的start
,因為-4 < -1
。
print(dossiers[-4:-1]) >>> ['Buggs Zapper', 'Jacqueline Hyde', 'Jane Reaction']
這更接近了,但仍然存在問題。Dee Cryption
是我們的最后一個元素,它在哪里呢?記住,stop
是停止計數的數字,且不包含當前數字。但我們不能只用dossiers[-4]
,因為那只會給我們Buggs Zapper
。并且dossiers[-4:-0]
是無效。
要解決這個問題的方法就是,告訴 Python 我們明確省略了第二個參數:在我們的第一個參數后面加上一個冒號!
print(dossiers[-4:]) >>> ['Buggs Zapper', 'Jacqueline Hyde', 'Jane Reaction', 'Dee Cryption']
現在我們得到了最后一個元素。如果我們想要最后三個,那就把-4
改為-3
......
print(dossiers[-3:]) >>> ['Jacqueline Hyde', 'Jane Reaction', 'Dee Cryption']
如果我們在第三個參數step
中輸入一個負數,你認為會發生什么?讓我們嘗試-1
在它前面加上兩個冒號,表示我們想要整個列表。
print(dossiers[::-1]) >>> ['Dee Cryption', 'Jane Reaction', 'Jacqueline Hyde', 'Buggs Zapper', 'General Mayhem', 'Medeva', 'Baron Grinnit', 'Dr. Belljar', 'Sir Vile']
看起來這是將所有內容都逆向打印除了!事實上, step
設置為-1
顛倒了列表。
現在讓我們嘗試-2
...
print(dossiers[::-2]) >>> ['Dee Cryption', 'Jacqueline Hyde', 'General Mayhem', 'Baron Grinnit', 'Sir Vile']
這不僅反轉了列表,而且跳過了所有部分元素。負數的step
行為與正數完全相同step
,只是它逆向工作!
那么,如果我們想把所有東西放在一起怎么辦?也許我們想以相反的順序列出第二個、第三個和第四個元素......
print(dossiers[2:5:-1]) >>> []
注意: start
和stop
必須按順序遍歷。如果step
為正,則start
必須小于stop
;但是,如果step
為負數,則start
必須大于stop
!
你可以把它想象成攝影之旅的步行路線。step
告訴你走哪條路,你的步幅應該有多大。一到就開始拍照start
,一遇到問題就stop
收起相機。
所以,要解決這個問題,我們需要交換我們的start
and stop
。
print(dossiers[5:2:-1]) >>> ['Buggs Zapper', 'General Mayhem', 'Medeva']
說明: Python 還提供了slice()
anditertools.islice()
函數,它們的行為方式大致相同。但是,它們都比擴展索引符號更受限制,因此你最好使用擴展索引符號而不是函數。
我們將在本節中探索的其余函數都與迭代對象一起使用。雖然我將在大多數示例中使用列表,但請記住,你可以使用任何可迭代的對象,包括range()
函數。
想象一下,你在一個可迭代的容器(例如列表)中獲得了一大堆數據,例如包含數百個名稱的列表。在將該列表輸入到你的超級算法之前,你希望通過檢查每個元素中是否存在異常值來節省一些處理時間。
這就是all
函數的用途。
dossiers = ['Sir Vile', 'Dr. Belljar', 'Baron Grinnit', 'Medeva', 'General Mayhem', 'Buggs Zapper', '', 'Jane Reaction', 'Dee Cryption'] print(all(dossiers)) >>> False
你可能還記得,空字符串 ( ''
)在 Python 中的計算結果為False
。該all()
函數評估每個元素,并確保它返回True
。如果甚至一個計算結果為False
,該all()
函數也將返回 false。
any()
以幾乎相同的方式工作,但是它只需要一個元素來評估True
.
乍一看,這些似乎不是很有用,但是當與其他一些工具結合使用時,甚至與列表解析(稍后部分)結合使用時,它們可以節省大量時間!
在循環中,如果你需要訪問列表的值及其索引,你可以使用該enumerate()
函數來完成。
foo = ['A', 'B', 'C', 'D', 'E'] for index, value in enumerate(foo): print(f'Element {index} is has the value {value}.')
但是enumerate()
,不僅限于列表。像所有這些其他函數一樣,它適用于任何可迭代的對象,需要返回編號(或枚舉)的每個值。例如,我們把它用在range()
。讓我們用它來打印從 10 到 100 ( range(10,101,10)
) 的每一個 10 的倍數。下面是舉例...
for index, value in enumerate(range(10,101,10)): print(f'Element {index} is has the value {value}.')
這給了我們...
Element 0 is has the value 10. Element 1 is has the value 20. Element 2 is has the value 30. Element 3 is has the value 40. Element 4 is has the value 50. Element 5 is has the value 60. Element 6 is has the value 70. Element 7 is has the value 80. Element 8 is has the value 90. Element 9 is has the value 100
我們可以從中得出一個簡潔的模式,但我們必須從1而不是0開始枚舉。果然,我們可以通過傳遞起始計數數字作為第二個參數來實現。我們還將稍微調整我們輸出的信息,簡化一下輸出格式。
for index, value in enumerate(range(10,101,10), 1): print(f'{index} times 10 equals {value}')
當我們運行它時,我們得到...
1 times 10 equals 10 2 times 10 equals 20 3 times 10 equals 30 4 times 10 equals 40 5 times 10 equals 50 6 times 10 equals 60 7 times 10 equals 70 8 times 10 equals 80 9 times 10 equals 90 10 times 10 equals 100
假設我們正在跟蹤在一堆地點找到的線索數量,將它們存儲在字典中。對于這個例子,我將在最后一節中借用和調整字典......
locations = { 'Parade Ground': 0, 'Ste.-Catherine Street': 0, 'Pont Victoria': 0, 'Underground City': 3, 'Mont Royal Park': 0, 'Fine Arts Museum': 0, 'Humor Hall of Fame': 2, 'Lachine Canal': 4, 'Montreal Jazz Festival': 1, 'Olympic Stadium': 0, 'St. Lawrence River': 2, 'Old Montréal': 0, 'McGill University': 0, 'Chalet Lookout': 0, '?le Notre-Dame': 0 }
也許我們需要找到所有有線索的地點,而忽略其余的。我們將首先編寫一個函數來測試特定的鍵值元組對。這似乎是一個荒謬的過度復雜化,但一會兒會有用:
def has_clues(pair): return bool(pair[1])
我們將字典中的每一對作為元組提交給函數,pair[1]
將會是值(例如('Underground City', 3)
)。如果線索數字是0
,bool()
函數將返回False
,那其他所有為True
的元素,就是我們想要的。
我們使用filter()
對剛剛編寫的函數來縮小字典范圍。回想一下上一節,我們需要使用locations.items()
來獲取鍵和值作為一對。
for place, clues in filter(has_clues, locations.items()): print(place)
請注意,我們不包括has_clues
后面的括號。我們將實際函數作為對象傳遞!filter
將進行實際調用。
果然,運行該代碼會打印出我們有線索的五個地點(值 > 0
)......
Underground City Humor Hall of Fame Lachine Canal Montreal Jazz Festival St. Lawrence River
在本系列的后面部分,我們將學習 lambdas匿名函數,我們不用單獨定義函數。代碼如下......
for place, clues in filter(lambda x:bool(x[1]), locations.items()): print(place)
map()
函數的方式與 類似filter()
,只是它不是使用函數從可迭代對象中省略元素,而是用于更改它們。
假設我們有一個華氏溫度列表:
temps = [67.0, 72.5, 71.3, 78.4, 62.1, 80.6]
我們想將這些都轉換為攝氏度,所以我們為此編寫了一個函數。
def f_to_c(temp): return round((temp - 32) / 1.8, 1)
我們可以使用該map()
函數將其應用于temps
中的每個值,從而生成可以在循環(或任何地方)中使用的迭代器。
for c in map(f_to_c, temps): print(f'{c}°C')
請記住,我們將函數對象 f_to_c
作為map()
的第一個參數傳遞,所以我們去掉括號!
運行該循環輸出:
19.4°C 22.5°C 21.8°C 25.8°C 16.7°C 27.0°C
讓我們繼續使用剛剛的溫度列表例子。如果我們想在列表中找到最低或最高,我們可以分別使用min()
ormax()
函數。這沒什么新奇的。
temps = [67.0, 72.5, 71.3, 78.4, 62.1, 80.6] print(min(temps)) >>> 62.1 print(max(temps)) >>> 80.6
注意:與可迭代對象無關,你還可以使用這些函數來查找你提供給它的參數列表中的最小或最大參數,例如min(4, 5, 6, 7, 8)
,這將返回4
。
通常,你需要對可迭代對象進行排序。Python 通過sorted()
內置函數非常有效地做到了這一點。
temps = [67.0, 72.5, 71.3, 78.4, 62.1, 80.6] for t in sorted(temps): print(t)
輸出如下...
62.1 67.0 71.3 72.5 78.4 80.6
大多數時候,擴展索引符號[::-1]
將允許你反轉列表或其他有序迭代。但如果這不是唯一辦法,你也可以使用reversed()
函數來反轉。
例如,我用sorted()
與剛才的函數結合起來......
temps = [67.0, 72.5, 71.3, 78.4, 62.1, 80.6] for t in reversed(sorted(temps)): print(t)
程序輸出如下...
80.6 78.4 72.5 71.3 67.0 62.1
另一個快速的內置函數是sum()
,它將迭代中的所有元素添加在一起。當然,這只有在所有元素都可以添加在一起時才有效。
這樣做的一種用途是更早地找到這些溫度的平均值。你可能還記得該len()
函數告訴我們容器中有多少元素。
temps = [67.0, 72.5, 71.3, 78.4, 62.1, 80.6] average = sum(temps) / len(temps) print(round(average, 2)) >>> 71.98
還記得前面那個關于地點和線索的例子嗎?想象一下,我們得到的信息不是在字典中,而是在兩個列表中:
locations = ['Parade Ground', 'Ste.-Catherine Street', 'Pont Victoria', 'Underground City', 'Mont Royal Park', 'Fine Arts Museum', 'Humor Hall of Fame', 'Lachine Canal', 'Montreal Jazz Festival', 'Olympic Stadium', 'St. Lawrence River', 'Old Montréal', 'McGill University', 'Chalet Lookout', '?le Notre-Dame'] clues = [0, 0, 0, 3, 0, 0, 2, 4, 1, 0, 2, 0, 0, 0, 0]
那么剛剛的方法就不能實現查找了,但是在現實世界中確實存在我們會以這種方式獲取數據的場景。
值得慶幸的是,zip()
函數可以幫助我們處理這些數據,方法是使用迭代器將其聚合成元組,給我們(locations[0], clues[0]), (locations[1], clues[1]), (locations[2], clues[2])
等等。
zip()
函數甚至不限于兩個迭代;它可以盡可能多地壓縮在一起!如果迭代的長度不同,“額外”內容會被放到最后。
當然,在這種情況下,兩個列表的長度相同,所以結果是相當明顯的。讓我們使用 zip 中的數據創建一個新列表,并將其打印出來。
data = list(zip(locations, clues)) print(data)
這給了我們一個與我們.items()
之前從字典函數中得到的結構不同的結構!
[('Parade Ground', 0), ('Ste.-Catherine Street', 0), ('Pont Victoria', 0), ('Underground City', 3), ('Mont Royal Park', 0), ('Fine Arts Museum', 0), ('Humor Hall of Fame', 2), ('Lachine Canal', 4), ('Montreal Jazz Festival', 1), ('Olympic Stadium', 0), ('St. Lawrence River', 2), ('Old Montréal', 0), ('McGill University', 0), ('Chalet Lookout', 0), ('?le Notre-Dame', 0)]
事實上,如果我回憶起我filter()
的 lambda 函數,我可以將它調整為 use zip
,讓我們完全從兩個列表中工作:
for place, clues in filter(lambda x:bool(x[1]), zip(locations, clues)): print(place)
和以前一樣,輸出...
Underground City Humor Hall of Fame Lachine Canal Montreal Jazz Festival St. Lawrence River
我已經介紹了幾乎所有 Python 用于處理可迭代對象的內置函數,但itertools
模塊中還有更多內容。我強烈建議閱讀官方文檔以了解更多信息。
以上就是“Python迭代工具有哪些及怎么使用”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。