*與**在形參與實參中的應用,函式的物件,函式的巢狀,名稱空間與作用域
阿新 • • 發佈:2020-07-20
一、*與**在形參與實參中的應用
1、可變長引數
可變長指的是引數的個數不固定
站在實參的角度,實參是用來為形參賦值的,如果實參的個數不固定,那麼必須要有對應的形參能夠接收溢位實參
2、在形參中用*與**
2.1 在形參名前加*:*會把溢位的位置實參存成元組,然後賦值其後的形參名
def func(x,*y): # y=(2,3,4)
print(x)
print(y)
func(1,2,3,4) #y打印出來(2,3,4)
func(1) #y打印出來()
func() # 報錯,位置形參x必須被傳值
2.2 在形參名前加**:**會把溢位的關鍵字實參存成字典,然後賦值其後的形參名
def func(x, **y):
print(x)
print(y) # {'a': 111, 'b': 222, 'c': 333}
func(1,a=111,b=222,c=333)
func(a=111, b=222, x=1, c=333)
3、在實參中用*與**
3.1 在實參前加*:*會把其後的值打散成位置實參
nums=[1,2,3]
func(*nums) # func(1,2,3)
3.2 在實參前加**:**會把其後的值打散關鍵字實參
dic = {'y': 111, 'z': 222, 'x': 333}
func(**dic) # func(y=111,z=222,x=333)
4、在形參與實參中混用*與**
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":1,"b":2,"c":3} index(*args, **kwargs) # index(*(1, 2, 3,),**{"a":1,"b":2,"c":3}) # index(1,2,3,c=3,b=2,a=1) wrapper(1, 2, 3, a=111, b=222, c=333)
5、命名關鍵字形參(**)
def func(x, y=222, *args, n=777,m, **kwargs): # m,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,6666666)
# func(1,2,3,4,5,m=6666666)
func(1, 2, 3, 4, 5, n=88888,m=6666666, a=11, b=22, c=33)
二、函式物件
函式物件指的是函式可以被當成變數去使用
1. 可以被賦值
f = foo
print(f is foo)
f()
2. 可以當作引數傳給一個函式
def bar(func):
print(func)
func()
bar(foo)
3. 可以當成一個函式的返回值
def bar(func):
return func
res=bar(foo)
print(res)
4. 可以當成容器型別的元素
l = [foo]
print(l)
l[0]()
#案例:實現使用者登入轉賬提現充值功能
def login():
print('登入功能......')
def withdraw():
print('提現功能......')
def transfer():
print('轉賬功能......')
def recharge():
print('充值功能')
func_dic={
"1": [login,"登入"],
"2": [withdraw,"提現"],
"3": [transfer,"轉賬"],
"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('輸入的指令不存在')
三、函式巢狀
1、 函式的巢狀呼叫
# 案例比較:
def max2(x,y):
if x > y:
return x
else:
return y
max(1,2)
# 案例比較加難度:
def max4(a,b,c,d):
res1 = max(a,b)
res2 = max(res1,c)
res3 = max(res2,d) #注意要用max比較的功能,需要直接用其本身,不要再將其賦值成max2啥的
print(res3)
max4(1,2,3,4)
2、 函式的巢狀定義
def f1():
print('from f1')
# f2 = 函式的記憶體地址
def f2():
print("from f2")
f1()
定義在函式內的函式特點是: 正常情況只能在函式體內呼叫
#求圓的周長、面積(利用函式巢狀)
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)
示例:
def func():
x = 10
print(x)
def f2():
print('from f2')
f2()
func()
# print(x)#報錯name 'x' is not defined
四、名稱空間與作用域
1、 名稱空間: 就是存放名字的地方
1.1 內建名稱空間: 存放的是內建的名字,如print\input\len
生命週期: 直譯器啟動則產生,直譯器關閉則銷燬
1.2 全域性名稱空間: 存放的是頂級的名字
生命週期: python程式執行時則產生,python程式結束則銷燬
1.3 區域性名稱空間:函式內的名字
生命週期: 呼叫函式時則產生,函式呼叫結束則銷燬
2、名字的查詢優先順序:
從當前位置往外查詢,如果當前是在區域性:區域性名稱空間->全域性名稱空間->內建名稱空間
從當前位置往外查詢,如果當前是在全域性:全域性名稱空間->內建名稱空間
def func():
len = 222
# print(len)
# len = 111
func()
print(len) #注意程式碼級別
3、結論:
(1)名稱空間可以理解為一層套一層的關係,名稱空間的巢狀關係是函式定義階段(即掃描語法時)就固定死的,與函式的呼叫位置無關
#示範1
# x=0
def f1():
# x=1
def f2():
# x=2
print(x)
f2()
f1()
#示範2
len = 111
def f1():
len=2222
def f2():
len=3333
f1()
f2()
(2)全域性範圍/全域性作用域:內建名稱空間+全域性名稱空間
特點:全域性存活,全域性有效
(3)區域性範圍/區域性作用域:區域性名稱空間
特點:臨時存活,區域性有效
4、瞭解
global(****)
nonlocal(***)
#案例1
x = 1
def func(x): # x = 值10的記憶體地址
# x = 值10的記憶體地址
x = 20
func(x) # func(值10的記憶體地址)
print(x) # 1
#案例2
x = [11,22,33]
def func(x): # x = 列表[11,22,33]的記憶體地址
# x = 列表[11,22,33]的記憶體地址
# x=444444444444
x[0] = 66666
func(x) # func(列表[11,22,33]的記憶體地址)
print(x) #[66666, 22, 33]
#案例3
x = [11,22,33]
def func():
x[0] = 66666
func()
print(x) #[66666, 22, 33]
#案例4
x = 10
def func():
global x
x=22
func()
print(x) # 22
# 案例5:nonlocal生命名字是來自於外層函式的(***)
x = 10
def f1():
x=111
def f2():
nonlocal x
x=222
f2()
print(x) # 222
f1()
print(x) # 10