導航:首頁 > 編程語言 > python類裝飾器參數

python類裝飾器參數

發布時間:2025-05-14 15:32:51

❶ 「低門檻 手把手」python 裝飾器(Decorators)原理說明

本文目的是由淺入深地介紹python裝飾器原理

裝飾器(Decorators)是 Python 的一個重要部分

其功能是, 在不修改原函數(類)定義代碼的情況下,增加新的功能

為了理解和實現裝飾器,我們先引入2個核心操作:

在這個例子中,函數hi的形參name,默認為'world'

在函數內部,又定義了另一個函數 howdoyoudo,定義這個函數時,將形參name作為新函數的形參name2的默認值。

因此,在函數內部調用howdoyoudo()時,將以調用hi時的實參為默認值,但也可以給howdoyoudo輸入其他參數。

上面的例子運行後輸出結果為:

這里新定義的howdoyoudo可以稱作一個「閉包」。不少關於裝飾器的blog都提到了這個概念,但其實沒必要給它取一個多專業的名字。我們知道閉包是 函數內的函數 就可以了

當我們進行 def 的時候,我們在做什麼?

這時,hi函數,列印一個字元串,同時返回一個字元串。

但hi函數本身也是一個對象,一個可以執行的對象。執行的方式是hi()。

這里hi和hi()有本質區別,

hi 代表了這個函數對象本身

hi() 則是運行了函數,得到函數的返回值。

作為對比,可以想像以下代碼

此時也是b存在,可以正常使用。

我們定義2個函數,分別實現自加1, 自乘2,

再定義一個函數double_exec,內容是將某個函數調用2次

在調用double_exec時,可以將函數作為輸入傳進來

輸出結果就是

7

27

同樣,也可以將函數作為輸出

輸出結果為

6

10

有了以上兩個核心操作,我們可以嘗試構造裝飾器了。

裝飾器的目的: 在不修改原函數(類)定義代碼的情況下,增加新的功能

試想一下,現在有一個原函數

在不修改原函數定義代碼的情況下,如果想進行函數內容的添加,可以將這個函數作為一個整體,添加到這樣的包裹中:

我們定義了一個my_decorator函數,這個函數進行了一種操作:

對傳入的f,添加操作(運行前後增加列印),並把添加操作後的內容連同運行原函數的內容,一起傳出

這個my_decorator,定義了一種增加前後列印內容的行為

調用my_decorator時,對這個行為進行了操作。

因此,new_function是一個在original_function上增加了前後列印行為的新函數

這個過程被可以被稱作裝飾。

這里已經可以發現,裝飾器本身對於被裝飾的函數是什麼,是不需要考慮的。裝飾器本身只定義了一種裝飾行為,這個行為是通過裝飾器內部的閉包函數()進行定義的。

運行裝飾前後的函數,可以清晰看到裝飾的效果

我們復現一下實際要用裝飾器的情況,我們往往有一種裝飾器,想應用於很多個函數,比如

此時,如果我們想給3個print函數都加上裝飾器,需要這么做

實際調用的時候,就需要調用添加裝飾器的函數名了

當然,也可以賦值給原函數名

這樣至少不需要管理一系列裝飾前後的函數。

同時,在不需要進行裝飾的時候,需要把

全部刪掉。

事實上,這樣並不方便,尤其對於更復雜的裝飾器來說

為此,python提供了一種簡寫方式

這個定義print1函數前的@my_decorator,相當於在定義完print1後,自動直接運行了

不論採用@my_decorator放在新函數前,還是顯示地重寫print1 = my_decorator(print1),都會存在一個問題:

裝飾後的函數,名字改變了(其實不止名字,一系列的索引都改變了)

輸出結果為:

這個現象的原因是,裝飾行為本身,是通過構造了一個新的函數(例子中是wrap_func函數)來實現裝飾這個行為的,然後把這個修改後的函數賦給了原函數名。

這樣,會導致我們預期的被裝飾函數的一些系統變數(比如__name__)發生了變化。

對此,python提供了解決方案:

經過這個行為後,被裝飾函數的系統變數問題被解決了

輸出結果為

剛才的例子都比較簡單,被裝飾的函數是沒有參數的。如果被裝飾的函數有參數,只需要在定義裝飾行為時(事實上,這個才更通用),增加(*args, **kwargs)描述即可

之前的描述中可以感受到,對於例子中的裝飾行為(前後加列印),函數被裝飾後,本質上是調用了新的裝飾函數wrap_func。

