day13 多個裝飾器疊加 生成式
1.裝飾器剩餘
from functions import wraps
@wrap(func) 會把func內的自帶方法賦給wrapper,這樣wrapper裝飾函式就和原函式一模一樣
多個裝飾器疊加
def outter1(func):
def wrapper1(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper1
def outter2(func):
def wrapper2(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper2
def outter3(func):
def wrapper3(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper3
@outer1
@outer2
@outer3
def f1(name):
print('welcome home %s' % name)
f1('egon')
載入順序
自下而上,因為裝飾器的語法糖,相當於f1 = outer1(outer2(outer3(f1)))
檢測語法後,先載入outer3,此時的原函式f1的記憶體地址還沒有變包在閉包函式wrapper3中傳給outer2,outer2將打包的閉包函式wrapper2地址傳給outer1,outer1將打包的閉包函式打包給f1
outer1(outer2(outer3(f1))) 從右往左一步一步閉包並且載入函式
執行順序 從上往下,因為用到的閉包函式都被包給了outer1中,先去outer1中開始執行,執行到其中要執行wrapper2的地方了,這時wrapper1還沒執行完,就跳到wrapper2中去執行,wrapper2還沒執行完,遇到wrapper3了,就跳到wrapper3中執行,執行完已經是最內層了,開始把wrapper3的返回值返回值給wrapper2,wrapper2執行完返回值返回給wrapper1,wrapper1執行完之後,返回值返回給最初始的函式,繼續執行全域性程式碼,整個裝飾器函式的呼叫結束。
2.有參裝飾器
以上裝飾器模版如下
from functools import wraps
def outter(func):
@wraps(func)
def wrapper(*args,**kwargs):
res = func(*args,**kwargs)
return res
return wrapper
這樣會遇到一個問題,這個函式確實可以完全模仿了舊函式的同時加了新功能,但是如果假如想給內部閉包函式傳進其他引數方便使用,在當前模版上就沒法做到
outter(func)的引數必須是原函式,不能增加,也不能減少,否則使用語法糖@outter func=outter(func)會報錯
另外,wrapper(*args,**kwargs)內傳的引數也不能改變,這是為了把原函式的引數原封不動還給原函式去呼叫
這個時候,就可以再多包一層函式,在最外層函式傳引數,而且引數可以任意指定,把最外層函式名返回,這樣包含著最外層名稱空間的閉包函式就賦給了原函式
既包含舊功能,又添加了新功能,還傳了新引數,可供程式擴充套件使用
根據傳進的檔案型別不同,在內部增加判斷選擇寫入檔案的方式
3.三元表示式
三元表示式用來在保證程式碼可讀性的前提下,精簡一些語句的寫法
如下需要函式判斷兩個數的大小語句
def max(x,y)
if x>y:
return x
else:
return y
可以用如下表達式代替
x=10
y=20
res = x if x >y else y #b表示式1 if條件表示式 else 表示式2,當if判斷返回True時,返回結果表示式1,否則返回結果表示式2
print(res)
res = ’ok‘ if False else 'No'
print(res)
4.生成式:用來生成資料的表示式
先來生成一個列表
l = []
for i in range(10):
if i >4:
l.append(i**2)
列表生成式
l = [i**2 for i in range(10) if i >4] 不能加else,因為不知道是加給for的還是if的
print(l)
name = ['egon','alex_sb','kevin_sb','hxx_sb','cxx_sb'] 匹配找出結尾是sb的元素
sbs=[]
for name in names:
if name.endswith('sb')
sbs.append(name)
用生成式代替
sbs = [name for name in names if name.endswith('sb')]
print([name.upper() for name in names])
字典生成式
res = {i:i**2 for i in range(10) if i > 3}
print(res)
print({i for i in 'hello'}) 生成集合,去重
5.匿名函式
先看有名函式
def func():
print(‘from func’)
func()
func()
func()
有名稱的函式定義後,可以在之後多次以名字呼叫
匿名函式就是隻定義一個函式的記憶體地址,主要用於臨時使用一次的場景
func = lambda x,y:(return)x+y 匿名函式自動返回值,不用新增return
print(func)
print(func(1,2))
res = (lambda x,y:x+y)(1,2) 匿名函式後面加扣號呼叫,並傳引數
print(max([10,11,-3,23]))
salaries = {
'egon':3000
'alex':100000000
'wupeiqi':10000
'yuanhao':2000
}
def func(k):
return salaries[k]
print(max(salaries,key = lambda k:salaries[k]))