小編寫這篇文章的主要目的,就是給大家介紹關(guān)于python裝飾器的用途方面的知識,這樣對我們以后的工作也是有一定的幫助,具體用途是什么呢?下面就給各位讀者詳細的解答下。
裝飾器自身的價值顯而易見,可以加強函數(shù)值基本功能、簡單化編碼、降低代碼冗余。
它的使用場景同樣很多,比較簡單的場景包含打印日志、統(tǒng)計運行時間,這類例子和用法網(wǎng)上已經(jīng)很多了:
def time_dec(func): def wrapper(*arg): t=time.clock() res=func(*arg) print func.func_name,time.clock()-t return res return wrapper time_dec def myFunction(n): ...
再進階一些的,可以用來校驗函數(shù)傳入?yún)?shù)類型、線程同步、單元測試等:
parameters( (2,4,6), (5,6,11), ) def test_add(a,b,expected): assert a+b==expected
目前可以用的裝飾器可以分為如下幾類:
自定義
第三方工具包
內(nèi)置
下面就分別來介紹一下。
自定義
關(guān)于自定義的裝飾器在前面已經(jīng)提到了,我在開發(fā)過程中經(jīng)常用到的就是日志打印、計時、數(shù)據(jù)校驗等場景,通過裝飾器可以提高代碼的簡潔性,避免重復造輪子。
除了這些基本的,也有一些比較實用的地方。
作為開發(fā)同學,肯定會遇到不同的運行環(huán)境:
開發(fā)環(huán)境
測試環(huán)境
生產(chǎn)環(huán)境
有時候,我們期望一個函數(shù)在不同環(huán)境下執(zhí)行不同的過程,產(chǎn)出不同的結(jié)果,做一些環(huán)境的隔離和差異化處理。
通過裝飾器就可以很好的解決:
production_servers=[...] def production(func:Callable): def inner(*args,**kwargs): if gethostname()in production_servers: return func(*args,**kwargs) else: print('This host is not a production server,skipping function decorated with production...') return inner def development(func:Callable): def inner(*args,**kwargs): if gethostname()not in production_servers: return func(*args,**kwargs) else: print('This host is a production server,skipping function decorated with development...') return inner def sit(func:Callable): def inner(*args,**kwargs): print('Skipping function decorated with sit...') return inner production def foo(): print('Running in production,touching databases!') foo() development def foo()
print('Running in production,touching databases!') foo()
inactive def foo(): print('Running in production,touching databases!') foo()
簡單介紹一下一下子這一段源代碼。
在這兒,一開始列舉了環(huán)境個性化服務榜單,隨后各自界定了制造、研發(fā)、測試流程的裝飾器,并給同名的的變量就能夠加上對應裝飾器。
在執(zhí)行代碼的過程中,這一段源代碼會首先獲取hostname,自動判斷所在環(huán)境,隨后執(zhí)行對應變量。
第三方工具包
上面是根據(jù)我們在開發(fā)過程中遇到的個性化場景進行來自界定一個裝飾器。
作為一款以工具包著稱的編程語言,Python中也有很多工具包提供了一些實用的裝飾器。
以日志為例,這是每個程序員都無法繞開的。
調(diào)試程序?qū)τ诖蠖鄶?shù)開發(fā)者來說是一項必不可少的工作,當我們想要知道源代碼是否按照預期的效果在執(zhí)行時,我們會想到去輸出一下子局部變量與預期的進行比對。目前大多數(shù)采用的方法主要有以下幾種:
Print函數(shù)
Log日志
IDE調(diào)試器
但是這些方法有著無法忽視的弱點:
繁瑣
過度依賴工具
其中有一款不錯的開源工具PySnooper就通過裝飾器把這個問題巧妙的解決了。
PySnooper的調(diào)用方式就是通過pysnooper.snoop的方式進行使用,該裝飾器可以傳入一些參數(shù)來實現(xiàn)一些目的,具體如下:
參數(shù)描述:
None輸出日志到控制臺
filePath輸出到日志文件,例如'log/file.log'
prefix給調(diào)試的行加前綴,便于識別
watch查看一些非局部變量表達式的值
watch_explode展開值用以查看列表/字典的所有屬性或項
depth顯示函數(shù)調(diào)用的函數(shù)的snoop行
舉個例子:
import numpy as np import pysnooper pysnooper.snoop() def one(number): mat=[] while number: mat.append(np.random.normal(0,1)) number-=1 return mat one(3)
然后,就會給出如下輸出:
Starting var:..number=3
22:17:10.634566 call 6 def one(number):
22:17:10.634566 line 7 mat=[]
New var:.......mat=[]
22:17:10.634566 line 8 while number:
22:17:10.634566 line 9 mat.append(np.random.normal(0,1))
Modified var:..mat=[-0.4142847169210746]
22:17:10.634566 line 10 number-=1
Modified var:..number=2
22:17:10.634566 line 8 while number:
22:17:10.634566 line 9 mat.append(np.random.normal(0,1))
Modified var:..mat=[-0.4142847169210746,-0.479901983375219]
22:17:10.634566 line 10 number-=1
Modified var:..number=1
22:17:10.634566 line 8 while number:
22:17:10.634566 line 9 mat.append(np.random.normal(0,1))
Modified var:..mat=[-0.4142847169210746,-0.479901983375219,1.0491540468063252]
22:17:10.634566 line 10 number-=1
Modified var:..number=0
22:17:10.634566 line 8 while number:
22:17:10.634566 line 11 return mat
22:17:10.634566 return 11 return mat
Return value:..[-0.4142847169210746,-0.479901983375219,1.0491540468063252]
局部變量值、代碼片段、局部變量所在行號、返回結(jié)果等,這些關(guān)鍵信息都輸出了,既方便,又清晰。
內(nèi)置
除了自定義和第三方工具包之外,Python還內(nèi)置了很多不錯的裝飾器,例如abc.abstractmethod、asyncio.coroutine、classmethod等等。
這里著重提一個非常強大的裝飾器,能夠極大的提升Python的運行速度和效率,通過一個裝飾器能夠?qū)ython代碼的執(zhí)行速度提升上萬倍,這個裝飾器就是functools.lru_cache。
以比較知名的斐波那契數(shù)列的例子來演示一下。
由于它遞歸計算的過程中,還會用到之前計算的結(jié)果,因此會涉及較多的重復計算,下面先看一下正常計算的耗時情況。
import time as tt def fib(n): if n<=1: return n return fib(n-1)+fib(n-2) t1=tt.time() fib(30) print("Time taken:{}".format(tt.time()-t1)) #0.2073
n等于30時,耗時0.2073。
加上functools.lru_cache裝飾器再看一下:
import time as tt import functools functools.lru_cache(maxsize=5) def fib(n): if n<=1: return n return fib(n-1)+fib(n-2) t1=tt.time() fib(30) print("Time taken:{}".format(tt.time()-t1)) #1.811981e-05
耗時為1.811981e-05,足足差了4個量級,快了10000+倍!
到此為止,關(guān)于Python裝飾器作用相關(guān)知識就為大家介紹到這里了,希望可以為各位讀者帶來幫助
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/127784.html
摘要:在中,裝飾器一般用來修飾函數(shù),實現(xiàn)公共功能,達到代碼復用的目的。智能裝飾器上節(jié)介紹的寫法,嵌套層次較多,如果每個類似的裝飾器都用這種方法實現(xiàn),還是比較費勁的腦子不夠用,也比較容易出錯。假設有一個智能裝飾器,修飾裝飾器,便可獲得同樣的能力。 在Python中,裝飾器一般用來修飾函數(shù),實現(xiàn)公共功能,達到代碼復用的目的。在函數(shù)定義前加上@xxxx,然后函數(shù)就注入了某些行為,很神奇!然而,這只...
摘要:今天就結(jié)合最近的世界杯帶大家理解下裝飾器。而德國是上屆的冠軍,又是這屆奪冠熱門。裝飾器的存在是為了適用兩個場景,一個是增強被裝飾函數(shù)的行為,另一個是代碼重用。在利用語法糖,簡化賦值操作。行為良好的裝飾器可以重用,以減少代碼量。 Python 裝飾器是在面試過程高頻被問到的問題,裝飾器也是一個非常好用的特性,熟練掌握裝飾器會讓你的編程思路更加寬廣,程序也更加 pythonic。 show...
摘要:那么,這個裝飾器要怎么定義呢我們來看一下。當然了,如果大家在網(wǎng)絡上搜索,關(guān)于如何定義裝飾器,看到的是一個更加規(guī)范的版本。在當中,調(diào)用原函數(shù)時又,即把輸入的元祖解包再傳入。 ...
摘要:一般情況下,我們使用裝飾器提供的語法糖,來簡化上面的寫法像上面的情況,可以動態(tài)修改函數(shù)或類功能的函數(shù)就是裝飾器。本文標題為會打扮的裝飾器本文鏈接為參考資料修飾器的函數(shù)式編程中的裝飾器介紹思誠之道裝飾器入門與提高賴明星 裝飾器 我們知道,在 Python 中,我們可以像使用變量一樣使用函數(shù): 函數(shù)可以被賦值給其他變量 函數(shù)可以被刪除 可以在函數(shù)里面再定義函數(shù) 函數(shù)可以作為參數(shù)傳遞給另外...
此篇文章主要是詳細介紹了python3常用3種裝飾器語法總結(jié),文中根據(jù)實例編碼為大家介紹得非常詳盡,對大家學習培訓和工作具有很強的參照參考意義,需用的小伙伴可以借鑒一下 python3常用3種裝飾器語法總結(jié) 1.概述詞法 裝飾器又稱函數(shù)公式裝飾器,主要是的作用是在沒有改動原先函數(shù)的編碼前提下(函數(shù)公式自身不被改動,實現(xiàn)方式都不轉(zhuǎn)變),提升的另一個"裝飾設計"函數(shù)公式,...
閱讀 928·2023-01-14 11:38
閱讀 902·2023-01-14 11:04
閱讀 759·2023-01-14 10:48
閱讀 2065·2023-01-14 10:34
閱讀 968·2023-01-14 10:24
閱讀 844·2023-01-14 10:18
閱讀 512·2023-01-14 10:09
閱讀 591·2023-01-14 10:02