因此,如果原函數需要有輸入參數傳遞,只需要在wrap_func(或其他任意名字的裝飾函數)定義時,也增加參數輸入(*args, **kwargs),並將這些參數,原封不動地傳給待裝飾函數f。

這種定義裝飾行為的方式更具有普遍性,忘記之前的定義方式吧

我們試一下

輸出

這里需要注意的是,如果按照以下的方式定義裝飾器

那麼以下語句將不會執行

因為裝飾後實際的函數wrap_func(雖然名字被改成了原函數,系統參數也改成了原函數),運行到return f(*args, **kwargs) 的時候已經結束了

因為裝飾器my_decorator本身也是可以輸入的,因此,只需要在定義裝飾器時,增加參數,並在後續函數中使用就可以了,比如

此時裝飾器已經可以有輸入參數了

輸出

你可能發現,為什麼不用簡寫版的方法了

因為以上代碼會報錯!!

究其原因,雖然

等價於

但是,

並不等價於

這本身和@語法有關,使用@my_decorator時,是系統在應用一個以單個函數作為參數的閉包函數。即,@是不能帶參數的。

但是你應該發現了,之前的@wraps(f)不是帶參數了嗎?請仔細觀察以下代碼

通過一層嵌套,my_decorator_with_parma本質上是返回了一個參數僅為一個函數的函數(my_decorator),但因為my_decorator對my_decorator_with_parma來說是一個閉包,my_decorator_with_parma是可以帶參數的。(這句話真繞)

通過以上的定義,我們再來看

可以這么理解,my_decorator_with_parma(msg='yusheng')的結果是原來的my_decorator函數,同時,因為my_decorator_with_parma可以傳參,參數實際上是參與了my_decorator的(因為my_decorator對my_decorator_with_parma是閉包), my_decorator_with_parma(msg='yusheng') 全等於 一個有參數參加的my_decorator

因此,以上代碼等價於有參數msg傳遞的

比較繞,需要理解一下,或者乾脆強記這種範式:

以上範式包含函數的輸入輸出、裝飾器的輸入,可以應對大部分情況了。

實驗一下:

輸出

以上是一個log裝飾器,利用datetime統計了函數的耗時,

並且,裝飾器可以進行輸出文件操作,如果給出了文件路徑,則輸出文件,否則就列印。

利用這個裝飾器,可以靈活地進行耗時統計

不設置輸出文件地址,則列印。運行結果為:

也可以輸出到文件

輸出結果為

同時在當前目錄生成了一個test.log 文件,內容為:

以上的裝飾器都是以函數形式出現的,但我們可以稍做改寫,將裝飾器以類的形式實現。

這個裝飾器類Log 上個例子里的裝飾器函數log功能是一樣的,同時,這個裝飾器類還可以作為基類被其他繼承,進一步增加功能。

原文 http://www.cnblogs.com/yushengchn/p/15636944.html

❷ Python 中的 dataclass 裝飾器詳解

Python 3.7及以上版本引入了dataclass裝飾器,這是一種簡化類創建的方法。dataclass能自動生成特殊方法,如__init__、__repr__、__eq__等,從而減少重復代碼。

使用dataclass裝飾器非常簡單,只需在類定義前加上@dataclass裝飾器。例如,定義一個包含x和y屬性的Point類,dataclass裝飾器會自動生成所需的方法。

dataclass支持欄位類型註解,方便閱讀代碼,並為IDE提供類型提示。例如,給欄位指定類型,如age和address。

可以為欄位設置默認值或使用默認工廠函數。例如,設置age欄位的默認值為0,address欄位的默認值為'Unknown'。

dataclass自動生成的__repr__方法按屬性聲明順序輸出對象的字元串表示。若需自定義,可手動實現該方法。

默認情況下,dataclass生成的類是可變的。若希望生成不可變類,可在類定義中添加frozen=True參數。

dataclass支持嵌套,可在類中使用其他dataclass構建復雜數據結構。

dataclass裝飾器提供了一種簡單而強大的類創建方式,提高類的可讀性和可維護性。通過欄位類型註解、默認值和默認工廠函數,以及支持嵌套,dataclass提供了更多靈活選項。添加frozen=True參數可輕松創建不可變對象,提高數據安全性。

dataclass是一個強大的工具,簡化了類創建和管理。在數據處理和對象建模方面,使用dataclass裝飾器可讓代碼更清晰,減少樣板代碼。深入理解dataclass特性,能更好地運用這一功能,提高代碼質量和開發效率。

❸ python 帶可變參數的裝飾器怎麼用

裝飾器本身是用來是為一個函數是實現新的功能,並且不改變原函數的代碼以及調用方式。

遇到這樣一種問題:

眾多函數調用了你寫的裝飾器,但客戶有需求說,我想實現我可以隨之控制裝飾器是否生效。

那你就不可能在得到命令的時候去原函數頭部去做刪除和添加裝飾器調用的命令。這是就可以用到帶參數的裝飾器,定義一個開關,調用裝飾器的時候,把這個裝飾器的開關參數給傳遞進去,這樣當開關打開的時候裝飾器生效,關閉的時候則只執行原函數的代碼。

舉例:開關參數為True的時候執行過程:

F=True#step1裝飾器的開關變數
defouter(flag):#step2
defwrapper(func):#step4
definner(*args,**kwargs):#stpe6
ifflag:#step9
print('before')#step10
ret=func(*args,**kwargs)#step11執行原函數
print('after')#step13
else:
ret=func(*args,**kwargs)
print('123')
returnret#step14
returninner#step7
returnwrapper#step5

@outer(F)#先執行step3:outer(True)這個函數,然後step6:@wrapper#此處把開關參數傳遞給裝飾器函數
defhahaha():
pass#step12
hahaha()#step8相當於inner()

開關參數為False的時候執行過程:

F=False#stpe1裝飾器的開關變數
defouter(flag):#step2
defwrapper(func):#step4
definner(*args,**kwargs):#stpe6
ifflag:#step9
print('before')
ret=func(*args,**kwargs)
print('after')
else:
ret=func(*args,**kwargs)#step10執行原函數
print('123')#step12
returnret#step13
returninner#step7
returnwrapper#step5

❹ Python筆記:Python裝飾器

裝飾器是通過裝飾器函數修改原函數的一些功能而不需要修改原函數,在很多場景可以用到它,比如① 執行某個測試用例之前,判斷是否需要登錄或者執行某些特定操作;② 統計某個函數的執行時間;③ 判斷輸入合法性等。合理使用裝飾器可以極大地提高程序的可讀性以及運行效率。本文將介紹Python裝飾器的使用方法。

python裝飾器可以定義如下:

輸出:

python解釋器將test_decorator函數作為參數傳遞給my_decorator函數,並指向了內部函數 wrapper(),內部函數 wrapper() 又會調用原函數 test_decorator(),所以decorator()的執行會先列印'this is wrapper',然後列印'hello world', test_decorator()執行完成後,列印 'bye' ,*args和**kwargs,表示接受任意數量和類型的參數。

裝飾器 my_decorator() 把真正需要執行的函數 test_decorator() 包裹在其中,並且改變了它的行為,但是原函數 test_decorator() 不變。

一般使用如下形式使用裝飾器:

@my_decorator就相當於 decorator = my_decorator(test_decorator) 語句。

內置裝飾器@functools.wrap可用於保留原函數的元信息(將原函數的元信息,拷貝到對應的裝飾器函數里)。先來看看沒有使用functools的情況:

輸出:

從上面的輸出可以看出test_decorator() 函數被裝飾以後元信息被wrapper() 函數取代了,可以使用@functools.wrap裝飾器保留原函數的元信息:

輸出:

裝飾器可以接受自定義參數。比如定義一個參數來設置裝飾器內部函數的執行次數:

輸出:

Python 支持多個裝飾器嵌套:

裝飾的過程:

順序從里到外:

test_decorator('hello world') 執行順序和裝飾的過程相反。

輸出:

類也可以作為裝飾器,類裝飾器主要依賴__call__()方法,是python中所有能被調用的對象具有的內置方法(python魔術方法),每當調用一個類的實例時,__call__()就會被執行一次。

下面的類裝飾器實現統計函數執行次數:

輸出:

下面介紹兩種裝飾器使用場景

統計函數執行所花費的時間

輸出:

在使用某些web服務時,需要先判斷用戶是否登錄,如果沒有登錄就跳轉到登錄頁面或者提示用戶登錄:

--THE END--

❺ python裝飾器使用

裝飾器是從英文decorator翻譯過來的,從字面上來看就是對某個東西進行修飾,增強被修飾物的功能,下面我們對裝飾器做下簡單介紹。

一、怎麼編寫裝飾器

裝飾器的實現很簡單,本質是一個可調用對象,可以是函數、方法、對象等,它既可以裝飾函數也可以裝飾類和方法,為了簡單說明問題,我們實現一個函數裝飾器,如下代碼:

有了這個裝飾器,我們就可以列印出什麼時候開始和結束調用函數,對於排查函數的調用鏈非常方便。

二、帶參數的裝飾器

上面的例子無論什麼時候調用sum都會輸出信息,如果我們需要按需輸出信息怎麼實現呢,這時就要用到帶參數的裝飾器了,如下代碼:

對sum使用裝飾器時沒有參數,這時debug為0,所以調用sum時不會輸出函數調用相關信息。

對multi使用裝飾器時有參數,這時debug為1,所以調用multi時會輸出函數調用相關信息。

三、函數名字問題

當我們列印被裝飾後的函數名字時,不知道大家有沒發現輸出的不是函數本身的名字,如下代碼會輸出『wrap』而不是『sum』:

有時這種表現並不是我們想要的,我們希望被裝飾後的函數名字還是函數本身,那要怎麼實現呢?很簡單,只需要引入functools.wraps即可,如下代碼就會輸出『sum』了:

看完後是不是覺得python裝飾器很簡單,只要了解它的本質,怎麼寫都行,有好多種玩法呢。

❻ 裝飾器(Decorator)

裝飾器是Python中一種允許在代碼運行期間動態增加功能的工具。以下是關於裝飾器的詳細解答:

  1. 定義與本質

    • 裝飾器本質上是Python中的函數或類。
    • 它允許在不修改原始代碼的情況下,為函數或方法添加新功能。
  2. 關鍵特點

    • 參數為函數:裝飾器接收一個函數作為參數。
    • 返回值為函數:裝飾器返回一個新的函數,該新函數在調用時會執行原始函數並附加額外的功能。
  3. 組成原則

    • 裝飾器涉及函數、高階函數、返回值、嵌套函數和語法糖等概念。
    • 高階函數是指可以接收函數作為參數或返回函數作為結果的函數。
  4. 功能擴展

    • 通過裝飾器,可以在函數執行前後添加各種新功能,如日誌記錄、性能測試、事務處理、緩存、許可權校驗等。
    • 裝飾器不修改原函數代碼,不改變調用方式,僅增強功能。
  5. 實現示例

    • 一個常見的實現示例是通過裝飾器添加統計函數運行時間的功能。
    • 裝飾器內部會使用嵌套函數來包裝原始函數,並在調用前後添加額外的邏輯。
  6. 參數傳遞與返回值處理

    • 對於有參函數的裝飾,裝飾器需要處理額外的參數。
    • 裝飾器可以返回與原始函數相同的返回值,也可以返回修改後的結果。
  7. 多個裝飾器的執行順序

    • 當多個裝飾器應用於同一個函數時,它們會按照從外到內的順序嵌套。
    • 函數的執行順序則遵循從內到外的順序,即最內層的裝飾器最先執行,最外層的裝飾器最後執行。
  8. 應用場景與優勢

    • 裝飾器在代碼復用、功能擴展、日誌記錄、性能測試等方面具有廣泛應用。
    • 它能夠提升代碼的可維護性和可擴展性,使代碼更加簡潔和易於管理。

通過理解裝飾器的工作原理和實現方式,開發者可以更加高效地編寫和維護Python代碼。

閱讀全文

與python類裝飾器參數相關的資料

熱點內容
安卓機內存刪除怎麼恢復 瀏覽:329
Qt環境的編譯軟體放到linux 瀏覽:212
聯創列印系統怎麼連接伺服器 瀏覽:935
杭州行政命令 瀏覽:160
如何查找伺服器日誌 瀏覽:801
加密的鑰匙扣怎麼寫 瀏覽:579
文件夾更新不了怎麼辦 瀏覽:475
壓縮機指示燈亮是什麼原因 瀏覽:956
什麼app訂酒店半價 瀏覽:765
中老年解壓神器 瀏覽:243
訊飛語音ttsandroid 瀏覽:468
腰椎壓縮性骨折術後能坐車嗎 瀏覽:507
python類裝飾器參數 瀏覽:348
均線pdf微盤 瀏覽:791
女生喜歡玩的解壓游戲 瀏覽:442
支付寶暗號加密操作 瀏覽:134
柯潔在哪個app下圍棋 瀏覽:751
平板用什麼app看內在美 瀏覽:609
cad計算機命令 瀏覽:173
郵箱設置域名伺服器錯誤什麼意思 瀏覽:671