1. 程式人生 > >20181130(裝飾器補充,疊加多個裝飾器,有參裝飾器,三元表達式,生成式,匿名函數,內置函數)

20181130(裝飾器補充,疊加多個裝飾器,有參裝飾器,三元表達式,生成式,匿名函數,內置函數)

names hello 對應關系 tools src recv log 原始的 裝飾

一、裝飾器的補充

1、函數屬性的傳遞

Python裝飾器(decorator)在實現的時候,被裝飾後的函數其實已經是另外一個函數了(函數名等函數屬性會發生改變),為了不影響,Python的functools包中提供了一個叫wraps的decorator來消除這樣的副作用。寫一個decorator的時候,最好在實現之前加上functools的wrap,它能保留原有函數的名稱和docstring。
簡言之:導入wraps,即可將原函數的屬性(解釋文本等)傳遞給裝飾器中對應的函數。
from functools import wraps #從 functools導入wraps
?
def outter(func):
@wraps(func) #相當於一個裝飾器,將func的屬性傳遞給wraps
def wrapper(*args,**kwargs):
res=func(*args,**kwargs)
return res
return wrapper
?
@outter #index=outter(index) #index=wrapper
def index():
"""
這是index函數....
"""
print(‘from index‘)
?
?
index()
print(index.__doc__) #輸出index的說明文檔
print(index.__name__) #輸出index的名字,index是函數的內存地址
輸出結果為:
from index
?
這是index函數....

index
?

1、疊加多個裝飾器

加載順序(outter函數的調用順序):自下而上

執行順序(wrapper函數的執行順序):自上而下

# 疊加多個裝飾器
# 1. 加載順序(outter函數的調用順序):自下而上
# 2. 執行順序(wrapper函數的執行順序):自上而下
?
?
def outter1(func1): #func1=wrapper2的內存地址
print(‘加載了outter1‘)
def wrapper1(*args,**kwargs):
print(‘執行了wrapper1‘)
res1=func1(*args,**kwargs)
return res1
return wrapper1
?
def outter2(func2): #func2=wrapper3的內存地址
print(‘加載了outter2‘)
def wrapper2(*args,**kwargs):
print(‘執行了wrapper2‘)
res2=func2(*args,**kwargs)
return res2
return wrapper2
?
def outter3(func3): # func3=最原始的那個index的內存地址
print(‘加載了outter3‘)
def wrapper3(*args,**kwargs):
print(‘執行了wrapper3‘)
res3=func3(*args,**kwargs)
return res3
return wrapper3
?
?
?
@outter1 # outter1(wrapper2的內存地址)======>index=wrapper1的內存地址
@outter2 # outter2(wrapper3的內存地址)======>wrapper2的內存地址
@outter3 # outter3(最原始的那個index的內存地址)===>wrapper3的內存地址
def index():
print(‘from index‘)
?
print(‘======================================================‘)
index()
輸出結果為:
加載了outter3
加載了outter2
加載了outter1
======================================================
執行了wrapper1
執行了wrapper2
執行了wrapper3
from index

技術分享圖片

import time
?
def timmer(func):
def aaa(*args,**kwargs):
start=time.time()
res=func(*args,**kwargs)
stop=time.time()
print(‘run time is %s‘ %(stop -start))
return res
return aaa
?
def auth(func):
def bbb(*args,**kwargs):
name=input(‘name>>>: ‘).strip()
pwd=input(‘pwd>>>: ‘).strip()
if name == ‘egon‘ and pwd == ‘123‘:
print(‘login successfull‘)
res=func(*args,**kwargs)
return res
else:
print(‘user or pwd error‘)
return bbb
?
@auth
@timmer #註意此處裝飾器的先後順序,調整裝飾器的先後順序,會得到不同的結果。
def index():
time.sleep(1)
print(‘from index‘)
?
index()

2、有參裝飾器:三層的閉包函數

對於裝飾器,三層就夠了(第一層傳參數,第二層傳函數,第三層執行添加的功能和源代碼)

import time
from functools import wraps
current_user={‘user‘:None}
?
def auth(engine=‘file‘):
def outter(func):
@wraps(func)
def wrapper(*args,**kwargs):
if current_user[‘user‘] is not None:
res=func(*args,**kwargs)
return res
?
user=input(‘username>>>: ‘).strip()
pwd=input(‘password>>>: ‘).strip()
?
if engine == ‘file‘:
# 基於文件的認證
if user == ‘egon‘ and pwd == ‘123‘:
print(‘login successfull‘)
current_user[‘user‘]=user
res=func(*args,**kwargs)
return res
else:
print(‘user or password error‘)
elif engine == ‘mysql‘:
# 基於mysql的認證
print(‘基於mysql的認證‘)
elif engine == ‘ldap‘:
# 基於ldap的認證
print(‘基於ldap的認證‘)
else:
print(‘不知道engine‘)
return wrapper
return outter
?
@auth(‘ldap‘) #@outter #index=outter(index) # index=wrapper #註意此處傳參的方法
def index():
time.sleep(1)
print(‘from index‘)
?
@auth(‘mysql‘) #@outter # home=outter(home) #home=wrapper #註意此處傳參的方法
def home(name):
print(‘welcome %s‘ %name)
?
index()
home(‘egon‘)
?
輸出結果:
username>>>: egon
password>>>: 123
基於ldap的認證
username>>>: egon
password>>>: 123
基於mysql的認證

