<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
裝飾器的價值不言而喻,可以用來增強函數功能、簡化程式碼、減少程式碼冗餘。
它的使用場景同樣很多,比較簡單的場景包含列印紀錄檔、統計執行時間,這類例子和用法網上已經很多了:
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): ...
再進階一些的,可以用來校驗函數傳入引數型別、執行緒同步、單元測試等:
@parameters( (2, 4, 6), (5, 6, 11), ) def test_add(a, b, expected): assert a + b == expected
目前可以用的裝飾器可以分為如下幾類:
下面就分別來介紹一下。
關於自定義的裝飾器在前面已經提到了,我在開發過程中經常用到的就是紀錄檔列印、計時、資料校驗等場景,通過裝飾器可以提高程式碼的簡潔性,避免重複造輪子。
除了這些基本的,也有一些比較實用的地方。
作為開發同學,肯定會遇到不同的執行環境:
有時候,我們期望一個函數在不同環境下執行不同的過程,產出不同的結果,做一些環境的隔離和差異化處理。
通過裝飾器就可以很好的解決:
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()
簡單的介紹一下這段程式碼。
在這裡,先是羅列了生產環境的服務列表,然後分別定義了生產、開發、測試環境的裝飾器,然後給同名的函數就可以配上對應的裝飾器。
在執行程式碼的過程中,這段程式碼會首先獲取hostname,自動判斷所在環境,然後執行對應函數。
上面是根據我們在開發過程中遇到的個性化場景進行來自定義一個裝飾器。
作為一款以工具包著稱的程式語言,Python中也有很多工具包提供了一些實用的裝飾器。
以紀錄檔為例,這是每個程式設計師都無法繞開的。
偵錯程式對於大多數開發者來說是一項必不可少的工作,當我們想要知道程式碼是否按照預期的效果在執行時,我們會想到去輸出一下區域性變數與預期的進行比對。目前大多數採用的方法主要有以下幾種:
但是這些方法有著無法忽視的弱點:
其中有一款不錯的開源工具PySnooper就通過裝飾器把這個問題巧妙的解決了。
PySnooper的呼叫方式就是通過@pysnooper.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]
區域性變數值、程式碼片段、區域性變數所在行號、返回結果等,這些關鍵資訊都輸出了,既方便,又清晰。
除了自定義和第三方工具包之外,Python還內建了很多不錯的裝飾器,例如@abc.abstractmethod、@asyncio.coroutine、@classmethod等等。
這裡著重提一個非常強大的裝飾器,能夠極大的提升Python的執行速度和效率,通過一個裝飾器能夠將Python程式碼的執行速度提升上萬倍,這個裝飾器就是@functools.lru_cache。
以比較知名的斐波那契數列的例子來演示一下。
由於它遞迴計算的過程中,還會用到之前計算的結果,因此會涉及較多的重複計算,下面先看一下正常計算的耗時情況。
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+倍!
到此這篇關於Python裝飾器有哪些絕妙的用法的文章就介紹到這了,更多相關Python裝飾器內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45