?? 4.html
字號:
<HTML><!-- Mirrored from www.math.pku.edu.cn/teachers/lidf/docs/Python/4.html by HTTrack Website Copier/3.x [XR&CO'2005], Fri, 08 Jul 2005 11:49:13 GMT --><HEAD><TITLE>第四章 流程控制</TITLE></HEAD><BODY LINK="#0000ff"><H1>第四章 流程控制</H1><P>前面我們已經(jīng)見到了如何由用while結(jié)構(gòu)控制流程運行。這一章我們介紹更多的控制結(jié)構(gòu)。Python具有和其它語言類似的控制結(jié)構(gòu)但略有差別。</P><H2>4.1 If 語句</H2><P>If 語句可能是最基本的程序分支語句了。例如:</P><PRE>>>> if x < 0:... x = 0... print 'Negative changed to zero'... elif x == 0:... print 'Zero'... elif x == 1:... print 'Single'... else:... print 'More'...</PRE><P>可以有零到多個elif部分,else部分可選。關(guān)鍵字elif是else if的縮寫,這樣可以縮短語句行長度。其它語言中switch 或 case 語句可以用if...elif...elif...語句組來實現(xiàn)。</P><H2>4.2 for 語句</H2><P>Python中的for語句與你可能熟悉的C或者Pascal中的相應(yīng)語句略有不同。不象Pascal那樣總是對數(shù)字序列進(jìn)行循環(huán),也不是象C中那樣完全由程序員自由地控制循環(huán)條件和循環(huán)體,Python的for循環(huán)是對任意種類的序列(如列表或字符串)按出現(xiàn)次序遍歷每一項。例如:</P><PRE>>>> # 計算字符串長:... a = ['cat', 'window', 'defenestrate']>>> for x in a:... print x, len(x)... cat 3window 6defenestrate 12>>></PRE><P>盡量不要在循環(huán)體內(nèi)修改用來控制循環(huán)的序列(當(dāng)然,只有可變的序列類型如列表才有可能被修改),這樣程序可能會出問題。如果需要這樣,比如說要復(fù)制某些項,可以用序列的副本來控制循環(huán)。片段記號讓你很容易生成副本:</P><PRE>>>> for x in a[:]: # 生成整個列表的片段副本... if len(x) > 6: a.insert(0, x)... >>> a['defenestrate', 'cat', 'window', 'defenestrate']>>></PRE><P>結(jié)果是把列表中長度超過6個字符的字符串插入到列表開頭。</P><H2>4.3 range() 函數(shù)</H2><P>如果確實需要對一列數(shù)字進(jìn)行循環(huán)的話,可以使用內(nèi)置函數(shù)range()。它生成包含數(shù)字序列的列表,如:</P><PRE>>>> range(10)[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]>>></PRE><P>注意給出的終點永遠(yuǎn)不出現(xiàn)在生成的列表中,range(10)生成一個十個數(shù)的列表,恰好是長度為10的序列的合法下標(biāo)的各個值。也可以指定不同的起始點,或者指定不同的間隔(甚至負(fù)數(shù)):</P><PRE>>>> range(5, 10)[5, 6, 7, 8, 9]>>> range(0, 10, 3)[0, 3, 6, 9]>>> range(-10, -100, -30)[-10, -40, -70]>>></PRE><P>為了對序列的下標(biāo)進(jìn)行循環(huán),如下聯(lián)合使用range() 和 len():</P><PRE>>>> a = ['Mary', 'had', 'a', 'little', 'lamb']>>> for i in range(len(a)):... print i, a[i]... 0 Mary1 had2 a3 little4 lamb>>> </PRE><H2>4.4 break語句,continue語句和循環(huán)中的else子句</H2><P>如同C語言一樣,break語句跳出其所處的最內(nèi)層的for 或 while循環(huán),continue語句繼續(xù)下一循環(huán)步。</P><P>循環(huán)語句還可以帶一個 else 子句,當(dāng)循環(huán)正常結(jié)束時執(zhí)行其內(nèi)容,但如果循環(huán)是用break語句跳出的則不執(zhí)行其內(nèi)容。下例說明了這種用法,此例求素數(shù):</P><PRE>>>> for n in range(2, 10):... for x in range(2, n):... if n % x == 0:... print n, 'equals', x, '*', n/x... break... else:... print n, 'is a prime number'... 2 is a prime number3 is a prime number4 equals 2 * 25 is a prime number6 equals 2 * 37 is a prime number8 equals 2 * 49 equals 3 * 3>>> </PRE><H2>4.5 pass 語句</H2><P>pass語句不執(zhí)行任何操作,當(dāng)語法要求一個語句而程序不需要執(zhí)行操作時就用此語句。例如:</P><PRE>>>> while 1:... pass # 等待鍵盤中斷... </PRE><H2>4.6 函數(shù)定義</H2><P>我們可以定義一個函數(shù)用來計算某一界限以下的所有Fibonacci序列值:</P><PRE>>>> def fib(n): # 寫出 n 以下的所有Fibonacci序列值... a, b = 0, 1... while b < n:... print b,... a, b = b, a+b... >>> # 調(diào)用剛剛定義的函數(shù):... fib(2000) 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597>>></PRE><P>其中關(guān)鍵字 def 開始一個函數(shù)定義,其后應(yīng)該是函數(shù)名,括號內(nèi)的形參表,以冒號結(jié)束。構(gòu)成函數(shù)體的各語句從下一行開始,用一個制表符縮進(jìn)。函數(shù)的第一個語句可以是一個字符串,如果是的話,這個字符串就是函數(shù)的文檔字符串,簡稱為docstring。有一些工具可以利用文檔字符串自動生成可打印的文檔,或者讓用戶交互地瀏覽代碼,所以在自己編程時加入文檔字符串是一個好習(xí)慣,應(yīng)該養(yǎng)成這樣的習(xí)慣。</P><P>函數(shù)在執(zhí)行時對局部變量引入一個新的符號表。函數(shù)中的變量賦值都存入局部符號表;引用變量時變量名先從局部符號表中查找,然后在全局符號表中查找,最后從內(nèi)置的名字中查找。因此,在函數(shù)中不能直接對全局變量賦值(除非用了global語句來說明),但可以引用全局變量的值。</P><P>函數(shù)調(diào)用的實參被引入函數(shù)的局部符號表,即函數(shù)的參數(shù)是按值調(diào)用的。函數(shù)再調(diào)用其它函數(shù)時為該函數(shù)生成一個新的符號表。但是嚴(yán)格地說,函數(shù)的調(diào)用是按引用調(diào)用的,因為如果參數(shù)是一個可變類型如列表的話在函數(shù)中改變形參的內(nèi)容將導(dǎo)致實參的內(nèi)容被改變(不改變的是實參名字的綁定關(guān)系)。</P><P>函數(shù)定義把函數(shù)名放入當(dāng)前符號表。函數(shù)名的值類型為用戶自定義函數(shù),這個值可以賦給另一個名字,從而這個名字也代表相同的函數(shù)。這可以作為一般的改名方法:</P><PRE> >>> fib<function object at 10042ed0>>>> f = fib>>> f(100)1 1 2 3 5 8 13 21 34 55 89>>> </PRE><P>你可能會說 fib 不是函數(shù)而是過程。Python和C一樣,過程只是不返回值的函數(shù)。實際上,嚴(yán)格地說,過程也返回一個值,只不過是一個很沒意思的值。這個值叫做 None(這是一個內(nèi)置的名字)。解釋程序交互運行時如果只需要顯示這個值的話就會忽略不顯示。如果希望顯示的話可以用 print 語句:</P><PRE> >>> print fib(0)None>>> 也可以寫一個函數(shù)返回Fibonacci 序列的數(shù)值列表而不是顯示這些值: >>> def fib2(n): # 返回直到n的Fibonacci 序列值... result = []... a, b = 0, 1... while b < n:... result.append(b) # 解釋見下面... a, b = b, a+b... return result... >>> f100 = fib2(100) # 調(diào)用>>> f100 # 輸出結(jié)果[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89] >>> </PRE><P>這個例子也演示了新的Python特色:return語句從函數(shù)中退出并返回一個值。不帶返回值的return可以從過程中間退出,運行到過程的末尾也可以退出,這兩種情況下返回None。</P><P>語句result.append(b)調(diào)用列表對象result的一個方法。方法是“屬于”一個對象的函數(shù),引用格式為obj.methodname,其中obj是某個對象(也允許是一個表達(dá)式), methodname是由該對象的類型定義的一個方法的名字。不同的不同的方法。不同類型的方法可以使用相同的名字而不致引起誤解。(可以定義自己的對象類型和方法,使用類,本文后面會討論這個話題)。例子中的append()方法時列表對象的方法,它在列表末尾增加一個新元素。在本例中這等價于“result = result + [b]”,只是更有效。</P><H2>4.7 函數(shù)參數(shù)</H2><P> 可以定義使用可變個數(shù)參數(shù)的函數(shù)。這樣的定義方法有三種,可以聯(lián)合使用。</P><H3>4.7.1 參數(shù)缺省值</H3><P>可以為一個參數(shù)或幾個參數(shù)指定缺省值。這樣定義的函數(shù)在調(diào)用時實參個數(shù)可以比定義時少。例如:</P><PRE>def ask_ok(prompt, retries=4, complaint='Yes or no, please!'): while 1: ok = raw_input(prompt) if ok in ('y', 'ye', 'yes'): return 1 if ok in ('n', 'no', 'nop', 'nope'): return 0 retries = retries - 1 if retries < 0: raise IOError, 'refusenik user' print complaint</PRE><P>這個函數(shù)在調(diào)用時既可以這樣調(diào)用:ask_ok('Do you really want to quit?'),或者可以這樣調(diào)用:ask_ok('OK to overwrite the file?', 2)。缺省值是在函數(shù)定義時的定義作用域中計算的,所以例如:</P><PRE>i = 5def f(arg = i): print argi = 6f()</PRE><P>將顯示5。</P><P>注意:缺省值只計算一次。當(dāng)缺省值是可變對象如列表或字典時這一點是要注意的。例如,以下函數(shù)會在以后的調(diào)用中累加它的值:</P><PRE>def f(a, l = []): l.append(a) return lprint f(1)print f(2)print f(3)This will print [1][1, 2][1, 2, 3]</PRE><P>如果你不希望缺省值在連續(xù)的調(diào)用中被保留,可以象下面這樣改寫函數(shù):</P><PRE>def f(a, l = None): if l is None: l = [] l.append(a) return l</PRE><H3>4.7.2 關(guān)鍵字參數(shù)</H3><P>函數(shù)調(diào)用時也可以象“關(guān)鍵字 = 值”這樣指定實參,其中關(guān)鍵字是定義時使用的形參的名字。例如:</P><PRE>def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'): print "-- This parrot wouldn't", action, print "if you put", voltage, "Volts through it." print "-- Lovely plumage, the", type print "-- It's", state, "!"</PRE><P>可以用如下幾種方式調(diào)用:</P><PRE>parrot(1000)						# 缺省值parrot(action = 'VOOOOOM', voltage = 1000000)		# 關(guān)鍵字,缺省值,次序可變parrot('a thousand', state = 'pushing up the daisies')	# 位置參數(shù),缺省值,關(guān)鍵字parrot('a million', 'bereft of life', 'jump')		# 位置參數(shù),缺省值</PRE><P>但以下幾種調(diào)用方式是錯誤的:</P><P> </P><PRE>parrot() # 非缺省的參數(shù)沒有提供parrot(voltage=5.0, 'dead') # 關(guān)鍵字參數(shù)后面又出現(xiàn)了非關(guān)鍵字參數(shù)parrot(110, voltage=220) # 參數(shù)值重復(fù)提供parrot(actor='John Cleese') # 未知關(guān)鍵字</PRE><P>一般說來,實參表中位置參數(shù)在前,關(guān)鍵字參數(shù)在后,關(guān)鍵字名字必須是形參名字。形參有沒有缺省值都可以用關(guān)鍵字參數(shù)的形式調(diào)用。每一形參至多只能對應(yīng)一個實參,因此,已經(jīng)由位置參數(shù)傳入值的形參就不能在同一調(diào)用中再作為關(guān)鍵字參數(shù)。</P><P>如果形參表中有一個形為**name的形參,在調(diào)用時這個形參可以接收一個字典,字典中包含所有不與任何形參匹配的關(guān)鍵字參數(shù)。形參表中還可以使用一個特殊的如*name的形參,它將接受所有不能匹配的位置參數(shù)組成的一個序表。*name只能在**name之前出現(xiàn)。例如,如果定義了下面的函數(shù):</P><PRE>def cheeseshop(kind, *arguments, **keywords): print "-- Do you have any", kind, '?' print "-- I'm sorry, we're all out of", kind for arg in arguments: print arg print '-'*40 for kw in keywords.keys(): print kw, ':', keywords[kw]</PRE><P>就可以象下面這樣調(diào)用:</P><PRE>cheeseshop('Limburger', "It's very runny, sir.", "It's really very, VERY runny, sir.", client='John Cleese', shopkeeper='Michael Palin', sketch='Cheese Shop Sketch')</PRE><P>結(jié)果顯示:</P><PRE>-- Do you have any Limburger ?-- I'm sorry, we're all out of LimburgerIt's very runny, sir.It's really very, VERY runny, sir.----------------------------------------client : John Cleeseshopkeeper : Michael Palinsketch : Cheese Shop Sketch</PRE><H3>4.7.3 任意個數(shù)參數(shù)</H3><P>在所有有名的形參的后面可以有兩個特殊的形參,一個以*args的形式命名,一個以**kw的形式命名。有了*args形式的形參后函數(shù)在調(diào)用時就可以在正常的能匹配的實參表后面輸入任意個數(shù)的參數(shù),這些參數(shù)組成一個序表賦給args形參,不能匹配的關(guān)鍵字參數(shù)組成一個字典賦給kw形參。在任意個數(shù)形參之前可以有0到多個正常的參數(shù)。例如:</P><PRE>def fprintf(file, format, *args): file.write(format % args)</PRE><H3>4.7.4 Lambda形式</H3><P>因為許多人的要求,Python中加入了一些在函數(shù)編程語言和Lisp中常見的功能。可以用lambda關(guān)鍵字來定義小的無名函數(shù)。這是一個返回其兩個參數(shù)的和的函數(shù):“l(fā)ambda a, b: a+b”。Lambda形式可以用于任何需要函數(shù)對象的地方。從句法上講lambda形式局限于一個表達(dá)式。從語義上講,這只是正常的函數(shù)定義的句法甜食。像嵌套函數(shù)定義一樣,lambda形式不能訪問包含其定義的作用域中的變量,但審慎地使用缺省參數(shù)之可以繞過這個限制。例如:</P><PRE>def make_incrementor(n): return lambda x, incr=n: x+incr</PRE><H3>4.7.5 文檔字符串</H3><P>關(guān)于文檔字符串的內(nèi)容與格式正在形成一些慣例。第一行應(yīng)該為簡短的對象目的概括說明。為了簡明起見,這一行不應(yīng)該提及對象的名字或類型,因為這些可以通過其他途徑得知(當(dāng)然如果對象名字就是一個描述函數(shù)操作的動詞則當(dāng)然可以提及其名字)。著以行應(yīng)該用大些字母開始,以句點結(jié)尾。如果文檔字符串中有多行,第二行應(yīng)該是空行,把概括說明與其它說明分開。以下的行可以是一段或幾段,描述對象的調(diào)用方法,它的副作用,等等。</P><P>Python的掃描程序不會從多行字符串中去掉縮進(jìn)空白,所以處理文檔的工具需要自己處理縮進(jìn)。只要遵循如下的慣例就可以有利于縮進(jìn)空白的處理。在第一行之后的第一個非空白的行決定整個文檔字符串的縮進(jìn)數(shù)量(我們不用第一行,因為它經(jīng)常是直接跟在表示字符串開始的引號后面)。文檔字符串中除第一行以外的各行都要刪除等價于此行的縮進(jìn)量的空白。對制表符將擴展為空格后再刪除。</P></BODY><!-- Mirrored from www.math.pku.edu.cn/teachers/lidf/docs/Python/4.html by HTTrack Website Copier/3.x [XR&CO'2005], Fri, 08 Jul 2005 11:49:13 GMT --></HTML>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -