python中的decorator裝飾器(上)

来源:https://www.cnblogs.com/pitaya01/archive/2022/06/06/16348782.html
-Advertisement-
Play Games

在理解裝飾器的概念前,我們首先看一下function和inner function在python中的含義。 function與inner function function:在python中,function就像其他對象一樣,可以當做參數或返回值。 inner function:一個函數A(inne ...


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

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的引用返回,用於在將來調用。
image

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__,發現
image
這對我們來說,不是有用的信息,為了“正確”顯示,使用@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

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

帶參數的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(10000)])  

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


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • props中的children屬性 組件標簽只用有子節點的時候,props就會有該屬性; children的屬性跟props一樣的,值可以是任意值;(文本,React元素,組件,函數) 組件: <ClassCom> 傳遞的數據 </ClassCom> 這樣的組件標簽中就會有子節點 props中的ch ...
  • Srinath,科學家,軟體架構師。Apache Axis2項目的聯合創始人,Apache Software基金會的成員,WSO2流處理器(wso2.com/analytics)的聯席架構師。 Srinath通過不懈的努力最終總結出了30條架構原則,他主張架構師的角色應該由開發團隊本身去扮演,而不... ...
  • 在《clickhouse專欄》上一篇文章中《資料庫、數據倉庫之間的區別與聯繫》,我們介紹了什麼是資料庫,什麼是數據倉庫,二者的區別聯繫。clickhouse的定位是“數據倉庫”,所以理解了上一篇的內容,其實就能夠知道clickhouse適用於什麼樣的應用場景,不適合什麼樣的應用場景。 下麵本節我們就 ...
  • 庫 是一種代碼的二進位的封裝形式,將.o文件打包封裝就成了庫。庫可以在任何地方使用,但用戶卻不能看見他的具體實現。庫有利於代碼模塊化,只要介面設計得合理,改變庫的內部實現,不會影響到用戶級別的代碼使用。 動態庫 1.封裝動態庫 假設有源代碼sum.c, sub.c gcc sum.c -c -o s ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • Spring Ioc源碼分析系列--實例化Bean的幾種方法 前言 前面的文章Spring Ioc源碼分析系列--Bean實例化過程(二)在講解到bean真正通過那些方式實例化出來的時候,並沒有繼續分析了,而是留到了這裡去分析,主要是因為獲取獲取構造函數,推斷構造函數也是一個比較複雜的操作,就想另起 ...
  • 主線程與守護線程 預設情況下,Java 進程需要等待所有線程都運行結束,才會結束。有一種特殊的線程叫做守護線程,只要其它非守護線程運行結束了,即使守護線程的代碼沒有執行完,也會強制結束。 package Daemon; import lombok.extern.slf4j.Slf4j; @Slf4j ...
  • 1 與其它協程庫使用對比 這個 C 協程庫是雲風(cloudwu) 寫的,其介面風格與 Lua 協程類似,並且都是非對稱 stackful 協程。這個是源代碼中的示例: #include "coroutine.h" #include <stdio.h> struct args { int n; }; ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...