函式初識2
-
形參角度
-
3.萬能引數:*args 接受所有的位置引數 ; **args 接受所有的關鍵字引數,定義一個函式時,傳入萬能引數,就可以接收任意的引數(位置實參、關鍵字實參)以供以后為函式添加功能,開放介面,
def func(*args,**kargs): return args,kargs #如此定義一個函式,就可以接收任意的引數(位置實參、關鍵字實參)以供以后為函式添加功能,開放介面,-
知識點補充:
- 撰寫代碼原則:開放封閉原則,代碼對于未來的一些拓展一定是要開放的(具有介面功能)可以添加一些功能,而有時需要對函式傳入的引數的數量不同,需要進行改進,因此需要一種形參,可以接受所有的實參(位置實參,關鍵字實參),即萬能引數(常用*args, **args 表示),
-
‘ * ’的魔術用法:在函式的定義時, 星號代表聚合;在函式的呼叫時,星號代表打散,
-
‘ * ’的聚合:用于萬能形參;約定俗稱萬能形參的形式為'*+args '或' **+kargs ',args與kargs可以換成別的引數,但最好不要換,
-
‘*args’ 可以接受所有位置引數,它將所有的位置實參聚合成一個元祖,將這個元祖賦值給args,
#寫一個函式,計算傳入任意數字的和 def func(*args): c = 0 for i in args: c += i return c print(funs(1,2,3,4,5)) #15 -
‘**kargs’ :可以接受所有的關鍵字實參.在函式的定義時, * *將所有的關鍵字引數聚合成一個一個字典,將這個字典賦值給kargs,
def func(**kargs): print(kargs) funs(number='980173694',massage='歡迎加入百度網盤群') >>>{'number': '980173694', 'massage': '歡迎加入百度網盤群'}
-
-
‘ * ’的打散:在函式的呼叫時 *代表打散,
- 在函式的呼叫時一個*打散的是迭代物件,必須用在可迭代物件上(str,list等)
def func(*args): print(args) funs([1,2,3],[4,5,6]) >>>([1, 2, 3], [4, 5, 6]) funs(*[1,2,3],*[4,5,6]) #*的打散,等同于funs(1, 2, 3, 4, 5, 6) >>>(1, 2, 3, 4, 5, 6) -
在函式的呼叫時兩個*打散的是字典,**
def func(*args,**kargs): print(kargs) print(args) funs({'number': '980173694', 'massage': '歡迎加入百度網盤python學習資源群'}) >>>{} ({'number': '980173694', 'massage': '歡迎加入百度網盤python學習資源群'},) funs(**{'number': '980173694'},**{'massage': '歡迎加入百度網盤python學習資源群'}) #**的打散,等同于funs(number='980173694', massage='歡迎加入百度網盤python學習資源群') >>>{'number': '980173694', 'massage': '歡迎加入百度網盤python學習資源群'} ()
-
-
-
4.僅限關鍵字引數(3.4版本以后):只能接受關鍵字引數,若設定此引數必須給此引數傳入值,否則會報錯,此引數只能在*args與**kargs之間,
def func(*args,a,**args): #a:僅限關鍵字引數 print(a) funs(a = '山就在那兒') >>>山就在那兒
-
-
形參的順序
-
呼叫函式時,會自動從左至右傳入引數,除萬能引數外,實參與形參會一一對應,因此如果形參的順序安排不得當,函式呼叫就會出現問題,甚至會報錯,因此,形參的順序如下:1.位置引數 2.*args 3.默認引數 3. 僅限關鍵字引數 4.**kargs, 讀者可以自行嘗試其他順序,自行找出為什么不能用其他的順序, 僅限關鍵字引數與默認引數可互換,
def func(a,b,*args,sex='男',c,**kargs): pass #a,b:位置引數 c:僅限關鍵字引數
-
-
命稱空間角度:在python解釋器開始執行之后, 就會在記憶體中開辟一個空間, 每當遇到一個變數的時候, 就把變數名和值之間的關系記錄下來, 但是當遇到函式定義的時候, 解釋器只是把函式名讀入記憶體, 表示這個函式存在了, 至于函式內部的變數和邏輯, 解釋器是不關心的. 也就是說一開始的時候函式只是加載進來, 只有當函式被呼叫和訪問的時候, 解釋器才會根據函式內部宣告的變數來進行開辟變數的內部空間,函式中的變數只能在函式內部使用,隨著函式執行完畢, 這些函式內部變數占用的空間也會隨著函式執行完畢而被清空.
我們給這個‘存放名字與值的關系’的空間起了一個名字-------命名空間,
一個py檔案中,存放變數與值的關系的一個空間叫做全域名稱空間,而當執行一個函式時,記憶體中會臨時開辟一個空間,臨時存放函式中的變數與值的關系,這個叫做臨時名稱空間,或者區域名稱空間,
python還有一個空間叫做內置名稱空間:內置名稱空間存放的就是一些內置函式等拿來即用的特殊的變數:input,print,list等等
-
全域名稱空間:代碼在運行伊始,創建的存盤“變數名與值的關系”的空間叫做全域命名空間;
即 我們直接在py檔案中, 函式外宣告的變數都屬于全域命名空間,程式不結束,全域名稱空間不會消失,
-
區域命名空間:在函式的運行中開辟的臨時的空間叫做區域命名空間也叫做臨時名稱空間 ,
即在函式中宣告的變數會放在區域命名空間,函式結束時區域命名空間就會消失,
-
內置名稱空間:存放python解釋器為我們提供的名字, list, tuple, str, int這些都是內置命名空間
-
加載順序:所謂的加載順序,就是這三個空間加載到記憶體的先后順序,也就是這個三個空間在記憶體中創建的先后順序,他們不能能同時創建,在啟動python解釋器之后,即使沒有創建任何的變數或者函式,還是會有一些函式直接可以用的比如abs(-1),max(8,3)等等,在啟動Python解釋器的時候,就已經匯入到記憶體當中供我們使用,所以肯定是先加載內置名稱空間,然后就開始從檔案的最上面向下一行一行執行,此時如果遇到了初始化變數,就會創建全域名稱空間,將這些對應關系存放進去,然后遇到了函式執行時,在記憶體中臨時開辟一個空間,加載函式中的一些變數等等,所以這三個空間的加載順序為:內置命名空間(程式運行伊始加載)->全域命名空間(程式運行中:從上到下加載)->區域命名空間(程式運行中:呼叫時才加載,
-
取值順序:取值順序就是參考一個變數,先從哪一個空間開始參考,這個有一個關鍵點:從哪個空間開始參考這個變數,我們分別舉例說明:
# 如果你在全域名稱空間參考一個變數,先從全域名稱空間參考,全域名稱空間如果沒有,才會向內置名稱空間參考, input = 123 print(input) # 123 # 如果你在區域名稱空間參考一個變數,先從區域名稱空間參考, # 區域名稱空間如果沒有,才會向全域名稱空間參考,全域名稱空間再沒有,就會向內置名稱空間參考, input = 123 print(input) # 123 def func(): input = 111 print(input) # 111 func()所以空間的取值順序與加載順序是相反的,取值順序滿足的就近原則,從小范圍到大范圍一層一層的逐步參考且單向不可逆,即LEGB原則,(L:lcoal E:eclose G:global B:builtin)
-
作用域:作用域就是作用范圍, 按照生效范圍來看分為全域作用域和區域作用域
全域作用域: 包含內置命名空間和全域命名空間. 在整個檔案的任何位置都可以使用(遵循從上到下逐?執行),作?域命名空間:全域作用域: 全域命名空間 + 內置命名空間
區域作用域: 在函式內部可以使用,作?域命名空間:2. 區域作?域: 區域命名空間
區域作用域可以參考全域作用域的變數但不能改變全域變數(當python解釋器讀取到區域作用域時,若發現有對一個變數進行修改的操作,解釋器會認為你在區域已經定義過這個區域變數了,于是就在區域找這個區域變數,若沒有就會報錯,無法改變全域變數),全域作用域不可義參考區域作用域的變數,
-
-
內置函式: globals() local() 注意與關鍵字(global、nonlocal)的區別,詳細請看明天的python基礎學習day11,
globals(): 以字典的形式回傳全域作用域(內置命稱空間以及全域命稱空間的所有內容)所有的變數對應關系,
locals(): 以字典的形式回傳當前作用域的變數所有的對應關系,
a = 1 b = 2 print(globals()) >>>{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000294B739F788>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/PycharmProjects/untitled/texr3/題.py', '__cached__': None, 'a': 1, 'b': 2} print(locals()) >>>{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000001BC4C41F788>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': 'D:/PycharmProjects/untitled/texr3/題.py', '__cached__': None, 'a': 1, 'b': 2} # 在區域作用域中列印, a = 1 b = 2 def func(): c = 3 print(globals()) # 和上面一樣,還是全域作用域的內容 print(locals()) # {'c': 3} funs() -
函式的嵌套(高階函式):有串列的嵌套:串列的嵌套就是一個串列中還有串列,可能那個串列中還有串列......那么顧名思義,函式的嵌套,就是一個函式中,還有函式,
關鍵點:只要遇見了函式名+()就是函式的呼叫. 如果沒有就不是函式的呼叫,那么現在舉例練習:請說出下面代碼的執行順序:
#例1: def func1(): print('in func1') print(3) def func2(): print('in func2') print(4) func1() print(1) func2() print(2) # 例2: def func1(): print('in func1') print(3) def func2(): print('in func2') func1() print(4) print(1) func2() print(2) # 例3: def func2(): print('1in func2') def func3(): print('in func3') print('2in func2') func3() print('3in func2') print(3) func2() print(5)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/169426.html
標籤:Python
