一:可變長參數(shù)
可變長指的是參數(shù)的個數(shù)不固定
站在實參的角度,實參是用來為形參賦值的砾莱,如果實參的個數(shù)不固定,那么必須要有對應(yīng)的形參能夠接收溢出實參
*與*在形參與實參中的應(yīng)用
在形參中用*與*
1.1 在形參名前加 *:* 會把溢出的位置實參存成元組聚假,然后賦值其后的形參名
def func(x,*y): # y=(2,3,4)
print(x)
print(y)
func(1,2,3,4)
func(1)
func() # 位置形參x必須被傳值
'''示范:'''
def add(*nums):
res = 0
for num in nums:
res += num
return res
res=add(1, 2, 3)
print(res)
1.2 在形參名前加**:**會把溢出的關(guān)鍵字實參存成字典闰非,然后賦值其后的形參名
def func(x, **y): # y=(2,3,4)
print(x)
print(y)
func(1,a=111,b=222,c=333)
func(a=111, b=222, x=1, c=333)
在實參中用\*與\**
def func(x, y, z):
print(x, y, z)
1.3 在實參前加*:*會把其后的值打散成位置實參
nums = [1, 2, 3]
func(*nums) # func(1,2,3)
# 若只有一個形參,則多余出來的值沒處放瘪贱,會出錯
def fun(x)
print(x)
1.4 在實參前加 **:**會把其后的值打散關(guān)鍵字實參
dic = {'y': 111, 'z': 222, 'x': 333}
func(**dic) # func(y=111,z=222,x=333)
'''
在形參與實參中混用*與**
'''
'''
同時使用*與**的作用是可以把外部傳的值原封不動的傳給另一個函數(shù),這在閉包函數(shù)甜害,裝飾器中有很大作用
'''
def index(x,y,z,a,b,c):
print("index===>",x,y,z,a,b,c)
def wrapper(*args, **kwargs): # args=(1, 2, 3,) kwargs={"a":111,"b":222,"c":333}
index(*args, **kwargs) # index(*(1, 2, 3,),**{"a":111,"b":222,"c":333})
# index(1,2,3,c=333,b=222,a=111)
wrapper(1, 2, 3, a=111, b=222, c=333)
函數(shù)參數(shù)總結(jié):
# def func(x,y=222,*args,**kwargs):
# pass
# 命名關(guān)鍵字形參(了解即可)
def func(x, y=222, *args, n=777,m, **kwargs): # m,n必須按照關(guān)鍵字實參的格式為其賦值
print(x) # 1
print(y) # 2
print(args) # (3,4,5)
print("m===>", m)
print("n===>", n)
print(kwargs)
func(1, 2, 3, 4, 5, n=88888,m=6666666, a=11, b=22, c=33)
二、函數(shù)對象
函數(shù)對象指的是函數(shù)可以被當(dāng)成變量去使用
def foo(): # foo = 函數(shù)的內(nèi)存地址
print('from foo')
1 可以被賦值
f = foo
print(f is foo)
f()
2 可以當(dāng)作參數(shù)傳給一個函數(shù)
def bar(func):
print(func)
func()
bar(foo)
3 可以當(dāng)成一個函數(shù)的返回值
def bar(func):
return func
res=bar(foo)
print(res)
4 可以當(dāng)成容器類型的元素
l = [foo]
print(l)
l[0]()
示例:當(dāng)我們的主函數(shù)是由多個其他函數(shù)組成河哑,即我們需要使用許多的if來判斷用戶輸入且調(diào)用對應(yīng)的函數(shù)時候,可以使用這種容器的方法,使得代碼量減少,同時铸抑,在面試時刁憋,若被問到如何減少if操作時,可使用字典替換
def login():
print('登錄功能......')
def withdraw():
print('提現(xiàn)功能......')
def transfer():
print('轉(zhuǎn)賬功能......')
def recharge():
print('充值功能')
func_dic={
"1": [login,"登錄"],
"2": [withdraw,"提現(xiàn)"],
"3": [transfer,"轉(zhuǎn)賬"],
"4": [recharge,"充值"]
}
func_dic["1"][0]()
while True:
print("0 退出")
for k in func_dic:
print("%s %s" %(k,func_dic[k][1]))
choice = input("請輸入你的指令編號: ").strip()
if choice == "0":
break
if choice in func_dic:
func_dic[choice][0]()
else:
print('輸入的指令不存在')
三泥耀、函數(shù)嵌套
1 函數(shù)的嵌套調(diào)用
def bar():
print('from bar')
def foo():
print('from foo')
bar()
foo()
案例:
def max2(x,y):
if x > y:
return x
else:
return y
def max4(a,b,c,d):
res1 = max2(a,b)
res2 = max2(res1,c)
res3 = max2(res2,d)
print(res3)
max4(1,2,3,4)
2 函數(shù)的嵌套定義
def f1():
print('from f1')
# f2 = 函數(shù)的內(nèi)存地址
def f2():
print("from f2")
f1()
定義在函數(shù)內(nèi)的函數(shù)特點是: 正常情況只能在函數(shù)體內(nèi)調(diào)用
from math import pi
def circle(radius,mode=0):
def perimiter(radius):
return 2 * pi * radius
def area(radius):
return pi * (radius ** 2)
if mode == 0:
return perimiter(radius)
elif mode == 1:
return area(radius)
res1=circle(3,0)
res2=circle(3,1)
print(res1)
print(res2)
-------------------------
18.84955592153876
28.274333882308138
def func():
x = 10
print(x)
def f2():
print('from f2')
f2()
func()
print(x)
---------------------------------
Traceback (most recent call last):
File "xxx", line 122, in <module>
print(x)
NameError: name 'x' is not defined
10
from f2
四、名稱空間與作用域
'''
名稱空間:就是存放名字的地方
名(函數(shù)名扫皱、變量名等):存放在內(nèi)存里
值(變量值等):存放在內(nèi)存里
通過劃分出各個名字空間段多,允許在不同的空間內(nèi)觉啊,可以有相同的名字
1缀程、內(nèi)置名稱空間:存放內(nèi)置的名字(python解釋器啟動時便定義好的)如 print摆昧、input、len
生命周期:解釋器啟動則產(chǎn)生,解釋器關(guān)閉則銷毀 (python解釋器在pyhton程序執(zhí)行時運行帝洪,執(zhí)行結(jié)束時結(jié)束)
2、全局名稱空間:存放的是頂級的名字
生命周期:python程序運行時則產(chǎn)生,python程序結(jié)束則銷毀
3、局部名稱空間:函數(shù)內(nèi)的名字
只有調(diào)用函數(shù)時,局部名字才產(chǎn)生,定義函數(shù)時,并不會產(chǎn)生,因為代碼并未執(zhí)行
生命周期:調(diào)用函數(shù)時產(chǎn)生,函數(shù)調(diào)用結(jié)束則銷毀
訪問 同名名字的優(yōu)先級:局部>全局>內(nèi)置
從當(dāng)前位置往外查找
名字的查找優(yōu)先級:
從當(dāng)前位置往外查找,如果當(dāng)前是在局部:局部名稱空間->全局名稱空間->內(nèi)置名稱空間
從當(dāng)前位置往外查找,如果當(dāng)前是在全局:全局名稱空間->內(nèi)置名稱空間
'''
1 內(nèi)置名稱空間: 存放的是內(nèi)置的名字,如print\input\len
生命周期: 解釋器啟動則產(chǎn)生,解釋器關(guān)閉則銷毀
2 全局名稱空間: 存放的是頂級的名字
生命周期: python程序運行時則產(chǎn)生,python程序結(jié)束則銷毀
x = 10
def func():
x = 111
print(x)
if 1:
y = 6666
3 局部名稱空間:函數(shù)內(nèi)的名字
生命周期: 調(diào)用函數(shù)時則產(chǎn)生,函數(shù)調(diào)用結(jié)束則銷毀
名字的查找優(yōu)先級:
從當(dāng)前位置往外查找,如果當(dāng)前是在局部:局部名稱空間->全局名稱空間->內(nèi)置名稱空間
從當(dāng)前位置往外查找,如果當(dāng)前是在全局:全局名稱空間->內(nèi)置名稱空間
示范1:
def func():
len = 222
# print(len)
# len = 111
func()
print(len)
名稱空間可以理解為一層套一層的關(guān)系,問題是嵌套關(guān)系是在函數(shù)定義階段生成的,還是在函數(shù)調(diào)用階段生成的?
x = 111
def foo():
print(x)
def bar(f):
x=222
f()
bar(foo)
一個非常重要的結(jié)論:名稱空間的嵌套關(guān)系是函數(shù)定義階段(即掃描語法時)就固定死的,與函數(shù)的調(diào)用位置無關(guān)
x = 111
def func():
print(x)
x=2222
func()
練習(xí)
x=0
def f1():
# x=1
def f2():
# x=2
print(x)
f2()
f1()
len = 111
def f1():
len=2222
def f2():
len=3333
f1()
f2()
全局范圍/全局作用域:內(nèi)置名稱空間+全局名稱空間
特點:全局存活,全局有效
局部范圍/局部作用域:局部名稱空間
特點:臨時存活,局部有效
了解:
global(****) 在局部名稱空間中指定某個變量為全局變量
nonlocal(***)
案例1
x = 10
def func(x): # x = 值10的內(nèi)存地址
# x = 值10的內(nèi)存地址
x = 20
func(x) # func(值10的內(nèi)存地址)
print(x)
案例2
x = [11,22,33]
def func(x): # x = 列表[11,22,33]的內(nèi)存地址
# x = 列表[11,22,33]的內(nèi)存地址
# x=444444444444
x[0] = 66666
func(x) # func(列表[11,22,33]的內(nèi)存地址)
print(x)
案例3
x = [11,22,33]
def func():
x[0] = 66666
func()
print(x)
案例4
x = 10
def func():
global x
x=22
func()
print(x)
案例5:nonlocal生命名字是來自于外層函數(shù)的(了解)
x = 10
def f1():
x=111
def f2():
nonlocal x
x=222
f2()
print(x)
f1()
print(x)