Functools.update_wrapper(wrapper,wrapped,assigned=WRAPPER_ASSIGNMENTS,updated=WRAPPER_UPDATES)
類似 copy_properties功能
Wrapper 包裝函數(shù)
wrapped 被包裝函數(shù)(源函數(shù))
元祖 WRAPPERA_ASSIGNMENTS中是被覆蓋的屬性
'_module_','_name_','_qualname_','_doc_','_annotations_'
模塊名。名稱。限定名。文檔。參數(shù)注解
元祖WRAPPER_UPDATES是要被更新的屬性__dict__屬性字典。將自己字典中的東西添加進(jìn)去,而不是覆蓋別人的東西,key相同,則是覆蓋,key不同,則是增加
增加一個(gè)__wrapped__屬性,保留著wrapped函數(shù)創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),汾陽企業(yè)網(wǎng)站建設(shè),汾陽品牌網(wǎng)站建設(shè),網(wǎng)站定制,汾陽網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,汾陽網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
# 裝飾器參數(shù)傳遞及相關(guān)應(yīng)用
import functools
import datetime,time
def x(t):
def _logger(fn):
def _wapper(*args,**kwargs):
'''This is wapper'''
print ("login.....")
start=datetime.datetime.now()
ret = fn(*args,**kwargs)
du=datetime.datetime.now()-start
if du.total_seconds()<5:
print (fn.__name__,du)
else:
print ("goods")
print ("logout....")
return ret
functools.update_wrapper(_wapper,fn)
return _wapper
return _logger
@x(5)
def add(x,y):
'''This is add'''
time.sleep(5)
return x+y
print (add(5,6),add.__name__,add.__doc__,sep='\n')
查看顯示結(jié)果
# 裝飾器參數(shù)傳遞及相關(guān)應(yīng)用
import functools
import datetime,time
def x(t):
def _logger(fn):
@functools.wraps(fn)#通過閉包和裝飾器完成,其和上面的_cpoy的是實(shí)現(xiàn)原理相似
def _wapper(*args,**kwargs):
'''This is wapper'''
print ("login.....")
start=datetime.datetime.now()
ret = fn(*args,**kwargs)
du=datetime.datetime.now()-start
if du.total_seconds()<5:
print (fn.__name__,du)
else:
print ("goods")
print ("logout....")
return ret
return _wapper
return _logger
@x(5)
def add(x,y):
'''This is add'''
time.sleep(5)
return x+y
print (add(5,6),add.__name__,add.__doc__,sep='\n')
結(jié)果如下:
偏函數(shù),把函數(shù)部分的參數(shù)固定下來,相當(dāng)于為部分的參數(shù)添加了一個(gè)固定的默認(rèn)值,形成一個(gè)新的函數(shù)并返回
從partial 生成新函數(shù),是對原函數(shù)的封裝
import inspect
import functools
def add(x,y)->int:
return x+y
newadd=functools.partial(add,y=5) # 構(gòu)建新函數(shù),使用y=5稱為其默認(rèn)值
print (newadd(3)) # 默認(rèn)是x傳值
print (newadd(4,y=6))
print (newadd(x=6,y=7))
sig1=inspect.signature(add)
sig2=inspect.signature(newadd)
print (sig1.parameters)
print (sig2.parameters)
結(jié)果如下
import inspect
import functools
def add(x,y,*args)->int:
print (x,y,args)
newadd= functools.partial(add,1,2,3,4,5,6)
print (inspect.signature(add).parameters.items())
print (inspect.signature(newadd).parameters.items())
print (newadd())
print (newadd(7))
print (newadd(8,9))
print (newadd(10,11,y=4,x=5)) #此處的x,y 已經(jīng)定義并且已經(jīng)賦值,不能被重復(fù)賦值
結(jié)果如下
functools.lru_cache(maxsize=128,typed=False)
least-recently-used裝飾器,lru,最近最少使用,cache緩存
如果maxsize設(shè)置為None,則禁用LRU功能,并且緩存可以無限制增長,當(dāng)maxsize是二的冪時(shí),LRU功能執(zhí)行得最好 。
如果typed設(shè)置為True,則不同類型的函數(shù)參數(shù)將單獨(dú)存儲(chǔ),如f(3)和f(3.0)將被視為具有不同結(jié)果的不同調(diào)用
實(shí)例
import functools
import datetime
import time
def logger(fn):
def _wapper(*args,**kwargs):
start_time=datetime.datetime.now()
ret = fn(*args,**kwargs)
send=(datetime.datetime.now()-start_time).total_seconds()
print ("{} 函數(shù)執(zhí)行時(shí)間為: {}".format(fn.__name__,send))
return ret
return _wapper
@logger # 此處的調(diào)用不分先后次序,其結(jié)果都一樣
@functools.lru_cache()
def add(x,y,z=3):
time.sleep(3)
return x+y+z
print (add(3,4))
print (add(3,4))
print (add(3.0,4.0))
print (add(3,4,3)) # 此處是重新計(jì)算
print (add(3,4.0,3.0))
執(zhí)行結(jié)果為
lru_cache 裝飾器基礎(chǔ)應(yīng)用
import functools
import datetime
import time
def logger(fn):
def _wapper(*args,**kwargs):
start_time=datetime.datetime.now()
ret = fn(*args,**kwargs)
send=(datetime.datetime.now()-start_time).total_seconds()
print ("{} 函數(shù)執(zhí)行時(shí)間為: {}".format(fn.__name__,send))
return ret
return _wapper
@logger # 此處的調(diào)用不分先后次序,其結(jié)果都一樣
@functools.lru_cache()
def Fib(n):
while n < 2:
return n
return Fib(n-1)+Fib(n-2)
print ([Fib(x) for x in range(10)])
結(jié)果如下
總結(jié)
lrucache 裝飾器應(yīng)用
使用前提
同樣的函數(shù)參數(shù)一定得到同樣的結(jié)果
函數(shù)執(zhí)行時(shí)間很長,且要多次執(zhí)行
本質(zhì)是函數(shù)調(diào)用的參數(shù)=> 返回值
缺點(diǎn)
不支持緩存過期,key無法過期,失效
不支持清除操作
不支持分布式,是一個(gè)單機(jī)的緩存
使用場景,單機(jī)上需要空間換取時(shí)間的地方,可以使用緩存來計(jì)算變成快速的查詢*
思想:
1 cache是通過可hash對象進(jìn)行存儲(chǔ)和調(diào)用的,因此其存入的key必須是不可變類型
2 通過前面的inspect模塊取出對應(yīng)的形參,及key,通過傳入的實(shí)參獲取到其對應(yīng)的值,進(jìn)行鍵和值的處理
實(shí)例如下
初步代碼實(shí)現(xiàn)如下:
#!/usr/bin/poython3.6
#conding:utf-8
import functools
import datetime
import time
import inspect
def logger(fn):
local_cache={} # 此處定義一個(gè)緩沖器
@functools.wraps(fn)
def _wapper(*args,**kwargs):
list_dict={} #此處定義一個(gè)構(gòu)建key的字典
sig=inspect.signature(fn)
param=sig.parameters
param_list=list(param.keys())
for i,v in enumerate(args): # 此處的作用是取出形參和傳入實(shí)參的對應(yīng)關(guān)系
list_dict[param_list[i]]=v
list_dict.update(kwargs)
key = tuple(sorted(list_dict.keys())) # 通過此處獲取字典的鍵的固定順序的元祖,因?yàn)樵媸遣豢勺償?shù)據(jù)類型
if key not in local_cache.keys(): #查詢這個(gè)key是否在此緩存中
ret = fn(*args,**kwargs) #此處調(diào)用外部參數(shù)獲取值
local_cache[key]=ret # 此處對值進(jìn)行處理
return local_cache[key] # 此處將值返回,用于返回,此處若返回為ret,則緩存變失去了意義,
return _wapper
def functime(fn):
@functools.wraps(fn)
def _wapper(*args,**kwargs):
start_time=datetime.datetime.now()
ret = fn(*args,**kwargs)
send=(datetime.datetime.now()-start_time).total_seconds()
print ("{} 函數(shù)的執(zhí)行時(shí)間為:{}".format(fn.__name__,send))
return ret
return _wapper
@functime
@logger
def add(x,y=4):
time.sleep(3)
return x+y
print (add(x=3,y=4))
print (add(3,4))
print (add(y=4,x=3))
執(zhí)行結(jié)果如下
添加默認(rèn)值參數(shù)
import functools
import datetime
import time
import inspect
def logger(fn):
local_cache={} # 此處定義一個(gè)緩沖器
@functools.wraps(fn)
def _wapper(*args,**kwargs):
list_dict={} #此處定義一個(gè)構(gòu)建key的字典
sig=inspect.signature(fn)
param=sig.parameters
param_list=list(param.keys())
for i,v in enumerate(args): # 此處的作用是取出形參和傳入實(shí)參的對應(yīng)關(guān)系
list_dict[param_list[i]]=v
list_dict.update(kwargs)
for i in param.keys(): #檢測形式參數(shù)
if i not in list_dict.keys(): # 判斷形參是否在傳入的對應(yīng)參數(shù)中,若不存在,則由默認(rèn)情況,則進(jìn)行加入對應(yīng)的字典中
list_dict[i]=param[i].default
key = tuple(sorted(list_dict.keys())) # 通過此處獲取字典的鍵的固定順序的元祖,因?yàn)樵媸遣豢勺償?shù)據(jù)類型
if key not in local_cache.keys(): #查詢這個(gè)key是否在此緩存中
ret = fn(*args,**kwargs) #此處調(diào)用外部參數(shù)獲取值
local_cache[key]=ret # 此處對值進(jìn)行處理
return local_cache[key] # 此處將值返回,用于返回,此處若返回為ret,則緩存變失去了意義,
return _wapper
def functime(fn):
@functools.wraps(fn)
def _wapper(*args,**kwargs):
start_time=datetime.datetime.now()
ret = fn(*args,**kwargs)
send=(datetime.datetime.now()-start_time).total_seconds()
print ("{} 函數(shù)的執(zhí)行時(shí)間為:{}".format(fn.__name__,send))
return ret
return _wapper
@functime
@logger
def add(x,y=4):
time.sleep(3)
return x+y
print (add(x=3,y=4))
print (add(3,4))
print (add(y=4,x=3))
print (add(3))
結(jié)果如下
配置過期功能
import functools
import datetime
import time
import inspect
def logger(times):
def _logger(fn):
local_cache={} # 此處定義一個(gè)緩沖器
@functools.wraps(fn)
def _wapper(*args,**kwargs):
pop_key_list=[]
for k,(_,item) in local_cache.items():
if datetime.datetime.now().timestamp()- item> times:
pop_key_list.append(k)
for i in pop_key_list:
local_cache.pop(i)
list_dict={} #此處定義一個(gè)構(gòu)建key的字典
sig=inspect.signature(fn)
param=sig.parameters
param_list=list(param.keys())
for i,v in enumerate(args): # 此處的作用是取出形參和傳入實(shí)參的對應(yīng)關(guān)系
list_dict[param_list[i]]=v
list_dict.update(kwargs)
for i in param.keys(): #檢測形式參數(shù)
if i not in list_dict.keys(): # 判斷形參是否在傳入的對應(yīng)參數(shù)中,若不存在,則由默認(rèn)情況,則進(jìn)行加入對應(yīng)的字典中
list_dict[i]=param[i].default
key = tuple(sorted(list_dict.keys())) # 通過此處獲取字典的鍵的固定順序的元祖,因?yàn)樵媸遣豢勺償?shù)據(jù)類型
if key not in local_cache.keys(): #查詢這個(gè)key是否在此緩存中
ret = fn(*args,**kwargs) #此處調(diào)用外部參數(shù)獲取值
local_cache[key]=(ret,datetime.datetime.now().timestamp()) # 此處將值返回,用于返回,此處若返回為ret,則緩存變失去了意義,
return local_cache[key]
return _wapper
return _logger
def functime(fn):
@functools.wraps(fn)
def _wapper1(*args,**kwargs):
start_time=datetime.datetime.now()
ret=fn( *args,**kwargs)
send=(datetime.datetime.now()-start_time).total_seconds()
print ("{} 函數(shù)的執(zhí)行時(shí)間為:{}".format(fn.__name__,send))
return ret
return _wapper1
@functime
@logger(5) #傳入過期時(shí)間為5s進(jìn)行處理
def add(x,y=4):
time.sleep(3)
return x+y
print (add(x=3,y=4))
print (add(3,4))
time.sleep(5)
print (add(y=4,x=3))
print (add(3))
查看結(jié)果
程序員可以方便的注冊函數(shù)到某一個(gè)命令,用戶輸入命令時(shí),路由到注冊函數(shù)
如果此命令沒有對應(yīng)的注冊函數(shù),執(zhí)行默認(rèn)函數(shù)
用戶輸入用input(">>")
分析:
輸入一個(gè)命令映射到一個(gè)函數(shù),并執(zhí)行這個(gè)函數(shù),應(yīng)該是cmd,fn 形式,此時(shí)字典整好滿足此中需求
如果輸入了某一個(gè)cmd命令后,沒有找到函數(shù),就要調(diào)用缺省的函數(shù)執(zhí)行,這整好是字典的缺省函數(shù)
cmd是字符串
基本代碼如下
#!/usr/bin/poython3.6
#conding:utf-8
#定義一個(gè)字典,其保存命令和函數(shù)的集合
commds={}
# 創(chuàng)建函數(shù)
def fun1():
print ("hello fun1")
def fun2():
print ("hello fun2")
#創(chuàng)建默認(rèn)函數(shù)
def fundefault():
print ("hello default")
# 創(chuàng)建注冊函數(shù)
def register(name,fn):
commds[name]=fn
# 創(chuàng)建查詢函數(shù)
def printf():
while True:
cmd=input(">>")
if cmd.strip() == 'quit':
return
commds.get(cmd,fundefault)() #調(diào)用函數(shù),若無存在,則調(diào)用默認(rèn)函數(shù)
# 調(diào)用注冊函數(shù)進(jìn)行注冊
register("fun1",fun1)
register("fun2",fun2)
#調(diào)用顯示函數(shù)
printf()
查看結(jié)果如下
改善注冊函數(shù)如下
#!/usr/bin/poython3.6
#conding:utf-8
#定義一個(gè)字典,其保存命令和函數(shù)的集合
commds={}
# 創(chuàng)建注冊函數(shù)
def register(name): #通過柯里化進(jìn)行處理
def _warpper(fn):
commds[name]=fn
return _warpper
# 創(chuàng)建查詢函數(shù)
def printf():
while True:
cmd=input(">>")
if cmd.strip() == 'quit':
return
commds.get(cmd,fundefault)() #調(diào)用函數(shù),若無存在,則調(diào)用默認(rèn)函數(shù)
# 調(diào)用注冊函數(shù)進(jìn)行注冊
# 創(chuàng)建函數(shù)
@register('fun1')
def fun1():
print ("hello fun1")
@register('fun2')
def fun2():
print ("hello fun2")
#創(chuàng)建默認(rèn)函數(shù)
def fundefault():
print ("hello default")
#調(diào)用顯示函數(shù)
printf()
將調(diào)用函數(shù)和顯示函數(shù)進(jìn)行合并,并進(jìn)行集中輸入,如下
#!/usr/bin/poython3.6
#conding:utf-8
#定義一個(gè)字典,其保存命令和函數(shù)的集合
commds={}
# 創(chuàng)建注冊函數(shù)
def comm():
def register(name): #通過柯里化進(jìn)行處理
def _warpper(fn):
commds[name]=fn
return _warpper
# 創(chuàng)建查詢函數(shù)
def printf():
while True:
cmd=input(">>")
if cmd.strip() == 'quit':
return
commds.get(cmd,fundefault)() #調(diào)用函數(shù),若無存在,則調(diào)用默認(rèn)函數(shù)
return register,printf
register,printf=comm()
# 調(diào)用注冊函數(shù)進(jìn)行注冊
# 創(chuàng)建函數(shù)
@register('fun1')
def fun1():
print ("hello fun1")
@register('fun2')
def fun2():
print ("hello fun2")
#創(chuàng)建默認(rèn)函數(shù)
def fundefault():
print ("hello default")
#調(diào)用顯示函數(shù)
printf()
#!/usr/bin/poython3.6
#conding:utf-8
from functools import partial
def dispatcher():
commads={}
def reg(cmd,*args,**kwargs):
def _reg(fn):
func=partial(fn,*args,**kwargs)
commads[cmd]=func
return func
return _reg
def run():
while True:
cmd=input('>>')
if cmd.strip() == 'q' or cmd.strip() =='quit':
break
else:
commads.get(cmd,defaunlt)()
def defaunlt():
print ('default')
return reg,run
reg,run=dispatcher()
@reg('add',1,2,3,4)
def add(x,y,z,w):
print (x+y+z+w)
@reg('sub',20,10)
def sub(x,y):
print (x-y)
run()
結(jié)果如下
Base64是網(wǎng)絡(luò)上最常見的用于傳輸8Bit字節(jié)碼的編碼方式之一,Base64就是一種基于64個(gè)可打印字符來表示二進(jìn)制數(shù)據(jù)的方法。
Base64編碼是從二進(jìn)制到字符的過程,可用于在HTTP環(huán)境下傳遞較長的標(biāo)識(shí)信息。采用Base64編碼具有不可讀性,需要解碼后才能閱讀。
Base64由于以上優(yōu)點(diǎn)被廣泛應(yīng)用于計(jì)算機(jī)的各個(gè)領(lǐng)域,然而由于輸出內(nèi)容中包括兩個(gè)以上“符號(hào)類”字符(+, /, =),不同的應(yīng)用場景又分別研制了Base64的各種“變種”。為統(tǒng)一和規(guī)范化Base64的輸出,Base62x被視為無符號(hào)化的改進(jìn)版本。
標(biāo)準(zhǔn)的Base64并不適合直接放在URL里傳輸,因?yàn)閁RL編碼器會(huì)把標(biāo)準(zhǔn)Base64中的“/”和“+”字符變?yōu)樾稳纭?XX”的形式,而這些“%”號(hào)在存入數(shù)據(jù)庫時(shí)還需要再進(jìn)行轉(zhuǎn)換,因?yàn)锳NSI SQL中已將“%”號(hào)用作通配符。
為解決此問題,可采用一種用于URL的改進(jìn)Base64編碼,它在末尾填充'='號(hào),并將標(biāo)準(zhǔn)Base64中的“+”和“/”分別改成了“-”和“_”,這樣就免去了在URL編解碼和數(shù)據(jù)庫存儲(chǔ)時(shí)所要作的轉(zhuǎn)換,避免了編碼信息長度在此過程中的增加,并統(tǒng)一了數(shù)據(jù)庫、表單等處對象標(biāo)識(shí)符的格式。Base64要求把每三個(gè)8Bit的字節(jié)轉(zhuǎn)換為四個(gè)6Bit的字節(jié)(3*8 = 4*6 = 24),然后把6Bit再添兩位高位0,組成四個(gè)8Bit的字節(jié),也就是說,轉(zhuǎn)換后的字符串理論上將要比原來的長1/3。
關(guān)于這個(gè)編碼的規(guī)則:
①.把3個(gè)字符變成4個(gè)字符。
②每76個(gè)字符加一個(gè)換行符。
③.最后的結(jié)束符也要處理。
import base64
source = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
def Base64(src):
ret = bytearray() # 定義可變字節(jié)列表,一個(gè)字節(jié)為8bit
length = len(src)
r = 0 # r為記錄的補(bǔ)0的數(shù)量
for offset in range(0, length, 3): # 進(jìn)行三位切割,三位8bbit切割成4位6bit,
if offset <= length - 3: #此處是匹配前面的整3位的
triple = src[offset:offset + 3]
else:
triple = src[offset:] # 截取后面的小于3位的
r = 3 - len(triple) # 獲取需要補(bǔ)0的位數(shù)
triple = triple + '\x00' * r # 補(bǔ)幾個(gè)0 bin(0x00) '0b0'
# print (triple,r)
b = int.from_bytes(triple.encode(), 'big') # 大端模式為big,小端模式為little
for i in range(18, -1, -6): # 進(jìn)行移位操作
if i == 18:
index = b >> i
else:
index = b >> i & 0x3F # 此處是進(jìn)行運(yùn)算 ,轉(zhuǎn)換為二進(jìn)制是 bin(0x3f) '0b111111'
# In [24]: int('0x3d',16)
# Out[24]: 61
# In [25]: chr(61)
# Out[25]: '='
ret.append(source[index])
for i in range(1, r + 1):
ret[-i] = 0x3D # 0x3D 表示等號(hào)
return bytes(ret)
print('Base64',Base64('123456'))
print ('base64',base64.b64encode('123456'.encode('utf-8')))
結(jié)果如下
import base64
#base64一定是四的倍數(shù)
from collections import OrderedDict
base_tb1="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
alphabet=OrderedDict(zip(base_tb1,range(64)))
def Base64decode(src):
ret=bytearray()
length=len(src)
step=4
for offset in range(0,length,step):
tmp=0x00
block=src[offset:offset+step] # 4位進(jìn)行截取,abcd
for i,c in enumerate(reversed(block)): # 進(jìn)行反向操作處理,第一個(gè)是0 d
index= alphabet.get(c) # 通過值找索引 ,其中負(fù)數(shù)表示沒找到,find不拋異常
if index==-1: #表示沒找到
continue #直接操作下一個(gè)
tmp += (index << i*6) # 此處第一個(gè)d是最后面的低6位,向左是高位,右邊位低位,,第一次i=0表示沒移動(dòng),
# 第二次i=1表示向左移動(dòng)6位,依次類推abcd,最后將其加在一起。此處相當(dāng)于將其進(jìn)行了拼接,此時(shí)已經(jīng)成為了24
ret.extend(tmp.to_bytes(3,'big')) # 將4個(gè)段進(jìn)行切成3段,若有等號(hào),則先不管
return bytes(ret.rstrip(b'\x00')) # 去掉多余的右邊的0,是asscii的0,在最后的4變3的過程中,才會(huì)出現(xiàn)0,因?yàn)榍懊娴亩际钦?
print ('Base64',Base64decode('abcd'))
print ('base64',base64.b64decode('abcd'.encode('utf-8')))
結(jié)果如下
文章題目:裝飾器進(jìn)階
當(dāng)前URL:http://muchs.cn/article48/gpppep.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、網(wǎng)站改版、網(wǎng)站導(dǎo)航、外貿(mào)網(wǎng)站建設(shè)、做網(wǎng)站、定制開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)