二、三元表達式

只能將if else這種簡單的取代,有elif的不行。

res=‘ok‘ if False else ‘no‘  #條件成立輸出左側的值,否則輸出右側的值,可以簡化if。。。else語句。
print(res)
輸出結果為:
no
三、生成式

列表生成式

# l=[]
# for i in range(10):
# if i>4:
# l.append(i**2)
# print(l)
上下代碼功能一致
l=[i**2 for i in range(10) if i >4] #後面不能使用else,無論是if else還是for else,可以對循環的參數進行操作
print(l)
輸出結果為:
[25, 36, 49, 64, 81]
?
?
# 映射和判斷
names=[‘egon‘,‘go_on‘,‘kevin‘,‘wxx‘]
print([name.upper() for name in names]) #映射關系
print([name for name in names if name.endswith(‘on‘)]) #判斷關系
print([name.upper() for name in names if name.endswith(‘on‘)]) #映射疊加判斷關系
輸出的結果:
[‘EGON‘, ‘GO_ON‘, ‘KEVIN‘, ‘WXX‘]
[‘egon‘, ‘go_on‘]
[‘EGON‘, ‘GO_ON‘]

字典生成式:key和value需要有對應關系才好處理。

res={i:i**2 for i in range(10) if i > 3} #註意字典的生成格式
print(res)
?
print({i for i in ‘hello‘}) #註意此處生成的是集合!
輸出結果為:
{4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
{‘e‘, ‘h‘, ‘l‘, ‘o‘}

四、匿名函數:匿名函數就是只定義了一個函數的內存地址,主要用於臨時使用一次的場景。
a=(lambda x,y:x+y)(1,2)  #格式為“lambda 參數:表達式”後接括號內輸入參數,匿名函數自帶return,可以得到返回值
print(a)
輸出結果為3

五、內置函數

1、max和min

print(max([10,11,-3,23]))  #max會從列表中先取出兩個值比較,再將較大的和下一個值比較
輸出結果為:
23
比較value的值,然後輸出對應的key:
salaries={
‘egon‘:3000,
‘alex‘:100000000,
‘wupeiqi‘:10000,
‘yuanhao‘:2000
}
?
def func(k):
return salaries[k]
?
print(max(salaries,key=lambda k:salaries[k])) #此處第一個salaries是一個序列,其中的元素會被遍歷,作為參數k進行函數的運算,不理解的話看下面
print(min(salaries,key=func)) #其實沒有必要做成有名函數,匿名函數就可以了。
# for循環的結果 比較依據
# ‘egon‘ 3000
# ‘alex‘ 100000000
# ‘wupeiqi‘ 10000
# ‘yuanhao‘ 2000
輸出結果為:
alex
yuanhao
?
max的解釋:
max(iterable, *[, key, default])
max(arg1, arg2, *args[, key])
字典是可叠代的,結果為key值,
salaries={
‘egon‘:3000,
‘alex‘:100000000,
‘wupeiqi‘:10000,
‘yuanhao‘:2000
}
?
l=list(salaries)
print(l)
輸出結果為:
[‘egon‘, ‘alex‘, ‘wupeiqi‘, ‘yuanhao‘]
?
res=max((1,2),[1,1],key = lambda x : x[1])
print(res)
輸出結果為:
(1, 2)

sorted函數:

def sorted(*args, **kwargs): # real signature unknown
"""
Return a new list containing all items from the iterable in ascending order.

A custom key function can be supplied to customize the sort order, and the
reverse flag can be set to request the result in descending order.
"""

以升序返回包含iterable中所有項的新列表。
可以提供自定義鍵功能來自定義排序順序,以及可以設置反向標誌以按降序請求結果。

匿名函數與其他函數的結合應用:

salaries={
‘egon‘:3000,
‘alex‘:100000000,
‘wupeiqi‘:10000,
‘yuanhao‘:2000
}
print(sorted(salaries,key=lambda k:salaries[k],reverse=True)) #字典中的key變成序列作為參數傳入後面的匿名函數,由升序改為降序排列。
輸出結果為:
[‘alex‘, ‘wupeiqi‘, ‘egon‘, ‘yuanhao‘]

20181130(裝飾器補充,疊加多個裝飾器,有參裝飾器,三元表達式,生成式,匿名函數,內置函數)