函數(shù)是重用的程序段。它們允許你給一塊語句一個名稱,然后你可以在你的程序的任何地方使用這個名稱任意多次地運行這個語句塊。這被稱為 調(diào)用 函數(shù)。我們已經(jīng)使用了許多內(nèi)建的函數(shù),比如 len 和 range。
函數(shù)通過 def 關(guān)鍵字定義。def 關(guān)鍵字后跟一個函數(shù)的 標(biāo)識符 名稱,然后跟一對圓括號。圓括號之中可以包括一些變量名,該行以冒號結(jié)尾。接下來是一塊語句,它們是函數(shù)體。下面這個例子將說明這事實上是十分簡單的:
例 7.1 定義函數(shù)
#!/usr/bin/python
# Filename: function1.py
def sayHello():
print 'Hello World!' # block belonging to the function
sayHello() # call the function
(源文件:code/function1.py)
輸出
$ python function1.py
Hello World!
它如何工作
我們使用上面解釋的語法定義了一個稱為 sayHello 的函數(shù)。這個函數(shù)不使用任何參數(shù),因此在圓括號中沒有聲明任何變量。參數(shù)對于函數(shù)而言,只是給函數(shù)的輸入,以便于我們可以傳遞不同的值給函數(shù),然后得到相應(yīng)的結(jié)果。
函數(shù)取得的參數(shù)是你提供給函數(shù)的值,這樣函數(shù)就可以利用這些值 做 一些事情。這些參數(shù)就像變量一樣,只不過它們的值是在我們調(diào)用函數(shù)的時候定義的,而非在函數(shù)本身內(nèi)賦值。
參數(shù)在函數(shù)定義的圓括號對內(nèi)指定,用逗號分割。當(dāng)我們調(diào)用函數(shù)的時候,我們以同樣的方式提供值。注意我們使用過的術(shù)語——函數(shù)中的參數(shù)名稱為 形參 而你提供給函數(shù)調(diào)用的值稱為 實參 。
例 7.2 使用函數(shù)形參
#!/usr/bin/python
# Filename: func_param.py
def printMax(a, b):
if a > b:
print a, 'is maximum'
else:
print b, 'is maximum'
printMax(3, 4) # directly give literal values
x = 5
y = 7
printMax(x, y) # give variables as arguments
(源文件:code/func_param.py)
輸出
$ python func_param.py
4 is maximum
7 is maximum
它如何工作
這里,我們定義了一個稱為 printMax 的函數(shù),這個函數(shù)需要兩個形參,叫做 a 和 b。我們使用 if..else 語句找出兩者之中較大的一個數(shù),并且打印較大的那個數(shù)。
在第一個 printMax 使用中,我們直接把數(shù),即實參,提供給函數(shù)。在第二個使用中,我們使用變量調(diào)用函數(shù)。printMax(x, y)使實參 x 的值賦給形參 a,實參y的值賦給形參 b。在兩次調(diào)用中,printMax 函數(shù)的工作完全相同。
當(dāng)你在函數(shù)定義內(nèi)聲明變量的時候,它們與函數(shù)外具有相同名稱的其他變量沒有任何關(guān)系,即變量名稱對于函數(shù)來說是 局部 的。這稱為變量的 作用域 。所有變量的作用域是它們被定義的塊,從它們的名稱被定義的那點開始。
例 7.3 使用局部變量
#!/usr/bin/python
# Filename: func_local.py
def func(x):
print 'x is', x
x = 2
print 'Changed local x to', x
x = 50
func(x)
print 'x is still', x
(源文件:code/func_local.py)
輸出
$ python func_local.py
x is 50
Changed local x to 2
x is still 50
它如何工作
在函數(shù)中,我們第一次使用 x 的 值 的時候,Python 使用函數(shù)聲明的形參的值。
接下來,我們把值 2 賦給 x。x 是函數(shù)的局部變量。所以,當(dāng)我們在函數(shù)內(nèi)改變 x 的值的時候,在主塊中定義的 x 不受影響。
在最后一個 print 語句中,我們證明了主塊中的 x 的值確實沒有受到影響。
如果你想要為一個定義在函數(shù)外的變量賦值,那么你就得告訴 Python 這個變量名不是局部的,而是 全局 的。我們使用 global 語句完成這一功能。沒有 global 語句,是不可能為定義在函數(shù)外的變量賦值的。
你可以使用定義在函數(shù)外的變量的值(假設(shè)在函數(shù)內(nèi)沒有同名的變量)。然而,我并不鼓勵你這樣做,并且你應(yīng)該盡量避免這樣做,因為這使得程序的讀者會不清楚這個變量是在哪里定義的。使用 global 語句可以清楚地表明變量是在外面的塊定義的。
例 7.4 使用 global 語句
#!/usr/bin/python
# Filename: func_global.py
def func():
global x
print 'x is', x
x = 2
print 'Changed local x to', x
x = 50
func()
print 'Value of x is', x
(源文件:code/func_global.py)
輸出
$ python func_global.py
x is 50
Changed global x to 2
Value of x is 2
它如何工作
global 語句被用來聲明x是全局的——因此,當(dāng)我們在函數(shù)內(nèi)把值賦給x的時候,這個變化也反映在我們在主塊中使用 x 的值的時候。
你可以使用同一個 global 語句指定多個全局變量。例如 global x, y, z。
對于一些函數(shù),你可能希望它的一些參數(shù)是 可選 的,如果用戶不想要為這些參數(shù)提供值的話,這些參數(shù)就使用默認(rèn)值。這個功能借助于默認(rèn)參數(shù)值完成。你可以在函數(shù)定義的形參名后加上賦值運算符(=)和默認(rèn)值,從而給形參指定默認(rèn)參數(shù)值。
注意,默認(rèn)參數(shù)值應(yīng)該是一個參數(shù)。更加準(zhǔn)確的說,默認(rèn)參數(shù)值應(yīng)該是不可變的——這會在后面的章節(jié)中做詳細(xì)解釋。從現(xiàn)在開始,請記住這一點。
例 7.5 使用默認(rèn)參數(shù)值
#!/usr/bin/python
# Filename: func_default.py
def say(message, times = 1):
print message * times
say('Hello')
say('World', 5)
(源文件:code/func_default.py)
輸出
$ python func_default.py
Hello
WorldWorldWorldWorldWorld
它如何工作
名為 say 的函數(shù)用來打印一個字符串任意所需的次數(shù)。如果我們不提供一個值,那么默認(rèn)地,字符串將只被打印一遍。我們通過給形參 times 指定默認(rèn)參數(shù)值1來實現(xiàn)這一功能。
在第一次使用 say 的時候,我們只提供一個字符串,函數(shù)只打印一次字符串。在第二次使用 say 的時候,我們提供了字符串和參數(shù) 5,表明我們想要 說 這個字符串消息 5 遍。
重要 只有在形參表末尾的那些參數(shù)可以有默認(rèn)參數(shù)值,即你不能在聲明函數(shù)形參的時候,先聲明有默認(rèn)值的形參而后聲明沒有默認(rèn)值的形參。 這是因為賦給形參的值是根據(jù)位置而賦值的。例如,def func(a, b=5)是有效的,但是 def func(a=5, b)是 無效 的。
如果你的某個函數(shù)有許多參數(shù),而你只想指定其中的一部分,那么你可以通過命名來為這些參數(shù)賦值——這被稱作 關(guān)鍵參數(shù) ——我們使用名字(關(guān)鍵字)而不是位置(我們前面所一直使用的方法)來給函數(shù)指定實參。
這樣做有兩個 優(yōu)勢 ——一,由于我們不必?fù)?dān)心參數(shù)的順序,使用函數(shù)變得更加簡單了。二、假設(shè)其他參數(shù)都有默認(rèn)值,我們可以只給我們想要的那些參數(shù)賦值。
例 7.6 使用關(guān)鍵參數(shù)
#!/usr/bin/python
# Filename: func_key.py
def func(a, b=5, c=10):
print 'a is', a, 'and b is', b, 'and c is', c
func(3, 7)
func(25, c=24)
func(c=50, a=100)
(源文件:code/func_key.py)
輸出
$ python func_key.py
a is 3 and b is 7 and c is 10
a is 25 and b is 5 and c is 24
a is 100 and b is 5 and c is 50
它如何工作
名為 func 的函數(shù)有一個沒有默認(rèn)值的參數(shù),和兩個有默認(rèn)值的參數(shù)。
在第一次使用函數(shù)的時候, func(3, 7),參數(shù) a 得到值 3,參數(shù) b 得到值 7,而參數(shù) c 使用默認(rèn)值 10。
在第二次使用函數(shù) func(25, c=24)的時候,根據(jù)實參的位置變量 a 得到值 25。根據(jù)命名,即關(guān)鍵參數(shù),參數(shù) c 得到值 24。變量 b 根據(jù)默認(rèn)值,為 5。
在第三次使用 func(c=50, a=100)的時候,我們使用關(guān)鍵參數(shù)來完全指定參數(shù)值。注意,盡管函數(shù)定義中,a 在 c 之前定義,我們?nèi)匀豢梢栽?a 之前指定參數(shù) c 的值。
return 語句用來從一個函數(shù) 返回 即跳出函數(shù)。我們也可選從函數(shù) 返回一個值 。
例 7.7 使用字面意義上的語句
#!/usr/bin/python
# Filename: func_return.py
def maximum(x, y):
if x > y:
return x
else:
return y
print maximum(2, 3)
(源文件:code/func_return.py)
輸出
$ python func_return.py
3
它如何工作
maximum 函數(shù)返回參數(shù)中的最大值,在這里是提供給函數(shù)的數(shù)。它使用簡單的 if..else 語句來找出較大的值,然后 返回 那個值。
注意,沒有返回值的 return 語句等價于 return None。None 是 Python 中表示沒有任何東西的特殊類型。例如,如果一個變量的值為 None,可以表示它沒有值。
除非你提供你自己的 return 語句,每個函數(shù)都在結(jié)尾暗含有 return None 語句。通過運行 print someFunction(),你可以明白這一點,函數(shù) someFunction 沒有使用 return 語句,如同:
def someFunction():
pass
pass 語句在 Python 中表示一個空的語句塊。
Python 有一個很奇妙的特性,稱為 文檔字符串 ,它通常被簡稱為 docstrings 。DocStrings 是一個重要的工具,由于它幫助你的程序文檔更加簡單易懂,你應(yīng)該盡量使用它。你甚至可以在程序運行的時候,從函數(shù)恢復(fù)文檔字符串!
例 7.8 使用 DocStrings
#!/usr/bin/python
# Filename: func_doc.py
def printMax(x, y):
'''Prints the maximum of two numbers.
The two values must be integers.'''
x = int(x) # convert to integers, if possible
y = int(y)
if x > y:
print x, 'is maximum'
else:
print y, 'is maximum'
printMax(3, 5)
print printMax.__doc__
(源文件:code/func_doc.py)
輸出
$ python func_doc.py
5 is maximum
Prints the maximum of two numbers.
The two values must be integers.
它如何工作
在函數(shù)的第一個邏輯行的字符串是這個函數(shù)的 文檔字符串 。注意,DocStrings 也適用于模塊和類,我們會在后面相應(yīng)的章節(jié)學(xué)習(xí)它們。
文檔字符串的慣例是一個多行字符串,它的首行以大寫字母開始,句號結(jié)尾。第二行是空行,從第三行開始是詳細(xì)的描述。 強烈建議 你在你的函數(shù)中使用文檔字符串時遵循這個慣例。
你可以使用 doc (注意雙下劃線)調(diào)用 printMax 函數(shù)的文檔字符串屬性(屬于函數(shù)的名稱)。請記住 Python 把 每一樣?xùn)|西 都作為對象,包括這個函數(shù)。我們會在后面的類一章學(xué)習(xí)更多關(guān)于對象的知識。
如果你已經(jīng)在 Python 中使用過 help(),那么你已經(jīng)看到過 DocStings 的使用了!它所做的只是抓取函數(shù)的 doc 屬性,然后整潔地展示給你。你可以對上面這個函數(shù)嘗試一下——只是在你的程序中包括 help(printMax)。記住按 q 退出 help。
自動化工具也可以以同樣的方式從你的程序中提取文檔。因此,我 強烈建議 你對你所寫的任何正式函數(shù)編寫文檔字符串。隨你的 Python 發(fā)行版附帶的 pydoc 命令,與 help()類似地使用 DocStrings。
我們已經(jīng)學(xué)習(xí)了函數(shù)的很多方面的知識,不過注意還有一些方面我們沒有涉及。然而,我們已經(jīng)覆蓋了大多數(shù)在日常使用中,你可能用到的 Python 函數(shù)知識。
接下來,我們將學(xué)習(xí)如何創(chuàng)建和使用 Python 模塊。