python中的decorator裝飾器(上)

在理解裝飾器的概念前,我們首先看一下function和inner function在python中的含義。

成都創新互聯是專業的瀾滄網站建設公司,瀾滄接單;提供成都網站設計、做網站,網頁設計,網站設計,建網站,PHP網站建設等專業做網站服務;采用PHP框架,可快速的進行瀾滄網站開發網頁制作和功能擴展;專業做搜索引擎喜愛的網站,專業的做網站團隊,希望更多企業前來合作!

function與inner function

  • function:在python中,function就像其他對象一樣,可以當做參數或返回值。

  • inner function:一個函數A(inner function)定義在另一個函數B中。函數A就叫做inner function。

# 函數用做參數
def hello():
    print("hello")
def welcome():
    print("Welcome")
def say_something(func):
    func()
# 函數add在函數cal中定義,并且用做返回值
def cal():
	def add(a,b):
		print(a+b)
	return add

注意:此時add不能直接被外界調用,因此此時內部函數還未定義。但可以通過cal將add的引用返回,用于在將來調用。

decorator

decorator:封裝了一個函數,并且改變了其行為

裝飾器本質上,是將要被裝飾的函數作為參數,并且返回一個包裹其的、內部定義的函數。如下所示:my_decorator返回了wrapper的引用,用于將在將來執行。

def hello():
    print("hello")
def my_decorator(func):
    def wrapper():
        print("before func work")
        func()
        print("after func work")
    return wrapper
hello_d = my_decorator(hello)
hello_d() 
"""
before func work
hello
after func work
"""

hello_d便是經過my_decorator裝飾的函數。我們明顯發現,過程有些復雜,為了簡化步驟,python提供了@decorator的語法糖。

下面,我們使用@decorator達到同樣的目的。

@my_decorator
def hello():
    print("hello")
def my_decorator(func):
    def wrapper():
        print("before func work")
        func()
        print("after func work")
    return wrapper
hello()#與hello = my_decorator(hello)作用相同
"""
before func work
hello
after func work
"""

在裝飾器中,wrapper的命名可自定義。

@functools.wrap(func)

觀察上面的例子,由于hello被my_decoratorx裝飾過,此時在python shell查看hello的__name__,發現

這對我們來說,不是有用的信息,為了“正確”顯示,使用@functools.wrap(func)

import functools
@my_decorator
def hello():
    print("hello")
def my_decorator(func):
	@functools.wrap(func)
    def wrapper():
        print("before func work")
        func()
        print("after func work")
    return wrapper

然后便可以達到和裝飾器裝飾前同樣的效果:

帶參數的decorator以及幾個例子

# do twice
def do_twice(func):
	 @functools.wraps(func)
    def wrapper(*args,**kwargs):
        func(*args,**kwargs)
        func(*args,**kwargs)
    return wrapper
# timer
def timer(func):
    @functools.wraps(func)
    def wrapper_timer(*args, **kwargs):
        start_time = time.perf_counter()
        value = func(*args, **kwargs)
        end_time = time.perf_counter()
        run_time = end_time - start_time
        print(f"Finished {func.__name__} in {run_time:.4f} seconds")
        return value
    return wrapper_timer

@timer
def waste_time(num):
    for _ in range(num):
        sum([i **2 for i in range()])  

waste_time(1000)
# flask check user login
def login_required(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        if g.user is None:
            return redirect(url_for('login',next=request.url))
        return func(*args, **kwargs)
    return wrapper
    
@app.route('/secret')
@login_required
def secret():
    ...

總結

decorator用于“包裹”一個函數,改變其行為。
在裝飾器的wrapper中并不一定要執行該函數,也可以保留函數的引用,用于插件的注冊。

參考

realpython

網站欄目:python中的decorator裝飾器(上)
分享地址:http://m.kartarina.com/article4/dsogjie.html

成都網站建設公司_創新互聯,為您提供微信公眾號、自適應網站云服務器外貿網站建設App開發、網站設計

廣告

聲明:本網站發布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創新互聯

微信小程序開發
主站蜘蛛池模板: 国产精品无码免费视频二三区| 无码中文在线二区免费| 久久美利坚合众国AV无码| 亚洲AV日韩AV永久无码色欲| 国产精品无码DVD在线观看| 无码一区二区三区| 午夜亚洲av永久无码精品| 精品人无码一区二区三区| 亚洲精品无码99在线观看| 18禁无遮挡无码国产免费网站 | 亚洲AV成人无码网站| 国产成人亚洲综合无码| 亚洲成av人片天堂网无码】| 国99精品无码一区二区三区| 一级片无码中文字幕乱伦| 中文AV人妻AV无码中文视频| 国产精品一级毛片无码视频| 欧洲精品无码成人久久久| 免费A级毛片无码视频| 无码少妇一区二区三区浪潮AV | 亚洲一区二区三区无码影院| 久久久久成人精品无码中文字幕| 一本加勒比HEZYO无码人妻| 国产精品爆乳奶水无码视频 | 亚洲AV无码一区二区三区国产 | 午夜无码视频一区二区三区| 亚洲精品中文字幕无码A片老| 亚洲成AV人片在线播放无码| 国产日产欧洲无码视频无遮挡 | 亚洲精品无码专区久久久| 国产强被迫伦姧在线观看无码 | 一本之道高清无码视频| 亚洲aⅴ无码专区在线观看| 亚洲AV无码之国产精品| 亚洲午夜无码久久久久小说| 中文字幕无码免费久久99| 少妇无码AV无码专区线| 国产免费午夜a无码v视频| 亚洲Av无码乱码在线播放| 国精品无码A区一区二区| 国产AⅤ无码专区亚洲AV|