欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

python——裝飾器

系統 1618 0

裝飾器:

概念:把一個函數當作參數傳遞給一個函數,返回一個替代版的函數本質上就是一個返回函數的函數
“在不改變原函數的基礎上,給函數增加功能”

@ 符號,那只是一個簡短的方式來生成一個被裝飾的函數

            
              def paint(func):        參數是一個函數
    def inner():
        print('#########')        這個的整個部分就都是裝飾器
        func()
    return  inner
@paint             這個就是函數戴帽子,也就是裝飾器
def func():
    print('have a nice day!!')      
@paint
def func2():
    print('hello world')
func()
func2()

#########
have a nice day!!
#########
hello world

            
          
1、 被裝飾的函數存在參數的時候

在構建裝飾器的時候,作為返回值的函數是用來替代作為參數的函數的,所以這兩個函數所需要的參數必須一致。就時說再定義函數裝飾器的時候,指定作為參數的函數可以由于任意個參數以及作為返回值的函數可以右任意個參數,這樣就能保證再實際使用的時候不論被裝飾的函數需要幾個參數,都能使用該裝飾器。

2 、被裝飾的函數有返回值的時候

需要再函數裝飾器中作為返回值的函數中,接收該作為參數的函數的返回值,飯后再返回該值。

            
              def outter(func):         函數作為參數+
    def inner(*args):
        # if age <=0:
        #     age = 0
        func(*args)     調用函數
    return inner
    
@outter
def say(name,age):
    print('%s is %d years old' %(name,age))
say('redhat',10)

            
          

3 、被裝飾的函數如何保留自己的函數名和幫助信息文檔
當函數被裝飾之后,裝飾器返回一個新的函數來替代原來的函數進行工作,這時候函數名稱以及函數文檔都會變成裝飾器中定義的函數。

            
              def welcome(func):  # 參數是一個函數
    def inner_f(*args,**kwargs):
        """這是裝飾器中的welcome函數"""
        print('welcome'.center(40,'~'))
        res = func(*args,**kwargs)
        return res
    return inner_f   # 返回值是另一個函數
@welcome   # 使用welcome進行裝飾
def name(name):
    """這是被裝飾的name函數"""
    print('name is %s'  %name)
@welcome     # 使用welcome進行裝飾
def stuinfo(name,age):
    """這是被裝飾的stuinfo函數"""
    return ('name is %s ,age is %d' %(name,age))
print(name.__name__)   # 輸出函數名稱
print(name.__doc__)  # 輸出函數文檔
print(stuinfo.__name__)   # 輸出函數名稱
print(stuinfo.__doc__)   # 輸出函數文檔

輸出結果:
inner_f
這是裝飾器中的welcome函數
inner_f
這是裝飾器中的welcome函數    # 任何被裝飾的函數民成以及函數文檔都變成裝飾器中定義的函數


            
          

Python提供給我們一個簡單的函數來解決這個問題,那就是functools.wraps。wraps接受一個函數來進行裝飾,并加入了復制函數名稱、注釋文檔、參數列表等等的功能。這可以讓我們在裝飾器里面訪問在裝飾之前的函數的屬性。

import time 模塊

            
              def desc(f):  # 需要傳遞的函數(要裝飾的函數)
    def add_info():
        print('兒童節快樂~~~')
        f()
        print('歡迎來西部開源~~~')
    return desc
@desc
def login():
    print('login...')
print(time.time())

            
          
裝飾器實現一個函數計時器
            
              import time
import string
import random
import functools
li = [random.choice(string.ascii_letters)
      for i in range(1000)]
def timeit(fun):
    # 問題1:被裝飾的函數有返回值的時候怎么辦?
    # 問題2:被裝飾的函數如何保留自己的函數名和幫助信息文檔?
    @functools.wraps(fun)
    def wapper(*args, **kwargs):
        """這是一個wapper函數"""
        # 在函數的執行之前
        start_time = time.time()
        # 執行函數
        res = fun(*args, **kwargs)
        # 在函數執行之后
        end_time = time.time()
        print('運行的時間為:%.6f' % (end_time - start_time))
        return res
    return wapper
@timeit
def con_add():
    s = ''
    for i in li:
        s += (i + '+')
    print(s)
@timeit
def join_add():
    print('+'.join(li))
con_add()
join_add()

            
          

創建裝飾器, 要求如下:
#1. 創建add_log裝飾器, 被裝飾的函數打印日志信息;
#2. 日志格式為: [字符串時間] 函數名: xxx,
運行時間:xxx, 運行返回值結果:xxx

            
              import time
import functools
#print(time.ctime())
def add_log(func):
    @functools.wraps(func)
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        end_time = time.time()
        print('[%s] 函數名:%s,運行時間:%.6f,運行返回值的'
              '結果:%d' %(time.ctime(),func.__name__,
                        end_time-start_time,res))
        return res
    return wrapper
