1. 程式人生 > >一文讓你掌握Python流程控制,如果沒有,任你伺候!

一文讓你掌握Python流程控制,如果沒有,任你伺候!

python

進群進群:700341555可以獲取Python各類入門學習資料!

這是我的微信公眾號【Python程式設計之家】各位大佬用空可以關注下,每天更新Python學習方法,感謝!

111111111111.png

 

if 語句

也許最著名的語句是 if 語句了。

例如:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> x = int(input("Please enter an integer: "))
Please enter an integer: 42

if x < 0:
... x = 0
... print('Negative changed to zero')
... elif x == 0:
... print('Zero')
... elif x == 1:
... print('Single')
... else:
... print('More')
...
More
</pre>

這邊可以有 0 個或者多個 elif 部分,並且 else 部分是可選的。關鍵字 elif 是 ‘else if’ 的縮寫,它有助於避免過度縮排。 一個 if… elif … elif … 序列可以替代其他語言中的 switch 或 case 語句。

for 語句

Python 中for 語句有點不同於 C 和 Pascal 中的 for 語句。Python 的 for 語句按照專案在序列中出現的順序迭代任何序列(列表或字串),而不是總是迭代數學的算術級數(如 Pascal 中),或者讓使用者能夠定義迭代步驟和停止條件(如 C),例如(沒有雙關語):

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> # 測量字串:
... words = ['cat', 'window', 'defenestrate']

for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12
x = int(input("Please enter an integer: "))
Please enter an integer: 42
>>> if x < 0:
... x = 0
... print('Negative changed to zero')
... elif x == 0:
... print('Zero')
... elif x == 1:
... print('Single')
... else:
... print('More')
...
More
</pre>

這邊可以有 0 個或者多個 elif 部分,並且 else 部分是可選的。關鍵字 elif 是 ‘else if’ 的縮寫,它有助於避免過度縮排。 一個 if… elif … elif … 序列可以替代其他語言中的 switch 或 case 語句。

for 語句

Python 中for 語句有點不同於 C 和 Pascal 中的 for 語句。Python 的 for 語句按照專案在序列中出現的順序迭代任何序列(列表或字串),而不是總是迭代數學的算術級數(如 Pascal 中),或者讓使用者能夠定義迭代步驟和停止條件(如 C),例如(沒有雙關語):

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> # 測量字串:
... words = ['cat', 'window', 'defenestrate']
>>> for w in words:
... print(w, len(w))
...
cat 3
window 6
defenestrate 12
</pre>

如果你需要修改序列在迴圈內的迭代(例如複製所選專案),建議你先複製。迭代序列操作並不會隱式地複製。切片方法使這一操作特別方便:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> for w in words[:]: # 迴圈遍歷整個列表的切片副本。
... if len(w) > 6:
... words.insert(0, w)
...

words
['defenestrate', 'cat', 'window', 'defenestrate']
</pre>

使用 for w in words:,該示例將嘗試建立一個無窮列表,反覆的插入 defenestrate 。

range() 函式

如果你需要迭代一系列的數字,內建的函式 range() 會非常有用。如,生成等差數列:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> for i in range(5):
... print(i)
...
0
1
2
3
4
</pre>

給定的停止位是不會出現在生成的序列中的; range(10) 生成 10 個值,是長度為 10 的序列的項的合法指數。可以讓區間開始於其他的數字,或者指定不同的增量(甚至是負數;有時候這被叫做 ‘步長’):

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">range(5, 10)
5, 6, 7, 8, 9
range(0, 10, 3)
0, 3, 6, 9
range(-10, -100, -30)
-10, -40, -70
</pre>

要遍歷一個序列的索引,你可以像下面這樣組合 range() 和 len() :

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> a = ['Mary', 'had', 'a', 'little', 'lamb']

for i in range(len(a)):
... print(i, a[i])
...
0 Mary
1 had
2 a
3 little
4 lamb
</pre>

然而,在大多數情況下,使用 enumerate() 函式更方便,可以看 迴圈技術.

如果你直接列印一個區間的話,會發生奇怪的事情:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> print(range(10))
range(0, 10)
</pre>

在很多方面, range() 返回的物件的行為像列表,但實際上它不是。它是一個物件,當你迭代它的時候,會連續的返回整個序列的專案,但不會真的建立列表,從而節省空間。

我們稱這樣的物件為 可迭代的 ,也就是說,它很適合於當作函式或者建構函式的目標,它們期望從這裡可以獲得連續的專案直到耗盡。我們已經看到 for 語句是一個 迭代器 。list() 函式是另一個;它可從可迭代物件中建立列表:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> list(range(5))
[0, 1, 2, 3, 4]
</pre>

稍後,我們會看到更多返回可迭代物件和將可迭代物件當作引數的函式。

break 和 continue 語句,以及迴圈上的 else 子句

break 語句,類似於 C ,會打破 for 或 while 迴圈的最內層。

迴圈語句可能有 else 子句;它會在列表耗盡(用 for )從而終止迴圈或者條件為假(用 while )的時候被執行,而不是迴圈被 break 語句終止的時候;這被下面的這個查詢素數的迴圈例證了:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> 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 number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3
</pre>

(是的,這是正確的程式碼。密切關注: for 迴圈的 else 子句,不是 if 語句。)

當在迴圈使中使用 else 子句時,與其說很類似於if 語句,不如說更類似於 try 語句中的 else 子句:一個 try 語句的 else 子句會在沒有異常發生的時候執行,而一個迴圈的 else 子句會在沒有 break 發生的時候執行。要了解更多 try 語句和異常,請看 異常處理.

continue 語句,也是從 C 借來的,用於繼續迴圈的下一次迭代:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> for num in range(2, 10):
... if num % 2 == 0:
... print("Found an even number", num)
... continue
... print("Found a number", num)
Found an even number 2
Found a number 3
Found an even number 4
Found a number 5
Found an even number 6
Found a number 7
Found an even number 8
Found a number 9
</pre>

pass 語句

pass 語句什麼也不做。它可以用於語法上需要,但程式不需要做什麼的時候。例如:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> while True:
... pass # 等待鍵盤中斷(Ctrl+C)
...
</pre>

通常也用於建立小類的時候:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> class MyEmptyClass:
... pass
...
</pre>

其他地方, pass 可以在你處理新程式碼的時候,用作函式或者條件體的佔位符,從而讓你繼續思考更抽象層級的事情。 pass 被默默地忽略了:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> def initlog(*args):
... pass # 記住實現它!
...
</pre>

定義函式

我們可以建立一個能打印出任意項的斐波那契數列的函式:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> def fib(n): # 將斐波那契數列列印到第 n 項
... """將斐波那契數列列印到第 n 項"""
... a, b = 0, 1
... while a < n:
... print(a, end=' ')
... a, b = b, a+b
... print()
...

呼叫上面定義的函式

... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
</pre>

關鍵字 def 引入了一個函式 定義 。其後面必須跟隨有函式的名稱以及用括號包起來的一系列引數。構成函式體的語句從下一行開始,並且必須縮排。

函式體的第一個語句可以是一個字串常量,這個字串常量就是這個函式的文件字串,或者說是 docstring 。(更多關於文件字串的內容可參考章節 Documentation Strings 。)有很多工具可以用於線上或者可列印文件的自動化生成,或者可以讓使用者互動地在程式碼中瀏覽文件;在程式碼中寫文件字串是比較好的實踐,所以請養成寫文件字串的習慣。

函式的 執行 引入了一個新的符號表用於儲存函式的區域性變數。更準確地說,在函式內的所有變數賦值都會被儲存到這張區域性符號表中;所以在查詢一個變數的引用時,會先查詢區域性符號表,然後查詢閉包函式的區域性符號表,接著是全域性符號表,最後才是內建名稱表。因此,儘管可能在函式中引用全域性變數,但在函式中無法對全域性變數直接進行賦值(除非用 global 語句來定義一個變數)

當一個函式被呼叫時,函式引數被引入到區域性符號表中;因此,引數是通過 按值傳遞 的方式來傳遞的(這個值表示一個物件的 引用 ,而不是該物件的值)。[1] 當在一個函式中呼叫另外一個函式時,將會為這次呼叫建立一個新的區域性符號表。

一個函式定義將會在當前符號表中引入函式的名稱。這個函式的名稱對應的值的型別會被直譯器解釋為使用者定義的函式。這個值可以被賦值給另外一個名稱,並且將這名稱可以當作一個函式來使用。這是一種常用的重新命名機制:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> fib
<function fib at 10042ed0>

f = fib
f(100)
0 1 1 2 3 5 8 13 21 34 55 89
</pre>

