1.函數的動態參數 1.1 動態接收位置參數 在參數位置用 表示接受任意參數 動態接收參數的時候要註意: 動態參數必須在位置參數後面 args 是 萬能(接受任意多個)的位置參數, 在函數定義的時候叫做 聚合 動態接收參數的時候要註意:動態參數必須在位置參數後面 優先順序:位置參數 動態位置參數 1. ...
1.函數的動態參數
1.1 動態接收位置參數
在參數位置用*表示接受任意參數
def eat(*args):
print('我想吃',args)
eat('蒸羊羔','蒸熊掌','蒸鹿尾兒','燒花鴨','燒雛雞','燒子鵝','滷豬','滷鴨','醬雞','腊肉','松花小肚兒','晾肉','香腸兒') # 收到的結果是一個tuple元祖
動態接收參數的時候要註意: 動態參數必須在位置參數後面
def eat(*args):
print('我想吃',args,a,b)
eat('蒸羊羔','蒸熊掌','蒸鹿尾兒','燒花鴨','燒雛雞','燒子鵝','滷豬','滷鴨','醬雞','腊肉','松花小肚兒','晾肉','香腸兒')
結果:
TypeError: eat() missing 2 required keyword-only arguments: 'a' and 'b'
# eat函數在調用的時候發現缺少倆個位置參數沒有進行傳遞
# 把所有的位置參數都給接受了,a和b接收不到值,所有會報錯.
def eat(a,b,*args):
print('我想吃',args,a,b)
eat('蒸羊羔','蒸熊掌','蒸鹿尾兒','燒花鴨','燒雛雞','燒子鵝','滷豬','滷鴨','醬雞','腊肉','松花小肚兒','晾肉','香腸兒')
結果:
我想吃 ('蒸鹿尾兒', '燒花鴨', '燒雛雞', '燒子鵝', '滷豬', '滷鴨', '醬雞', '腊肉', '松花小肚兒', '晾肉', '香腸兒') 蒸羊羔 蒸熊掌
def func(a,b,*args):
print(a,b,args) #*args 是 萬能(接受任意多個)的位置參數, *在函數定義的時候叫做聚合
print(*args) # 在這一行 *args作用是 打散
args 是 萬能(接受任意多個)的位置參數, 在函數定義的時候叫做聚合
動態接收參數的時候要註意:動態參數必須在位置參數後面
優先順序:位置參數 > 動態位置參數
1.2 動態接收關鍵字參數
在python中可以動態的位置參數,但是*這種情況只能接收位置參數無法接收關鍵字參數,在python中使用**來接收動態關鍵字參數
def func(**kwargs):
print(kwargs)
func(a=1, b=2, c=3)
結果:
{'a': 1, 'b': 2, 'c': 3} #dict字典形式
動態關鍵字參數最後獲取的是一個dict字典形式
位置參數必須在關鍵字參數前面.動態接收關鍵字參數也要在後面
倆個動態參數:
def trans_para(*args,**kwargs):
print(args,type(args)) # args是元祖形式
print(kwargs,type(kwargs)) # kwargs接收的只是鍵值對的參數,並保存在字典中。
trans_para("jinxin",12,[1,2,3,4],[3,4,],(1,4,7),{"a":"123","c":456},country="china")
結果:
('jinxin', 12, [1, 2, 3, 4], [3, 4], (1, 4, 7), {'c': 456, 'a': '123'}) <class 'tuple'>
{'country': 'china'} <class 'dict'>
動態參數,也叫不定長傳參,就是你需要傳給函數的參數很多,不定個數,那這種情況下,你就用*args,**kwargs接收,args是元祖形式,接收除去鍵值對以外的所有參數,kwargs接收的只是鍵值對的參數,並保存在字典中。
*args和 **kwargs
args是元祖形式,kwargs是字典形式
最終順序:
位置參數 > *args(動態位置參數) > 預設值參數 > **kwargs(動態預設參數)
如果想接收所有的參數:
def func(*args,**kwargs):
print(args,kwargs)
print(*args,*kwargs) #*args為把元組打散,*kwargs為字典的keys
func(1,23,5,a=1,b=6)
結果:
(1, 23, 5) {'a': 1, 'b': 6}
1 23 5 a b
動態參數還可以這樣傳參:
lst = [1,4,7]
# 方法一
def func(*args):
print(args)
func(lst[0],lst[1],lst[2]) # (1, 4, 7)
# 方法二
def func(*args):
print(args)
func(*lst) # (1, 4, 7)
# 在實參的位置上用*將lst(可迭代對象)按照順序打散
# 在形參的位置上用*把收到的參數組合成一個元祖
字典也可以進行打散,不過需要**
dic = {'a':1,'b':2}
lst = [1,2,3,4,5,6,7,81]
def func(*args,**kwargs):
print(args)
print(kwargs)
func(*lst,**dic)
結果:
(1, 2, 3, 4, 5, 6, 7, 81)
{'a': 1, 'b': 2}
2.函數的註釋
# 函數的註釋
def func(*args,**kwargs):
'''
#很重要 寫函數一定要寫註釋
:param args: 要標識的內容
:param kwargs: 要標識的內容
:return: 要標識的內容
'''
pass
# 函數名.__doc__ 查看函數的註釋
# 函數名.__name__ 查看函數名(在學反射的時候使用)
3.名稱空間
在python解釋器開始執行之後, 就會在記憶體中開闢一個空間, 每當遇到一個變量的時候, 就把變量名和值之間的關係記錄下來, 但是當遇到函數定義的時候, 解釋器只是把函數名讀入記憶體, 表示這個函數存在了, 至於函數內部的變量和邏輯, 解釋器是不關心的. 也就是說一開始的時候函數只是載入進來, 僅此而已, 只有當函數被調用和訪問的時候, 解釋器才會根據函數內部聲明的變量來進行開闢變量的內部空間. 隨著函數執行完畢, 這些函數內部變量占用的空間也會隨著函數執行完畢而被清空.
def fun():
a = 10
print(a)
fun()
print(a) # a不存在了已經..
我們給存放名字和值的關係的空間起一個名字叫: 命名空間. 我們的變量在存儲的時候就 是存儲在這片空間中的.
命名空間分類:
- 全局命名空間--> 我們直接在py文件中, 函數外聲明的變量都屬於全局命名空間
- 局部命名空間--> 在函數中聲明的變量會放在局部命名空間
- 內置命名空間--> 存放python解釋器為我們提供的名字, list, tuple, str, int這些都是內置命名空間
載入順序:
- 內置命名空間
- 全局命名空間
- 局部命名空間(函數被執行的時候)
取值順序:
- 局部命名空間
- 全局命名空間
- 內置命名空間
a = 10
def func():
a = 20
print(a)
func() # 20
作用域: 作用域就是作用範圍, 按照生效範圍來看分為 全局作用域 和 局部作用域
全局作用域: 包含內置命名空間和全局命名空間. 在整個文件的任何位置都可以使用(遵循 從上到下逐⾏執行).
局部作用域: 在函數內部可以使用.
作⽤域命名空間:
- 全局作用域: 全局命名空間 + 內置命名空間
- 局部作用域: 局部命名空間
我們可以通過globals()函數來查看全局作⽤用域中的內容,也可以通過locals()來查看局部作 ⽤用域中的變數量和函數信息
a = 10
def func():
a = 40
b = 20
print("哈哈")
print(a, b)
print(globals()) # 列印全局作用域中的內容
print(locals()) # 列印當前作用域中的內容
func()
4.函數嵌套
- 只要遇見了()就是函數的調用. 如果沒有()就不是函數的調用
- 函數的執行順序
def fun1():
print(111)
def fun2():
print(222)
fun1()
fun2()
print(111)
def fun2():
print(222)
def fun3():
print(666)
print(444)
fun3()
print(888)
print(33)
fun2()
print(555)
5.global nonlocal (很重要)
首先我們寫這樣一個代碼, 首先在全局聲明一個變量, 然後再局部調用這個變量, 並改變這 個變量的值
a = 100
def func():
global a # 加了個global表示不再局部創建這個變量了. 而是直接使用全局的a
a = 28
print(a)
func()
print(a)
結果:
100
28
global表示不再使用局部作用域中的內容了. 而改用全局作用域中的變量
2.1global 宗旨
在函數內部修改全局的變數,如果全局中不存在就創建一個變數
lst = ["周道鎔", "章超印", "楊紅興"]
def func():
lst.append("朱凡宇")
# 對於可變數據類型可以直接進行訪問
print(lst)
func()
print(lst)
2.2 nonlocal宗旨
nonlocal 只修改上一層變數,如果上一層中沒有變數就往上找一層,只會找到函數的最外層,不會找到全局進行修改
a = 10
def func1():
a = 20
def func2():
nonlocal a
a = 30
print(a)
func2()
print(a)
func1()
結果:
加了nonlocal
30
30
不加nonlocal
30
20
再看, 如果嵌套了很多層, 會是一種什麼效果:
a = 1
def fun_1():
a = 2
def fun_2():
nonlocal a
a = 3
def fun_3():
a = 4
print(a)
print(a)
fun_3()
print(a)
print(a)
fun_2()
print(a)
print(a)
fun_1()
print(a)
# 這樣的程式如果能分析明白. 那麼作用域, global, nonlocal就沒問題了
6.其他
三元運算符
a = 10
b = 30
c = a if a > b else b
print(c)
結果:
30
enumerate() #枚舉
lst = [11,22,33,44,55,66]
for i,j in enumerate(lst):
print(i,j)
結果:
0 11
1 22
2 33
3 44
4 55
5 66
元組和字典打散:
tu = (1,2,3,4,5,6)
dic = {1:2,2:4}
print(*tu)
print(*dic)
結果:
1 2 3 4 5 6
1 2
一日總結:
# 1.函數的動態參數
# *args,**kwargs (能夠接受動態的位置參數和動態的關鍵字參數)
# 定義階段(*args,**kwargs) 聚合
# *args - tuple
# **kwargs -- dict
# 使用階段*args,*kwargs 打散
# *args - 源數據類型
# *kwargs - 打散是字典的鍵
# 優先順序: 位置 > 動態位置> 預設 > 動態關鍵字
# lst = [12,23,3,4,5,6]
# def func(*args):
# print(*args)
# func(lst[0],lst[1]) # 笨的辦法
# func(*lst)
# dic = {"key":1,"key1":34}
# def func(**kwargs):
# print(kwargs)
# func(**dic)
# 2.函數的註釋
"""
每次寫函數的時候需要寫註釋
函數名.__doc__
函數名.__name__
"""
# 3.名稱空間
# 內置空間: python解釋器自帶的
# 全局空間:當前文件(.py文件)
# 局部空間:函數體開闢的空間
# 載入順序: 內置 > 全局> 局部
# 取值順序: 局部 > 全局 > 內置
# 作用域:
# 全局作用域 內置 + 全局
# 局部作用域: 局部
# 4.函數嵌套
# 函數中套函數
# 函數嵌套調用
# 函數嵌套參數的傳遞
# 函數嵌套返回值的傳遞
# 5.global nonlocal
# global : 修改全局空間的變數對應的值
# nonlocal :在外層的函數中,修改局部空間的變數值.完全不涉及全局變數,
# 只修改離它最近的一層,最近的一層沒有變數繼續向上找,直到找到最外層函數
# 6.三元運算符
# a = 10
# b = 20
# c = a if a> b else b
# 變數名 = 條件成立的結果 條件 條件不成立的結果