溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

裝飾器進(jìn)階

發(fā)布時(shí)間:2020-07-13 02:21:25 來源:網(wǎng)絡(luò) 閱讀:679 作者:長(zhǎng)跑者1號(hào) 欄目:編程語言

一 functools 模塊

1 update_wrapper模塊

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ù)

# 裝飾器參數(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é)果
裝飾器進(jìn)階

2 wraps ,類似上述的變種

# 裝飾器參數(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é)果如下:
裝飾器進(jìn)階

3 partial 方法

偏函數(shù),把函數(shù)部分的參數(shù)固定下來,相當(dāng)于為部分的參數(shù)添加了一個(gè)固定的默認(rèn)值,形成一個(gè)新的函數(shù)并返回
從partial 生成新函數(shù),是對(duì)原函數(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é)果如下
裝飾器進(jìn)階

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é)果如下
裝飾器進(jìn)階

4 lru_cache

functools.lru_cache(maxsize=128,typed=False)
least-recently-used裝飾器,lru,最近最少使用,cache緩存
如果maxsize設(shè)置為None,則禁用LRU功能,并且緩存可以無限制增長(zhǎng),當(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é)果為

裝飾器進(jìn)階

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é)果如下
裝飾器進(jìn)階

總結(jié)

lrucache 裝飾器應(yīng)用
使用前提
同樣的函數(shù)參數(shù)一定得到同樣的結(jié)果
函數(shù)執(zhí)行時(shí)間很長(zhǎng),且要多次執(zhí)行
本質(zhì)是函數(shù)調(diào)用的參數(shù)=> 返回值
缺點(diǎn)
不支持緩存過期,key無法過期,失效
不支持清除操作
不支持分布式,是一個(gè)單機(jī)的緩存
使用場(chǎng)景,單機(jī)上需要空間換取時(shí)間的地方,可以使用緩存來計(jì)算變成快速的查詢*

二 裝飾器練習(xí)

1 實(shí)現(xiàn)一個(gè)cache裝飾器,實(shí)現(xiàn)可過期,可刪除的功能,可以不換出

思想:
1 cache是通過可hash對(duì)象進(jìn)行存儲(chǔ)和調(diào)用的,因此其存入的key必須是不可變類型
2 通過前面的inspect模塊取出對(duì)應(yīng)的形參,及key,通過傳入的實(shí)參獲取到其對(duì)應(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í)參的對(duì)應(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  # 此處對(duì)值進(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é)果如下
裝飾器進(jìn)階

添加默認(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í)參的對(duì)應(yīng)關(guān)系
            list_dict[param_list[i]]=v
        list_dict.update(kwargs)
        for  i  in  param.keys():  #檢測(cè)形式參數(shù)
            if  i not  in  list_dict.keys():  # 判斷形參是否在傳入的對(duì)應(yīng)參數(shù)中,若不存在,則由默認(rèn)情況,則進(jìn)行加入對(duì)應(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  # 此處對(duì)值進(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é)果如下
裝飾器進(jìn)階

配置過期功能

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í)參的對(duì)應(yīng)關(guān)系
                list_dict[param_list[i]]=v
            list_dict.update(kwargs)
            for  i  in  param.keys():  #檢測(cè)形式參數(shù)
                if  i not  in  list_dict.keys():  # 判斷形參是否在傳入的對(duì)應(yīng)參數(shù)中,若不存在,則由默認(rèn)情況,則進(jìn)行加入對(duì)應(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é)果
裝飾器進(jìn)階

2 寫一個(gè)命令分發(fā)器

程序員可以方便的注冊(cè)函數(shù)到某一個(gè)命令,用戶輸入命令時(shí),路由到注冊(cè)函數(shù)
如果此命令沒有對(duì)應(yīng)的注冊(cè)函數(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)建注冊(cè)函數(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)用注冊(cè)函數(shù)進(jìn)行注冊(cè)
register("fun1",fun1)
register("fun2",fun2)
#調(diào)用顯示函數(shù)
printf()

查看結(jié)果如下
裝飾器進(jìn)階

改善注冊(cè)函數(shù)如下

#!/usr/bin/poython3.6
#conding:utf-8
#定義一個(gè)字典,其保存命令和函數(shù)的集合
commds={}
# 創(chuàng)建注冊(cè)函數(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)用注冊(cè)函數(shù)進(jìn)行注冊(cè)
# 創(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)建注冊(cè)函數(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)用注冊(cè)函數(shù)進(jìn)行注冊(cè)
# 創(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()

裝飾器進(jìn)階

#!/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é)果如下
裝飾器進(jìn)階

3 實(shí)現(xiàn)base64編碼和解碼

1 簡(jiǎn)介

Base64是網(wǎng)絡(luò)上最常見的用于傳輸8Bit字節(jié)碼的編碼方式之一,Base64就是一種基于64個(gè)可打印字符來表示二進(jìn)制數(shù)據(jù)的方法。
Base64編碼是從二進(jìn)制到字符的過程,可用于在HTTP環(huán)境下傳遞較長(zhǎng)的標(biāo)識(shí)信息。采用Base64編碼具有不可讀性,需要解碼后才能閱讀。
Base64由于以上優(yōu)點(diǎn)被廣泛應(yīng)用于計(jì)算機(jī)的各個(gè)領(lǐng)域,然而由于輸出內(nèi)容中包括兩個(gè)以上“符號(hào)類”字符(+, /, =),不同的應(yīng)用場(chǎ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ù)庫(kù)時(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ù)庫(kù)存儲(chǔ)時(shí)所要作的轉(zhuǎn)換,避免了編碼信息長(zhǎng)度在此過程中的增加,并統(tǒng)一了數(shù)據(jù)庫(kù)、表單等處對(duì)象標(biāo)識(shí)符的格式。

Base64要求把每三個(gè)8Bit的字節(jié)轉(zhuǎn)換為四個(gè)6Bit的字節(jié)(3*8 = 4*6 = 24),然后把6Bit再添兩位高位0,組成四個(gè)8Bit的字節(jié),也就是說,轉(zhuǎn)換后的字符串理論上將要比原來的長(zhǎng)1/3。

2 規(guī)則

關(guān)于這個(gè)編碼的規(guī)則:
①.把3個(gè)字符變成4個(gè)字符。
②每76個(gè)字符加一個(gè)換行符。
③.最后的結(jié)束符也要處理。

3 base64編碼

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é)果如下
裝飾器進(jìn)階

4 Base64解碼

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)階

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI