Python——while和for循環
阿新 • • 發佈:2018-04-08
found BE 進行 AC 閱讀 解包 rate sha 但是
while 循環 一般格式: [python] view plain copy while <test>: <statements1> else <test>: <statements2> else為可選部分,當控制權離開循環而又沒有碰到break語句時會執行。 [python] view plain copy >>> x = ‘spam‘ >>> while x : print (x,end=‘ ‘) x = x[1:] spam pam am m 註意:這裏使用end = ‘ ‘關鍵字參數,使所有輸出都出現在同一行,之間用空格隔開 ------------------------------------------------------------------------------------------------------------------------------------------------ break、continue、pass和循環else break:跳出最近所在的循環(跳過整個循環語句) continue:跳到最近所在循環的開頭處(來到循環的首行) pass:什麽事也不做,只是空占位語句 循環else塊:只有當循環正常離開時才會執行(也就是沒有碰到break語句) ------------------------------------------------------------------------------------------------------------------------------------------------ 一般循環格式 加入break和continue後,while的一般循環格式變為: [python] view plain copy while <test1>: <statements1> if <test2>:break if <test3>:continue else: <statements2> ------------------------------------------------------------------------------------------------------------------------------------------------ pass語句是無運算的占位語句,當語法需要語句並且還沒有任何使用的語句可寫時,就可以使用它。它通常用於為復合語句編寫一個空的主體。例如,如果想寫個無限循環,每次叠代什麽也不做,就寫個pass [python] view plain copy >>> while True :pass 因為主體只是空語句,Python陷入了死循環,這個程序並沒有什麽用處。以後將會看到它更有意義的用處。例如,忽略try語句所捕獲的異常,以及定義帶屬性的空類對象,而該類實現的對象行為就像其他語言的結構和記錄。pass有時指的是“以後會填上”,只是暫時用於填充函數主體而已 [python] view plain copy def func1(): pass def func2(): pass 我們無法保持函數體為空而不產生語法錯誤,因此,可以使用pass來替代 【另外:在Python3.0以後,程序中可以使用三個點...來代替pass,這樣似乎更加簡潔明了】 ------------------------------------------------------------------------------------------------------------------------------------------------ continue語句會立即跳到循環的頂端,即跳過本次循環,執行下一次循環 break 語句會立即離開循環 [python] view plain copy >>> while True: name = input(‘Enter name:‘) if name == ‘stop‘:break age = input(‘Enter age:‘) print(‘Hello‘,name,‘=>‘,int(age)**2) Enter name:Gavin Enter age:2 Hello Gavin => 4 Enter name:Spam Enter age:20 Hello Spam => 400 Enter name:stop ------------------------------------------------------------------------------------------------------------------------------------------------ 循環else 和循環else子句結合時,break語句通常可以忽略其他語言中所需要的搜索狀態標誌位。 例如,下列程序搜索大於1的因子,來決定正整數y是否為質數: [python] view plain copy >>> def judge(y): x = y//2 while x >1: if y % x ==0: print(y,‘has factor‘,x) break x -= 1 else: print(y,‘is prime‘) >>> judge(8) 8 has factor 4 >>> judge(19) 19 is prime >>> judge(119) 119 has factor 17 除了設置標誌位在循環結束時進行測試外,也可以在找到因子時插入break。這樣一來,循環else分句可以視為只有當沒有找到因子時才會執行。如果你沒有碰到break,該數就是質數。 【註意,當第一次判斷while循環條件就不滿足時,也就是一次循環也沒有進行時,還是會執行else子句的】 ================================================================================= for循環 一般用法: [python] view plain copy for <target> in <object>: <statements> else: <statements> 當python運行for循環時,會逐個將序列對象中的元素賦值給目標,然後為每個元素執行循環主體。 for循環也可以用break、continue和else子句 完整格式如下: [python] view plain copy for <target> in <object>: <statements> if <test>:break if <test>:continue else: <statements> ------------------------------------------------------------------------------------------------------------------------------------------------ 基礎應用: [python] view plain copy >>> for x in [‘spam‘,‘eggs‘,‘ham‘]: print(x,end= ‘ ‘) spam eggs ham 下面兩個例子會計算列表得到所有元素的和與乘積。 [python] view plain copy >>> s = 0 >>> for x in [1,2,3,4]: s += x >>> x #這裏x這個變量依然是有值的 4 >>> s 10 [python] view plain copy >>> p = 1 >>> for x in [1,2,3,4]: p *= x >>> p 24 在以後,還會知道Python有一些工具,可以自動對列表中的元素應用諸如‘+’和‘*‘類似的運算,但是使用for循環通常也一樣簡單 ------------------------------------------------------------------------------------------------------------------------------------------------ 其他數據類型 不止對於列表適用,for循環對任何序列都適用,for循環還可以應用於字符串和元組,這裏就不舉例了。 實際上,for循環甚至可以應用在一些根本不是序列的對象上,對於文件和字典也有效。 ------------------------------------------------------------------------------------------------------------------------------------------------ 在for 循環中的元組賦值 [python] view plain copy >>> T = [(1,2),(3,4),(5,6)] >>> for (a,b) in T: print(a,b) 1 2 3 4 5 6 [python] view plain copy >>> for x in T : print(x) (1, 2) (3, 4) (5, 6) 註意上述兩個例子的區別。第一個例子可以看做元組解包的賦值運算 這種形式通常和我們將要介紹的zip調用一起使用,以實現並行遍歷。在Python中,它通常還和SQL數據庫一起使用,其中,查詢結果表作為這裏使用的列表這樣的序列的序列而返回——外圍的列表就是數據庫表,嵌套的元組是表中的行,元組賦值和列對應 for 循環中的元組使得用items方法來遍歷字典中的鍵和值變得很方便,而不必再遍歷鍵並手動索引以獲取值: [python] view plain copy >>> D = {‘a‘:1,‘b‘:2,‘c‘:3} >>> for key in D: print(key,‘=>‘,D[key]) b => 2 c => 3 a => 1 [python] view plain copy >>> list(D.items()) [(‘b‘, 2), (‘c‘, 3), (‘a‘, 1)] >>> for (key,value) in D.items(): print(key,‘=>‘,value) b => 2 c => 3 a => 1 註意for循環中的元組賦值並非一種特殊情況,這一點很重要;單詞for之後的任何賦值目標在語法上都是有效的。盡管我們總是在for循環中手動地賦值以解包: [python] view plain copy >>> for both in T: a,b = both print(a,b) 1 2 3 4 5 6 ------------------------------------------------------------------------------------------------------------------------------------------------ Python3.0 在for循環中擴展的序列賦值 實際上,for循環中的循環變量真的可以是任何賦值目標,在這裏,也可以使用Python3.0的擴展序列解包賦值語法,來提取序列中的序列的元素和部分。 擴展序列賦值可以參考這裏 ------------------------------------------------------------------------------------------------------------------------------------------------ 嵌套for循環 這段代碼會在對象列表中搜索每個鍵,然後報告其搜索結果: [python] view plain copy >>> items = [‘aaa‘,111,(4,5),2.01] >>> tests = [(4,5),3.14] >>> for key in tests: for item in items: if key == item: print(key,‘was found‘) break else: print(key,‘not found‘) (4, 5) was found 3.14 not found ================================================================================= 編寫循環的技巧 1.內置range函數返回一系列連續增加的整數,可作為for中的索引 2.內置zip函數返回並行元素的元組的列表,可用於在for中內遍歷整個序列。 ------------------------------------------------------------------------------------------------------------------------------------------------ 循環計數器:while和range range函數是通用的工具,可用在各種環境中,雖然range常用在for循環中來產生索引,但也可以用在任何需要整數列表的地方。在Python3.0中,range是一個叠代器,會根據需要產生元素,因此,我們需要將其包含到一個list調用中以一次性顯示其結果: [python] view plain copy >>> list(range(5)),list(range(2,5)),list(range(0,10,2)) ([0, 1, 2, 3, 4], [2, 3, 4], [0, 2, 4, 6, 8]) 一個參數時,range會產生從零算起的整數列表,但其中不包括該參數的值; 如果傳進兩個參數,第一個視為下邊界。 第三個選用參數可以提供步進值,使用時,Python會對每個連續整數加上步進值(步進值默認為1). range也可以是非正數或非遞增的: [python] view plain copy >>> list(range(-5,5)) [-5, -4, -3, -2, -1, 0, 1, 2, 3, 4] >>> list(range(5,-5,-2)) [5, 3, 1, -1, -3] 從內部實現上來看,for循環以這種方式使用時,會自動處理叠代的細節。如果你真的想要明確得掌控索引邏輯,可以用while循環來實現: [python] view plain copy >>> s = ‘gavin‘ >>> i = 0 >>> while i<len(s): print(s[i],end = ‘ ‘) i+=1 g a v i n ------------------------------------------------------------------------------------------------------------------------------------------------ 非完備遍歷:range和分片 一般情況下,在對序列進行遍歷時,最好使用Python中的簡單的for循環,不要使用while,並且不要在for循環中使用range調用,只將其視為最後的手段。 [python] view plain copy >>> for item in X:print(item) 然而利用range進行索引的用處是,我們可以通過控制range來實現特殊的遍歷,例如,在遍歷的過程中跳過一些元素 [python] view plain copy >>> S = ‘abcdefghijklmn‘ >>> for i in range(0,len(S),2):print(S[i],end = ‘ ‘) a c e g i k m 在這裏,我們通過所產生的range列表,訪問了字符串S中每隔一個的元素,要使用每隔兩個的元素,可以把range的第三個參數改為3,以此類推。 然而,這可能不是如今Python中最理想情況下實現的技術,如果你真想跳過序列中的元素,可以用前面介紹的擴展的第三個限制值形式的分片表達式,例如,要使用S中每隔一個的字符串,可以用步進值2來分片: [python] view plain copy >>> for item in S[::2]:print(item,end=‘ ‘) a c e g i k m 結果是相同的,但對我們來說更容易編寫,對其他人來說,更容易閱讀。 ------------------------------------------------------------------------------------------------------------------------------------------------ 修改列表:range 可以使用range和for的組合的常見場合就是在循環中遍歷列表時對其進行修改。例如,假設你因某種理由要為列表中的每個元素都加1,你可以通過簡單的for循環來做,但結果可能不是你想要的: [python] view plain copy >>> L = [1,2,3,4,5] >>> for x in L: x+=1 >>> L [1, 2, 3, 4, 5] >>> x 6 這樣並不行,因為修改的是循環變量x,而不是列表L. 要真的在我們遍歷列表時對其修改,我們需要使用索引,讓我們可以在遍歷時替每個位置賦一個一個已更新的值。range/len組合可以替我們產生所需要的索引。 [python] view plain copy >>> L = [1,2,3,4,5] >>> for i in range(len(L)): L[i] +=1 >>> L [2, 3, 4, 5, 6] 用while循環也可以做,只是運行比較慢。 [python] view plain copy [x+1 for x in L] 這種形式的列表解析表達式也能做類似的工作,而且沒有對最初的列表進行在原處的修改(我們可以把表達式的新列表對象賦值給L,但是這樣不會更新原始列表的其他任何引用值)。因為這是循環的核心概念,我們將在以後對列表解析做一個完整的介紹。 ------------------------------------------------------------------------------------------------------------------------------------------------ 並行遍歷:zip和map 內置zip函數可以讓我們使用for循環來並行使用多個序列,在基本運算中,zip會取得一個或多個序列為參數,然後返回元組的列表,將這些序列中的並排的元素配成對 例如,假設我們要使用兩個列表: [python] view plain copy >>> A = [1,2,3,4] >>> B = [11,22,33,44] 要合並這些列表中的元素,我們可以使用zip來創建一個元組對的列表(和range一樣,zip在Python3.0中也是一個可叠代對象,因此,我們必須將其包含在一個list調用中以便一次性顯示所有結果) [python] view plain copy >>> C = zip(A,B) >>> C <zip object at 0x0405BE18> >>> list(C) [(1, 11), (2, 22), (3, 33), (4, 44)] 這樣的結果在其他環境下也有用,然而搭配for循環中,它就會支持並行叠代: [python] view plain copy >>> for (x,y) in zip(A,B): print(x,y,‘---‘,x+y) 1 11 --- 12 2 22 --- 24 3 33 --- 36 4 44 --- 48 zip可以接受任何類型的序列(其實就是任何可叠代的對象,包括文件),並且可以有兩個以上的參數。例如 [python] view plain copy >>> T1,T2,T3 = (1,2,3),(4,5,6),(7,8,9) >>> T2 (4, 5, 6) >>> list(zip(T1,T2,T3)) [(1, 4, 7), (2, 5, 8), (3, 6, 9)] 當參數長度不同時,zip會以最短序列的長度為準來截斷所得到的元組: [python] view plain copy >>> S1 = ‘abc‘ >>> S2 = ‘xyz123‘ >>> list(zip(S1,S2)) [(‘a‘, ‘x‘), (‘b‘, ‘y‘), (‘c‘, ‘z‘)] ------------------------------------------------------------------------------------------------------------------------------------------------ 使用zip構造字典 前面介紹過,當鍵和值的集合必須在運行時計算時,這裏所用的zip調用也可用於產生字典,並且非常方便。 假設有下列的鍵和值的列表: [python] view plain copy >>> keys = [‘spam‘,‘eggs‘,‘toast‘] >>> vals=[1,2,3] 將這些列表變成字典的一種做法就是將這些字符zip起來,並通過for循環並行步進處理: [python] view plain copy >>> list(zip(keys,vals)) [(‘spam‘, 1), (‘eggs‘, 2), (‘toast‘, 3)] >>> D2 = {} >>> for (key,val) in zip(keys,vals): D2[key] = val >>> D2 {‘toast‘: 3, ‘spam‘: 1, ‘eggs‘: 2} 不過,在Python2.2和後續版本中,可以完全跳過for循環,直接把zip過的鍵/值列表傳給內置的dict構造函數: [python] view plain copy >>> D3 = dict(zip(keys,vals)) >>> D3 {‘toast‘: 3, ‘spam‘: 1, ‘eggs‘: 2} ------------------------------------------------------------------------------------------------------------------------------------------------ 產生偏移和元素:enumerate 之前,我們討論過通過range來產生字符串中元素的偏移值,而不是那些偏移處的元素,不過,在有些程序中,我們兩者都需要:需要的元素以及這個元素的偏移值。 可以按照下面這個簡單的例子做: [python] view plain copy >>> S = ‘spam‘ >>> offset = 0 >>> for item in S: print(item,‘appears at offset‘,offset) offset += 1 s appears at offset 0 p appears at offset 1 a appears at offset 2 m appears at offset 3 不過內置函數enumerate可以為我們做這件事情: [python] view plain copy >>> S = ‘spam‘ >>> for (offset,item) in enumerate(S): print(item,‘appears at offset‘,offset) s appears at offset 0 p appears at offset 1 a appears at offset 2 m appears at offset 3 可以看到: [python] view plain copy >>> enumerate(S) <enumerate object at 0x03602FA8> >>> list(enumerate(S)) [(0, ‘s‘), (1, ‘p‘), (2, ‘a‘), (3, ‘m‘)] enumerate函數返回一個生成器對象:這種對象支持接下來要學習的叠代協議。簡而言之,這個對象有一個__next__方法,由下一個內置函數調用它,並且在循環中每次叠代的時候它會返回一個(index,value)的元祖。我們可以在for循環中通過元組賦值將元組解包(很像是使用zip) [python] view plain copy >>> E = enumerate(S) >>> E <enumerate object at 0x03602F80> >>> next(E) (0, ‘s‘) >>> next(E) (1, ‘p‘) >>> next(E) (2, ‘a‘) [python] view plain copy >>> [c*i for (i,c) in enumerate(S)] [‘‘, ‘p‘, ‘aa‘, ‘mmm‘]
Python——while和for循環