今天書接昨天的函數繼續去學習瞭解: 昨天說到函數的動態參數。 1、函數的【動態參數】 2、函數中【\ 和 的魔法運用】 在函數的調用(執行)時, 加一個可迭代對象(列表,元祖,字元串,字典等)代表解包, (列表元祖打散成列表中的每個元素,字元串打散成每個字元,字典打散成每個鍵) 並將元素一 一添加進 ...
今天書接昨天的函數繼續去學習瞭解:
昨天說到函數的動態參數。
1、函數的【動態參數】
*args 動態參數,萬能參數
args接受的就是實參對應的所有剩餘的位置參數,並將其放在元組( )中。
def func(x, y, z, *args):
print(x, y, z)
print(args)
func(1, 2, 'a', 'b', 'c', 34)
1 2 a
('b', 'c', 34)
**kwargs 動態參數
將非位置對應的所有的關鍵字參數放到一個字典{ }中。
(排除形參中位置參數對應的實參中的關鍵字參數)
def func(x, y, z, *args, sex='男', **kwargs):
print(x, y, z)
print(args)
print(sex)
print(kwargs)
func(1, 2, 'a', 'b', 'c', 34, m='yue', n=12, sex='女', p='r')
1 2 a
('b', 'c', 34)
女
{'m': 'yue', 'p': 'r', 'n': 12}
從形參的角度來看,它們的順序應為:
位置參數在最前,*args次之,
預設參數因為形式上是關鍵字參數的式樣故要排在*args後,而要在**kwargs之前。
(位置參數,*args,預設參數,**kwargs)
2、函數中【*和**的魔法運用】
在函數的調用(執行)時,*加一個可迭代對象(列表,元祖,字元串,字典等)代表解包,
(列表元祖打散成列表中的每個元素,字元串打散成每個字元,字典打散成每個鍵)
並將元素一 一添加進args。
如下例:
def func(*args):
return args
l1 = [1, 2, 30]
l2 = [1, 2, 33, 21, 45, 60]
# 要求將l1 和 l2 轉化成元祖,
# 並且裡面包含所有l1和l2的每一個元素,相同元素也得重覆。
# 解:
tu = func(*l1, *l2)
print(tu)
(1, 2, 30, 1, 2, 33, 21, 45, 60)
也可以簡單理解成*是求可迭代對象的每一個元素。
而在函數的定義時,*args代表的是聚合(打包成元祖)
**運用只限於字典(因它存在有鍵值對,可兩兩對應上),
同樣在函數的調用執行時,**dict(一個字典對象),代表將字典所有的鍵值對放到kwargs字典里。
(解包打散字典)
例:
def func(**kwargs):
return kwargs
dic = {'name':'tiele', 'age':18, 'hobby':'下棋'}
dic2 = {'name2':'mao', 'age2':5, 'hobby2':'曬太陽'}
# 字典的鍵得是唯一,如果兩個字典同鍵雖然不同值,執行下麵函數的**運用也會報錯
dic3 = func(**dic, **dic2)
print(dic3)
{'name': 'tiele', 'age': 18, 'hobby2': '曬太陽', 'hobby': '下棋', 'age2': 5, 'name2': 'mao'}
在函數定義時,**kwargs代表的是聚合(成字典)
3、全局命名空間、局部命名空間、內置命名空間
名稱空間:放置變數與對應的值(有的還有記憶體地址對應)的關係;
全局命名空間,放置變數與對應的值(有的還有記憶體地址對應)的關係的名稱空間。
當執行函數的時候,記憶體開闢出一個臨時名稱空間(又叫局部命名空間),存放該函數內的變數與值的關係。
隨著函數的執行完畢,臨時名稱空間也隨之關閉。
內置名稱空間,(python的內置函數),所有的內置函數等存儲的空間。
4、順序與函數的嵌套
載入順序:
內置名稱空間--->全局名稱空間--->(函數執行時)--->局部名稱空間。
取值順序:
剛好與載入順序相反,優先順序為:
局部名稱空間--->全局名稱空間--->內置名稱空間。
函數的嵌套:
函數在被調用的時候才執行;函數裡面同樣代碼遵循從上至下依次執行;
5、作用域
作用域就是作用範圍,按照生效範圍可以分為全局作用域和局部作用域。
全局作用域:包含內置名稱空間、全局名稱空間,在整個文件的任意位置都能被引用、全局有效。
局部作用域:局部名稱空間,只能在局部範圍內生效。
由作用域引申出兩個函數方法globals()和locals()
例:
def func():
a = 33
b = 22
print(locals())
print(globals())
func()
c = 40
print(locals())
{'a': 33, 'b': 22}
{'__name__': '__main__', '__spec__': None, 'func': <function func at 0x0000000000755488>, '__builtins__': <module 'builtins' (built-in)>,
'__cached__': None, '__file__': 'E:/Python/day10/筆記.py', '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x000000000066E048>,
'__doc__': None, '__package__': None}
{'__file__': 'E:/Python/day10/筆記.py',
'__name__': '__main__', '__spec__': None,
'__builtins__': <module 'builtins' (built-in)>,
'__doc__': None, 'c': 40,
'__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x00000000009AE048>,
'__cached__': None, '__package__': None,
'func': <function func at 0x0000000000D85488>}
由上例可以看到,函數中locals存儲的是{'a': 33, 'b': 22}
因為它的作用域是在局部命名空間中,所以它存儲的變數和值並不多,而在函數之外再列印的locals就不同了,它的作用域擴大了,但是不包括局部,所以裡面的值里可以找到'c':40而找不到a,b的值。
在函數中使用locals()方法可以很方便返回在這個臨時命名空間作用域中所有的變數的值,呈字典返回,所以還是有它常用到的地方的。
global關鍵字,nonlocal關鍵字:
global:
1、聲明一個全局變數。
2、在局部作用域想要對全局作用域的全局變數進行修改時,需要用到global(限於字元串,數字)。
例:
a = 2
def func():
a = 5
func()
print(a) #這時候a返回的是2
a = 2
def func():
global a
a = 5
func()
print(a) #使用了global後返回的是5
註:對可變數據類型(list,dict,set)可以直接引用不用通過global。
li = [1,2,3]
dic = {'a':'b'}
def change():
li.append('a')
dic['q'] = 'g'
print(dic)
print(li)
change()
print(li)
print(dic)
{'a': 'b', 'q': 'g'}
[1, 2, 3, 'a']
[1, 2, 3, 'a']
{'a': 'b', 'q': 'g'}
nonlocal:
1、不能修改全局變數。
2、在局部作用域中,對父級作用域(或者更外層作用域非全局作用域)的變數進行引用和修改,並且引用的哪層,從那層及以下此變數全部發生改變。
def add_b():
b = 42
def do_global():
b = 10
print(b)
def dd_nonlocal():
nonlocal b
b = b + 20
print(b)
dd_nonlocal()
print(b)
do_global()
print(b)
add_b()
10
30
30
42
end