如果你學習了別的程式語言,你可能認為 fib 不是一個函式而是一個過程,因為它沒有返回值。事實上,一個不包含 return 語句的函式也是會返回一個值的。這個值是 None (這是一個內建名稱)。 一般來說直譯器不會打印出單獨的返回值 None ,如果你真的想打印出 None ,你可以使用 print() :

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> fib(0)

print(fib(0))
None
</pre>

寫一個返回包含斐波那契數列的列表的函式比寫一個列印斐波那契數列的函式要簡單:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> def fib2(n): # 返回斐波那契數列的前 n 項
... """返回包含斐波那契數列前 n 項的列表的函式"""
... result = []
... a, b = 0, 1
... while a < n:
... result.append(a) # 看上面的解釋
... a, b = b, a+b
... return result
...

f100 = fib2(100) # 呼叫函式
f100 # 輸出結果
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
</pre>

這個例子和之前一樣闡述了一些 Python 的新特性:

函式通過 return 語句來返回結果值。不包含引數表示式的 return 語句返回表示函式返回 None。函式執行到末端的時候也返回 None

result.append(a) 語句呼叫了列表 result 的 方法。方法是 “屬於” 一個物件的函式,被命名為 obj.methodname, obj 表示這個物件(也可以是一個表示式),methodname 表示該物件型別定義中方法的名字。不同的型別定義了不同的方法。不同型別的方法的名字可以是相同的且不會產生歧義。(你可以使用 classes 來定一個你自己的物件型別和方法,參見 Classes)例子中的 append() 方法是列表物件定義的。它添加了一個新的元素到列表的末端,相當於 result =result + [a],但是更高效。

更多關於定義函式的內容

也可以使用可變數量的引數定義函式。 一共有三種方式,並且它們可以組合使用。

預設引數值

最常用的形式是為一個或多個引數指定預設值。這樣,函式可以以少於其定義的引數被呼叫。比如:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def ask_ok(prompt, retries=4, reminder='Please try again!'):
while True:
ok = input(prompt)
if ok in ('y', 'ye', 'yes'):
return True
if ok in ('n', 'no', 'nop', 'nope'):
return False
retries = retries - 1
if retries < 0:
raise ValueError('invalid user response')
print(reminder)
</pre>

該函式可以有幾種不同的呼叫方式:

只指定強制的引數

引數: ask_ok(‘Do you really want to quit?’)

提供一個可選引數

引數: ask_ok(‘OK to overwrite the file?’, 2)

或者給定全部的引數

引數: ask_ok(‘OK to overwrite the file?’, 2, ‘Come on, onlyyes or no!’)

上述例子順便也提及了 in 關鍵字。它是用來測試某個特定值是否在一個序列中。

預設值是在定義函式時的“定義過程中” (defining )的範圍內評估的, 所以,

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">i = 5
def f(arg=i):
print(arg)
i = 6
f()
會列印 5.
</pre>

重要提示: 預設值只被評估一次。 這個特性會導致當預設值是列表,字典,或者大多數類的例項時,預設值會是一個可變物件。比如,以下函式會累積在一系列的呼叫過程中所提供的引數:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def f(a, L=[]):
L.append(a)
return L
print(f(1))
print(f(2))
print(f(3))
會打印出:
[1]
[1, 2]
[1, 2, 3]
</pre>

你可以把上面的函式寫成以下的形式,以避免預設值被不同的函式呼叫所共享:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def f(a, L=None):
if L is None:
L = []
L.append(a)
return L
</pre>

關鍵字引數

函式 關鍵字引數 同樣可以使用 kwarg=value 的形式。例如,以下函式:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
print("-- This parrot wouldn't", action, end=' ')
print("if you put", voltage, "volts through it.")
print("-- Lovely plumage, the", type)
print("-- It's", state, "!")