@add_log
def add(x,y):
    time.sleep(1)
    return x+y
add(1,10)

實驗效果
[Mon Jun  3 16:01:39 2019] 函數名:add,運行時間:1.000481,運行返回值的結果:11

            
          
裝飾器的執行順序,先上到下執行
            
              def decorator_a(fun):
    def inner_a(*args,**kwargs):
        print('Get in inner_a')
        return fun(*args,**kwargs)
    return inner_a
def decorator_b(fun):
    def inner_b(*args,**kwargs):
        print('Get in inner_b')
        return fun(*args,**kwargs)
    return inner_b
##多個裝飾器裝飾函數,從上到下執行
@decorator_b
@decorator_a
def f(x):
    print('Gat in f')
    return x*2
f(1)

實驗效果
Get in inner_b
Get in inner_a
Gat in f

            
          

練習
[‘root’,‘admin’,‘redhat’]
多個裝飾器的應用場景:
會采用多個裝飾器先驗證是否登陸成功,再驗證登陸權限是否足夠

            
              import inspect
import functools
def is_admin(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        # inspect.getcallargs會返回一個字典,
        # key值:形參 value:對應的實參數
        inspect_res = inspect.getcallargs(fun,*args,**kwargs)
        print('inspect的返回值是:%s' %(inspect_res))
        if inspect_res.get('name') == 'root':
            temp = fun(*args,**kwargs)
            return temp
        else:
            print('not root user,no permisson add user')
    return wrapper
login_session = ['root','admin','redhat']
def is_login(fun):
    @functools.wraps(fun)
    def wrapper(*args,**kwargs):
        if args[0] in login_session:
            temp = fun(*args,**kwargs)
            return temp
        else:
            print('Error:%s 沒有登陸成功' %(args[0]))
    return wrapper
@is_login
@is_admin
def add_user(name):
    print('add user~')
add_user('root')

實驗效果
inspect的返回值是:{'name': 'root'}
add user~

            
          

帶參數的裝飾器

            
              import functools
import time

def log(kind):
    def add_log(func):
        @functools.wraps(func)
        def wrapper(*args,**kwargs):
            start_time = time.time()
            res = func(*args,**kwargs)
            end_time = time.time()
            print('<%s>[%s] 函數名:%s,運行時間:%.6f,運行返回值的'
              '結果:%d' %(kind,time.ctime(),func.__name__,
                        end_time-start_time,res))
            return res
        return wrapper
    return add_log
@log('debug')
def add(x,y):
    time.sleep(1)
    return x+y
print(add(1,2))

            
          

編寫裝飾器required_types, 條件如下:
1). 當裝飾器為@required_types(int,float)確保函數接收到的每一個參數都是int或者float類型;
2). 當裝飾器為@required_types(list)確保函數接收到的每一個參數都是list類型;
3). 當裝飾器為@required_types(str,int)確保函數接收到的每一個參數都是str或者int類型;
4). 如果參數不滿足條件, 打印 TypeError:參數必須為xxxx類型

            
              import functools
def required_types(*k):
    def required(func):
        @functools.wraps(func)
        def wrappers(*args, **kwargs):
            for i in args:
                if not isinstance(i, k):
                    print('參數必須為:', *k)
                    break
            else:
                res = func(*args, **kwargs)
                return res
        return wrappers
    return required
@required_types(int,str)
def output(*args):
    print(*args)

            
          

更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 日本一区二区三区免费观看 | 欧美福利一区二区三区 | 亚洲第一黄色网 | 91久久精品一区二区二区 | 国产精品第1页在线播放 | 久久99综合国产精品亚洲首页 | 亚洲色图国产精品 | 色综合久久中文字幕网 | 亚洲国产最新 | 欧美伊人久久综合网 | 国产综合精品 | 99久久综合给久久精品 | 欧美日韩后 | 奇米影视8888狠狠狠狠 | 亚洲精品国产综合一线久久 | 日本国产成人精品视频 | av大片| 99热精品在线 | 久久亚洲国产成人亚 | 国产精品国产午夜免费福利看 | 黄色亚洲 | 丁香花婷婷| 夜夜操av| 国产成人精品一区二区三区四区 | 亚洲日韩欧美视频 | 激情网五月 | 免费超碰 | 国产91一区二区三区 | 亚洲欧美精品中字久久99 | 黑人xxx视频 | 日韩在线免费播放 | 欧美成人性生活 | 成人 日韩 在线 | 奇米777视频| 精品日韩视频 | 一本到在线观看视频不卡 | 久久se精品一区精品二区 | 男人天堂av网站 | 日韩精品亚洲专区在线电影不卡 | 91高清在线成人免费观看 | 久久影城|