標籤:通過 完整 細節 之間 空格 測試 python運行 stat 質數
while 迴圈一般格式:[python] view plain copywhile <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和迴圈elsebreak:跳出最近所在的迴圈(跳過整個迴圈語句)continue:跳到最近所在迴圈的開頭處(來到迴圈的首行)pass:什麼事也不做,只是空佔位語句迴圈else塊:只有當迴圈正常離開時才會執行(也就是沒有碰到break語句)------------------------------------------------------------------------------------------------------------------------------------------------一般迴圈格式加入break和continue後,while的一般迴圈格式變為:[python] view plain copywhile <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 copydef 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 copyfor <target> in <object>: <statements> else: <statements> 當python運行for迴圈時,會逐個將序列對象中的元素賦值給目標,然後為每個元素執行迴圈主體。for迴圈也可以用break、continue和else子句完整格式如下:[python] view plain copyfor <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和rangerange函數是通用的工具,可用在各種環境中,雖然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迴圈