1、函數的動態參數 *args,**kwargs, 形參的順序
一、你的函數,爲了拓展,對於傳入的實參數量應該是不固定,
因此就須要用到萬能參數,動態參數,*args, **kwargspython
1,*args 將全部實參的位置參數聚合到一個元組,並將這個元組賦值給args
(起做用的是* 並非args,可是約定俗成動態接收實參的全部位置參數就用args)app
def sum1(*args): print(args) sum1(1,2,['hello']) #是一個元組(1, 2, ['hello'])
2,**kwargs 將全部實參的關鍵字參數聚合到一個字典,並將這個字典賦值給kwargs
(起做用的是** 並非kwargs,可是約定俗成動態接收實參的全部關鍵字參數就用kwargs)函數
def fun(*args,**kwargs): print(args) print(kwargs) fun(1,2,['a','b'],name='xiaobai',age=18) # 結果: # (1, 2, ['a', 'b']) #位置參數,元組 # {'name': 'xiaobai', 'age': 18} #關鍵字參數,字典
二、*的用法
在函數的定義時,*位置參數,**關鍵字參數--->聚合。
在函數的調用(執行)時,*位置參數,**關鍵字參數--->打散。post
實參--->*位置參數--->把位置參數打散成最小的元素,而後一個個添加到args裏組成一個元組this
l1 = [1,2,3] l2 = [111,22,33,'xiaobai'] #若是要將l1,l2經過函數整合到一塊兒 # 方法一(實參不用*): def func1(*args): return args[0] + args[1] print(func1(l1,l2)) #[1, 2, 3, 111, 22, 33, 'xiaobai'] # 方法二(實參用*): def func1(*args): return args print(func1(*l1,*l2)) #(1, 2, 3, 111, 22, 33, 'xiaobai')
實參--->**關鍵字參數--->把關鍵字參數打散成最小的元素,而後一個個添加到kwargs裏組成一個字典spa
def func1(**kwargs): print(kwargs) #func1(name='xiaobai',age=18,job=None,hobby='girl') func1(**{'name':'xiaobai','age':18},**{'job':None,'hobby':'girl'}) # 結果: # {'name': 'xiaobai', 'age': 18, 'job': None, 'hobby': 'girl'}
三、形參的順序(a--->b,表明的順序是寫參數時,要先寫a再寫b)
位置參數--->默認參數code
def func(a,b,sex='男'): print(sex) func(100,200)
位置參數--->*args--->默認參數blog
def func(a,b,*args,sex='男'): print(a,b) print(args) print(sex) func(100,200,1,2,34,5,'女',6) # 結果: # 100 200 #a,b # (1, 2, 34, 5,'女',6) #args # 男 #默認參數
位置參數--->*args--->默認參數--->**kwargs內存
def func(a,b,*args,sex='男',**kwargs): print(a,b) print(args) print(sex) print(kwargs) func(100,200,1,2,34,5,6,sex='女',name='xiaobai',age=1000) func(100,200,1,2,34,5,6,name='xiaobai',age=1000,sex='女') # 兩個的結果都是: # 100 200 #a,b # (1, 2, 34, 5, 6) #args # 女 #默認參數修改後的值 # {'name': 'xiaobai', 'age': 1000} #kwargs # 如果形參這樣寫: def func(a,b,*args,**kwargs,sex='男'): print(a,b) print(args) print(sex) print(kwargs) func(100,200,1,2,34,5,6,name='xiaobai',age=1000,sex='女') # 結果:會報錯,默認參數必定要寫在kwargs前面
2、命名空間,臨時命名空間,做用域,取值順序,加載順序等
'''
咱們首先回憶一下Python代碼運行的時候遇到函數是怎麼作的,從Python解釋器開始執行以後,就在內存中開闢裏一個空間,每當遇到一個變量的時候,
就把變量名和值之間對應的關係記錄下來,可是當遇到函數定義的時候,解釋器只是象徵性的將函數名讀入內存,表示知道這個函數存在了,至於函數內部的變量和邏輯,解釋器根本不關心。
等執行到函數調用的時候,Python解釋器會再開闢一塊內存來儲存這個函數裏面的內容,這個時候,才關注函數裏面有哪些變量,而函數中的變量會儲存在新開闢出來的內存中,
函數中的變量只能在函數內部使用,由於隨着函數執行完畢,這塊內存中的全部內容也會被清空。作用域
咱們給這個‘存放名字與值的關係’的空間起了一個名字-------命名空間。
代碼在運行開始,建立的存儲「變量名與值的關係」的空間叫作全局命名空間;
在函數的運行中開闢的臨時的空間叫作局部命名空間。
'''
一、python中,命名空間分三種:
1,全局命名空間
2,局部命名空間(臨時)
3,內置命名空間
*內置命名空間中存放了python解釋器爲咱們提供的名字:input,print,str,list,tuple...它們都是咱們熟悉的,拿過來就能夠用的方法。
二、做用域:
1,全局做用域:全局命名空間 內置命名空間
2,局部做用域:局部命名空間(臨時)
三、取值順序: 就近原則(LEGB)
局部命名空間 ----> 全局命名空間 ----->內置命名空間 單向 從小到大範圍
也就是說:
在局部調用時取值順序是:局部命名空間->全局命名空間->內置命名空間
在全局調用時取值順序是:全局命名空間->內置命名空間
len = 6 #設置全局變量 並且len也在內置命名空間中
def func1():
len = 3 #設置局部變量
return len
print(func1()) #返回的len值是局部命名空間的值:3
四、加載順序
內置命名空間(程序運行前加載) ----> 全局命名空間(程序運行中:從上到下加載) --- > 局部命名空間(當函數調用的時候)
3、global,nonlocal
一、在局部命名空間 能夠引用全局命名空間的變量,可是不能改變它的值。
count = 1
def func1():
print(count)
func1() #引用全局命名空間的變量,結果爲:1
count = 1
def func1():
count += 1
print(count)
func1() #會報錯,由於在局部命名空間中不能直接修改全局命名空間的變量
#若是你在局部名稱空間對一個變量進行修改,那麼解釋器會認爲你的這個變量在局部中已經定義了,
#可是對於上面的例題,局部中沒有定義,因此就會報錯。
二、global:
1,在局部命名空間聲明一個全局變量。
2,在局部做用域想要對全局做用域的全局變量進行修改時,須要用到global(限於字符串,數字)。
例子:
def fun(): global a #聲明瞭一個全局變量a。 a = 3 fun() #調用函數後,就生成了全局變量a,不會由於函數的結束而釋放掉。 print(a) # 3 count = 1 #全局變量count def fun(): global count #在局部做用域想要對全局做用域的全局變量進行修改時,用global聲明。 count += 1 fun() print(count) # 2
ps:對於在全局命名空間的可變數據類型(list,dict,set)能夠直接引用並修改不用經過global。
可是函數內部(局部命名空間)的可變數據類型在沒有global的聲明下,全局命名空間也是不能夠調用的。
li = [1, 2, 3] # 全局命名空間的可變數據類型 dic = {'name': 'sb'} def change(): li.append('hello') # 在局部命名空間直接引用並修改 dic['age'] = 18 change() print(li) # [1, 2, 3, 'hello'] print(dic) # {'name': 'sb', 'age': 18} def fun(): l1 = [1, 2, 3] # 局部名稱空間的可變數據類型 fun() l1.append(4) print(l1) # 報錯,name 'l1' is not defined def fun(): global l1 # 局部名稱空間用global聲明可變數據類型 l1 l1 = [1, 2, 3] fun() l1.append(4) print(l1) # [1, 2, 3, 4]
三、nonlocal
1,此變量聲明的變量不能是全局變量,它不能修改全局變量。
2,子函數對父函數的變量進行修改。(在局部做用域中,對父級做用域(或者更外層做用域非全局做用域)的變量進行引用和修改,而且引用的是哪一層,就從那一層及如下此變量所有發生改變。)
例子:
def func1(): count = 666 def inner(): print(count) def func2(): nonlocal count #這裏若是不聲明nonlocal,那麼能夠引用父函數的conut值,可是不能修改不然就會報錯 count += 1 print('func2',count) func2() print('inner',count) inner() print('func1',count) func1() # 666 func2 667 inner 667 func1 667
4、函數的嵌套
一、函數的嵌套定義
def f1(): print("in f1") def f2(): print("in f2") f2() f1() #in f1 #in f2 def f1(): def f2(): def f3(): print("in f3") print("in f2") f3() print("in f1") f2() f1() #in f1 #in f2 #in f3
二、函數的嵌套調用
def max1(x,y): m = x if x>y else y return m def max2(a,b,c,d): res1 = max1(a,b) res2 = max1(res1,c) res3 = max1(res2,d) return res3 print(max2(23,-7,31,11)) # 31