接收一個必選引數 (voltage ) 和三個可選引數( state,action, 和 type )。這個函式下方式呼叫:
```python
parrot(1000) # 一個位置引數
parrot(voltage=1000) # 一個關鍵字引數
parrot(voltage=1000000, action='VOOOOOM') # 2個關鍵字引數
parrot(action='VOOOOOM', voltage=1000000) # 2個關鍵字引數
parrot('a million', 'bereft of life', 'jump') # 3個位置引數
parrot('a thousand', state='pushing up the daisies') # 一個位置引數,一個關鍵字引數
</pre>

但是下列的所有呼叫方式是無效的:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">parrot() # 必選引數缺失
parrot(voltage=5.0, 'dead') # 非關鍵字引數在關鍵字引數後面
parrot(110, voltage=220) # 同一引數重複賦值
parrot(actor='John Cleese') # 未知關鍵字引數
</pre>

在函式呼叫中,關鍵字引數必須遵循引數位置。傳遞的所有關鍵字引數必須跟函式接受的其中一個引數匹配。(例如: actor 在函式 parrot 中不是一個有效的引數),並且它們的順序並不重要。這同樣也包括那些非必選引數 (例如 parrot(voltage=1000) 同樣有效)。沒有引數可能多次獲取一個值。下例就是因此而失敗的:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> def function(a):
... pass
...
>>> function(0, a=0)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: function() got multiple values for keyword argument 'a'
</pre>

當最後存在 **name 形式的引數時,它最後會接收一個字典, (參見 Mapping Types — dict) 包含所有除了和形式引數相對應的關鍵字引數。這可以與 * name 形式的形式引數(在下一小節中描述)結合,該引數接收包含正式引數列表之外的位置引數的元組。 (*name 必須出現在 **name 之前。) 例如,我們如果定義一個如下函式:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">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:
print(kw, ":", keywords[kw])

它可以像這樣呼叫:

cheeseshop("Limburger", "It's very runny, sir.",
 "It's really very, VERY runny, sir.",
 shopkeeper="Michael Palin",
 client="John Cleese",
 sketch="Cheese Shop Sketch")
</pre>

最終它會列印如下:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">-- Do you have any Limburger ?
-- I'm sorry, we're all out of Limburger
It's very runny, sir.
It's really very, VERY runny, sir.
----------------------------------------
shopkeeper : Michael Palin
client : John Cleese
sketch : Cheese Shop Sketch
</pre>

請注意,保證列印函式關鍵字引數的順序,和函式中呼叫中提供它們的順序相一致。

**可變引數**

最後,最不常用的指定引數的選項是可變數量的引數。這些引數將被組裝成一個元組(參見 元組和序列) 。在可變引數之前,可能會出現零個或多個正常引數。

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">def write_multiple_items(file, separator, *args):
 file.write(separator.join(args))
</pre>

通常,這些可變引數將在形式引數列表中排在最後,因為它們會對傳遞給函式的所有剩餘輸入引數進行辨識。 在 * args 引數之後出現的任何引數都是關鍵字引數,這意味著它們只能用作關鍵字引數而不是位置引數。

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> def concat(*args, sep="/"):
... return sep.join(args)
...
>>> concat("earth", "mars", "venus")
'earth/mars/venus'
>>> concat("earth", "mars", "venus", sep=".")
'earth.mars.venus'
</pre>

**分離引數列表**

當輸入的引數已經是列表或元組形式而為了呼叫其中單獨的位置引數時,將會出現與上面相反的情況。例如內建函式 range() 需要有獨立的 start 和 stop 引數。如果輸入的時候不是獨立的引數,則需要用 * 操作符來將引數從列表或者元組裡面提取出來:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> list(range(3, 6)) # 正常利用引數呼叫函式
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args)) # 從列表中提取引數來呼叫函式
[3, 4, 5]
以同樣的方式,可以用 ** 操作符來將關鍵字引數從字典中提取出來:
>>> def parrot(voltage, state='a stiff', action='voom'):
... print("-- This parrot wouldn't", action, end=' ')
... print("if you put", voltage, "volts through it.", end=' ')
... print("E's", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !
</pre>

**Lambda 表示式**

我們可以使用lambda關鍵字來建立小型匿名函式。此函式會返回其兩個引數的和:lambda a,b:a + b。可以在任何需要函式物件的場合使用 Lambda 函式。它們在語法上僅限於單個表示式。從語義上講,它們只是普通函式定義的語法糖。與巢狀函式定義類似,lambda 函式可以從包含它的上下文中引用變數:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> def make_incrementor(n):
... return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43
</pre>

上面的例子使用 lambda 表示式返回了一個函式。另一個用途是傳遞一個小函式作為引數:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]
</pre>

**文件字串**

對於文件字串的內容和格式,是有一定的約定的。

第一行應該始終是一個對物件目的的精簡的總結。為簡潔起見,它不該顯式地宣告物件的名稱或型別,因為它們可以通過其他方式獲得(除非函式名恰好是描述函式作用的動詞)。這一行應該以大寫字母開頭並以句號結尾。

如果文件字串不止一行,則第二行應為空白,從而能在視覺上將總結與其餘的描述分開。接下來的幾行應該是一個或多個段落,負責描述物件的呼叫約定以及其副作用等。

在 Python 中,Python 解析器並不會刪除多行字串文字的縮排,因此處理文件的工具必須在有必要之時刪除縮排。這點是使用以下的約定完成的。在第一行之後的首個非空行決定了整個文件字串的縮排數。(我們不能用第一行來決定,因為它通常與字串開頭的引號相鄰,因此它的縮排在字串中並不明顯。)之後,我們把「等同於」這段縮排的空格從字串的所有行的開頭全部去除。不應出現少縮排的行,但如果出現了就把它們前面的空格全部去除。展開製表符後我們應當測試空格的等效性(通常為8個空格)。

以下是個多行文件字串的例子:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> def my_function():
... """只要寫文件,其他啥都別做。
...
... 確實,它也啥都不做。
... """
... pass
...
>>> print(my_function.__doc__)
</pre>

只要寫文件,其他啥都別做。

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">確實,它也啥都不做。
</pre>

**函式註解**

函式註解 (Function annotations)應用於使用者自定義的函式,可使用的型別是完全可選的元資料 (參考 PEP 3107和 PEP 484 獲取更多資訊)。

註解(Annotations)是以字典的形式存放在函式的 **annotations** 屬性中,並且不對函式有任何影響。引數註解 (Parameter annotations) 是由引數名稱後面加上冒號來定義的,後面緊跟一個描述,來表示註解的值。 返回註解 (Return annotations) 的定義方式是:由 -> 符號開始,在引數列表和表示函式def結束的冒號之間,加上你的描述。 接下來的例子,表示了位置引數、關鍵字引數和返回值的註解方法:

<pre style="-webkit-tap-highlight-color: transparent; box-sizing: border-box; font-family: Consolas, Menlo, Courier, monospace; font-size: 16px; white-space: pre-wrap; position: relative; line-height: 1.5; color: rgb(153, 153, 153); margin: 1em 0px; padding: 12px 10px; background: rgb(244, 245, 246); border: 1px solid rgb(232, 232, 232); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">>>> def f(ham: str, eggs: str = 'eggs') -> str:
... print("Annotations:", f.__annotations__)
... print("Arguments:", ham, eggs)
... return ham + ' and ' + eggs
...
>>> f('spam')
Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
Arguments: spam eggs
'spam and eggs'
</pre>

**插曲: 程式碼風格**

現在你能夠寫更長更復雜的 Python 程式碼了。 是時候可以談談程式碼風格了。大多數程式語言可以使用不同的程式碼風格編寫(就是格式化); 有的可讀性比其他的強。使用一種不錯的程式碼風格可以幫助別人更好的閱讀你的程式碼。

PEP 8 是大多數 Python 專案使用的程式碼風格指南。它提供了高可讀性和養眼的程式碼風格。每一個 Python 開發者都應該閱讀它,這裡列出了其中的一些重點:

*   縮減使用四個空格而不是製表符
*   四個空格縮排比更少空格(執行跟多的巢狀深度)或者更多空格(更容易閱讀)的縮排要好。 製表符會帶來歧義,所以最好不要用它
*   每行不好超過79個字元
*   這可以幫助顯示器較小的使用者與幫助顯示器較大的使用者同屏顯示多個檔案。
*   使用空行分隔函式、類或者函式內較大的程式碼段。
*   儘量將註釋和程式碼放在一起。
*   用 docstrings。
*   用在操作符前後和逗號之後加空格,但是括號之內不需要: a= f(1, 2) + g(3, 4).
*   一致性的命名你的類與函式;慣例是用 CamelCase 命名類 ,用 lower_case_with_underscores 命名函式和方法。必須使用 self 作為方法的第一個引數(想了解更多請閱讀 A First Look at Classes)。
*   如果你的程式碼將用於國際化的環境中,請不要使用任何花哨的編碼。 Python 預設使用 UTF-8,甚至純 ASCII 在任何情況下都能最好地工作。
*   即使說其他語言的人閱讀或者維護你的程式碼的機率很小,也不要使用非 ASCII 字元。