函式(Function)是指可重復使用的程式片段,它們允許你為某個代碼塊賦予名字,允許你 通過這一特殊的名字在你的程式任何地方來運行代碼塊,并可重復任何次數,這就是所謂的 呼叫函式,
我們已經使用過了許多內置的函式,例如 len 和 range ,
函式可以通過關鍵字 def 來定義,這一關鍵字后跟一個函式的識別符號名稱,再跟一對圓括 號,其中可以包括一些變數的名稱,再以冒號結尾,結束這一行,
隨后而來的陳述句塊是函式 的一部分,下面的案例將會展示出這其實非常簡單:
def say_hello():
# 該塊屬于這一函式
print('hello world')
# 函式結束
say_hello() # 呼叫函式
say_hello() # 再次呼叫函式
輸出:
hello worldhello world
它是如何作業的
我們以上文解釋過的方式定義名為 say_hello 的函式,這個函式不使用引數,因此在括號中 沒有宣告變數,函式的引數只是輸入到函式之中,以便我可以傳遞不同的值給它,并獲得相 應的結果,
要注意到我們可以兩次呼叫相同的函式,這意味著我們不必重新把代碼再寫一次,
函式引數
函式中的引數通過將其放置在用以定義函式的一對圓括號中指定,并通過逗號予以分隔,當 我們呼叫函式時,我們以同樣的形式提供需要的值,要注意在此使用的術語——在定義函式 時給定的名稱稱作“形參”(Parameters),在呼叫函式時你所提供給函式的值稱作“實 參”(Arguments),
def print_max(a, b):
if a > b:
print(a, '是比較大的數')
elif a == b:
print(a, '等于', b)
else:
print(b, '是比較大的數')
# 直接傳遞字面值
print_max(3, 4)
x = 5
y = 7
輸出
4 是比較大的數7 是比較大的數
它是如何作業的
在這里,我們將函式命名為 print_max 并使用兩個引數分別稱作 a 和 b ,我們使用一個 簡單的 if...else 陳述句來找出更大的那個數,并將它列印出來,
第一次呼叫函式 print_max 時,我們以實參的形式直接向函式提供這一數字,
在第二次呼叫 時,我們將變數作為實參來呼叫函式,print_max(x, y) 將使得實參 x 的值將被賦值給形參 a ,而實參 y 的值將被賦值給形參 b ,在兩次呼叫中, print_max 都以相同的方式工 作,
區域變數
當你在一個函式的定義中宣告變數時,它們不會以任何方式與身處函式之外但具有相同名稱 的變數產生關系,也就是說,這些變數名只存在于函式這一區域(Local),
這被稱為變數的 作用域(Scope),
所有變數的作用域是它們被定義的塊,從定義它們的名字的定義點開始,
案例:
x = 50 def func(x): print('x 是:', x) x = 2 print('改變區域變數x為', x)
func(x)
print('x 仍然為', x)
輸出:
x 為:50改變區域變數x為 2x 仍然為 50
它是如何作業的
當我們第一次列印出存在于函式塊的第一行的名為 x 的值時,Python 使用的是在函式宣告 之上的主代碼塊中宣告的這一引數的值,
接著,我們將值 2 賦值給 x ,x 是我們這一函式的區域變數,因此,當我們改變函式中 x 的值的時候,主代碼塊中的 x 則不會受到影響,
隨著最后一句 print 陳述句,我們展示出主代碼塊中定義的 x 的值,由此確認它實際上不受 先前呼叫的函式中的區域變數的影響,
global 陳述句
如果你想給一個在程式頂層的變數賦值(也就是說它不存在于任何作用域中,無論是函式還 是類),那么你必須告訴 Python 這一變數并非區域的,而是全域(Global)的,
我們需要通 過 global 陳述句來完成這件事,因為在不使用 global 陳述句的情況下,不可能為一個定義于 函式之外的變數賦值,
你可以使用定義于函式之外的變數的值(假設函式中沒有具有相同名字的變數),然而,這 種方式不會受到鼓勵而且應該避免,因為它對于程式的讀者來說是含糊不清的,無法弄清楚 變數的定義究竟在哪,
而通過使用 global 陳述句便可清楚看出這一變數是在最外邊的代碼塊 中定義的,
案例:
x = 50
def func():
global x
print('x 為:', x)
x = 2
print('改變全域變數為', x)
func()
print('x的值為', x)
輸出:
x 為: 50改變全域變數為 2x的值為 2
它是如何作業的
global 陳述句用以宣告 x 是一個全域變數——因此,當我們在函式中為 x 進行賦值時,這 一改動將影響到我們在主代碼塊中使用的 x 的值,
你可以在同一句 global 陳述句中指定不止一個的全域變數,例如 global x, y, z ,
默認引數值
對于一些函式來說,你可能為希望使一些引數可選并使用默認的值,以避免用戶不想為他們 提供值的情況,默認引數值可以有效幫助解決這一情況,
你可以通過在函式定義時附加一個 賦值運算子( = )來為引數指定默認引數值,
案例
def say(message, times=1):
print(message * times)
say('Hello')
say('World', 5)
輸出
HelloWorldWorldWorldWorldWorld
它是如何作業的
名為 say 的函式用以按照給定的次數列印一串字串,如果我們沒有提供一個數值,則將按 照默認設定,只列印一次字串,我們通過為引數 times 指定默認引數值 1 來實作這一 點,
在第一次使用 say 時,我們只提供字串因而函式只會將這個字串列印一次,在第二次使 用 say 時,我們既提供了字串,同時也提供了一個引數 5 ,宣告我們希望說(Say)這 個字串五次,
注意
只有那些位于引數串列末尾的引數才能被賦予默認引數值,意即在函式的引數串列中擁 有默認引數值的引數不能位于沒有默認引數值的引數之前,
這是因為值是按引數所處的位置依次分配的,舉例來說, def func(a, b=5) 是有效的, 但 def func(a=5, b) 是無效的,
關鍵字引數
如果你有一些具有許多引數的函式,而你又希望只對其中的一些進行指定,那么你可以通過 命名它們來給這些引數賦值——這就是關鍵字引數(Keyword Arguments)——我們使用命 名(關鍵字)而非位置(一直以來我們所使用的方式)來指定函式中的引數
這樣做有兩大優點
其一,我們不再需要考慮引數的順序,函式的使用將更加容易,
其 二,我們可以只對那些我們希望賦予的引數以賦值,只要其它的引數都具有默認引數值,
案例
def func(a, b=5, c=10):
print('a 是:', a, ' b 是:', b, ' c是:', c)
?
?
func(3, 7)
func(25, c=24)
func(c=50, a=100)
輸出
a 是: 3 b 是: 7 c是:10a 是: 25 b 是: 5 c是:24a 是: 100 b 是: 5 c是:50
它是如何作業的
名為 func 的函式有一個沒有默認引數值的引數,后跟兩個各自帶有默認引數值的引數,
在第一次呼叫函式時, func(3, 7) ,引數 a 獲得了值 3 ,引數 b 獲得了值 7 ,而 c 獲得了默認引數值 10 ,
在第二次呼叫函式時, func(25, c=24) ,由于其所處的位置,變數 a 首先獲得了值 25,然 后,由于命名——即關鍵字引數——指定,變數 c 獲得了值 24 ,變數 b 獲得默認引數值 5 ,
在第三次呼叫函式時, func(c=50, a=100) ,我們全部使用關鍵字引數來指定值,在這里要注 意到,盡管 a 在 c 之前定義,但我們還是我們在變數 a 之前指定了變數 c ,
可變引數
有時你可能想定義的函式里面能夠有任意數量的變數,也就是引數數量是可變的,這可以通 過使用星號來實作
案例
def total(a=5, *numbers, **phonebook):
print('a', a)
?
#遍歷元組中的所有專案
for num in numbers:
print('num項為:', num)
?
#遍歷字典中的所有專案
for key, val in phonebook.items():
print(key,val)
?
print(total(10,1,2,3,Jack=1123,John=2231,Inge=1560))
輸出
a 10num項為: 1num項為: 2num項為: 3Jack 1123John 2231Inge 1560None
它是如何作業的
當我們宣告一個諸如 *param 的星號引數時,從此處開始直到結束的所有位置引數 都將被收集并匯集成一個稱為“param”的元組(Tuple),
類似地,當我們宣告一個諸如 **param 的雙星號引數時,從此處開始直至結束的所有關鍵字 引數都將被收集并匯集成一個名為 param 的字典(Dictionary),
return 陳述句
return 陳述句用于從函式中回傳,也就是中斷函式,我們也可以選擇在中斷函式時從函式中返 回一個值
def maximum(x, y):
if x > y:
return x
elif x == y:
return '兩個數相等'
else:
return y
print(maximum(2, 3))
輸出:
3
它是如何作業的
maximum 函式將會回傳引數中的最大值,在本例中是提供給函式的數值,它使用一套簡單的 if...else 陳述句來找到較大的那個值并將其回傳,
要注意到如果 return 陳述句沒有搭配任何一個值則代表著 回傳 None ,None 在 Python 中一 個特殊的型別,代表著虛無,舉個例子, 它用于指示一個變數沒有值,如果有值則它的值便 是 None(虛無) ,
每一個函式都在其末尾隱含了一句 return None ,除非你寫了你自己的 return 陳述句,你可 以運行 print(some_function()) ,其中 some_function 函式不使用 return 陳述句,就像這 樣:
def some_function():
pass
Python 中的 pass 陳述句用于指示一個沒有內容的陳述句塊,
提示:
有一個名為 max 的內置函式已經實作了“找到最大數”這一功能,所以盡可能地使 用這一內置函式,
DocStrings 檔案字串
Python 有一個甚是優美的功能稱作檔案字串(Documentation Strings),在稱呼它時通常 會使用另一個短一些的名字docstrings,
DocStrings 是一款你應當使用的重要工具,它能夠幫 助你更好地記錄程式并讓其更加易于理解,令人驚嘆的是,當程式實際運行時,我們甚至可 以通過一個函式來獲取檔案!
案例
def print_max(x, y):
'''列印兩個數值中的最大數,
這兩個數都應該是整數'''
?
# 如果可能,將其轉換至整數型別
x = int(x)
y = int(y)
if x > y:
print(x, '大些')
else:
print(y, '大些')
print_max(3, 5)
print(print_max.__doc__)
輸出
5 大些列印兩個數值中的最大數,這兩個數都應該是整數
它是如何作業的
函式的第一行邏輯行中的字串是該函式的 檔案字串(DocString),這里要注意檔案字符 串也適用于后面相關章節將提到的模塊(Modules)與類(Class)
該檔案字串所約定的是一串多行字串,其中第一行以某一大寫字母開始,以句號結束,第二行為空行,后跟的第三行開始是任何詳細的解釋說明,
在此強烈建議你在你所有重要功 能的所有檔案字串中都遵循這一約定,
我們可以通過使用函式的 __doc__ (注意其中的雙下劃綫)屬性(屬于函式的名稱)來獲取 函式 print_max 的檔案字串屬性,只消記住 Python 將所有東西都視為一個物件,這其中 自然包括函式,我們將在后面的類(Class)章節討論有關物件的更多細節,
自動化工具可以以這種方式檢索你的程式中的檔案,因此,我強烈推薦你為你撰寫的所有重 要的函式配以檔案字串,你的 Python 發行版中附帶的 pydoc 命令與 help() 使用檔案字 符串的方式類似,
嵌套函式
python允許創建嵌套函式,也就是說我們可以在函式里面定義函式,而且現有的作用域和變數生存周期依舊不變,
需要注意:1.外部函式的變數可以被內部函式所使用,但不能被內部函式修改,若要修改需要添加關鍵字nonlocal
def max(a,b):
return a if a>b else b
print(max(5,2)) #5
def the_max(x,y,z):
c = max(x,y)
return max(c,z)
?
print(the_max(1,5,3)) #5
輸出
55
嵌套函式作用:
1.封裝-資料隱藏:外部無法訪問“嵌套函式”,
2.減少重復代碼
3.閉包
閉包
啥是閉包?
如果一個函式定義在另一個函式的作用域內,并且參考了外層函式的變數,則該函式稱為閉包,
閉包是Python所支持的一種特性,它讓在非global scope定義的函式可以參考其外圍空間中的變數,這些外圍空間中被參考的變數叫做這個函式的環境變數,
環境變數和這個非全域函式一起構成了閉包,
def outer():
a = 1
def inner():
print(a)
return inner
inn = outer()
inn() #1
閉包特點:
一個函式回傳的函式物件,這個函式物件執行的話依賴非函式內部的變數值,這個時候,函式回傳的實際內容如下:
1 函式物件
2 函式物件需要使用的外部變數和變數值
在函式的外部使用內部函式
總結
我們已經了解了許多方面的函式,但我們依舊還未覆寫到所有型別的函式,不過,我們已經 覆寫到了大部分你每天日常使用都會使用到的 Python 函式,
接下來,我們將了解如何創建并使用 Python 模塊,
IT入門 感謝關注
練習地址:www.520mg.com/it
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/135409.html
標籤:Python
下一篇:08-python中的包與模塊
