Python內置裝飾器太強了
裝飾器可以在編寫更少、更簡單代碼的基礎上實現復雜的邏輯,并在任何地方都能調用
是體現“Python 之禪”的最佳Python特性
有許多很棒的內置Python裝飾器使得效率蹭蹭上漲,只需使用一行代碼就可以為現有函數或類添加復雜的功能
一起來看看吧!
1.@lru_cache:通過緩存加速程序
使用緩存技巧加速 Python 函數的最簡單方法是使用@lru_cache
裝飾器
這個裝飾器可以用來緩存一個函數的結果,這樣后續(xù)調用相同參數的函數就不會再執(zhí)行了
它對于計算量大或使用相同參數頻繁調用的函數特別有用
看一個直觀的例子:
該例是經典的計算斐波那契數
計算fibonacci(30)
的時候很耗時,很多前面的Fibonacci數在遞歸過程中會重復計算多次
現在,使用@lru_cache
裝飾器來加速它:
如上所示,使用@lru_cache
裝飾器后,可以在0.00002990
秒內得到相同的結果,比之前的0.18129450
秒快了很多
@lru_cache
裝飾器有一個maxsize
參數,指定存儲在緩存中的最大結果數
當緩存已滿并且需要存儲新結果時,最近最久未使用的結果將從緩存中彈出
這稱為最近最久未使用 (Least Recently Used,LRU) 策略
默認情況下,maxsize
設置為128
如果將其設置為None
,如示例,LRU 功能將被禁用,并且緩存可以無限增長
2. @total_ordering:類裝飾器,填充缺失的比較方法
來自functools
模塊的@total_ordering
裝飾器,用于根據定義的方法為Python類生成缺少的比較方法
例如:
如上所示,在Student
類中沒有定義__ge__
、__gt__?
和?__le__?
方法
但是,@total_ordering
的存在,讓我們在不同實例之間的比較結果都是正確的,優(yōu)點顯而易見
可以使代碼更清晰并節(jié)省時間,因為不需要寫所有的比較方法
一些舊類可能沒有定義足夠的比較方法,
@total_ordering
裝飾器確保使用安全
3. @contextmanager:制作定制的上下文管理器
Python提供上下文管理器機制來幫助正確的管理資源
大多數情況下,我們都知道使用with
語句:
如上,使用with
語句打開一個文件,寫入后自動關閉
不需要顯式的調用f.close()
函數來關閉文件
有時,需要為一些特殊的需求定義一個自定義的上下文管理器
在這種情況下,@contextmanager
裝飾器該登場了
例如,下面的代碼實現了一個簡單的自定義上下文管理器,可以在文件打開或關閉時打印相應的信息
4. @property:為Python類設置getter和setter
getter和setter是面向對象編程(OOP)中的重要概念
對于類的每個實例變量,getter方法返回它的值,而setter方法設置或更新它的值
鑒于此,getter和setter也分別稱為訪問器和修改器
二者用于保護數據不被直接和意外地訪問或修改
不同的OOP語言有不同的機制來定義getter和setter
在Python中,可以簡單地使用@property
裝飾器
如上所示,score
變量不能設置為 999,這是一個無意義的數字
因為使用@property
裝飾器在setter函數中限制了它的可接受范圍
5. @cached_property:將方法的結果緩存為屬性
Python3.8為functool
模塊引入了一個新的強大裝飾器——@cached_property
可以將一個類的方法轉換為一個屬性,該屬性的值計算一次,然后在實例的生命周期內作為普通屬性緩存
在上面的代碼中,通過@cached_property
修飾了area
方法
所以沒有對同一個不變實例的circle.area
進行重復計算
6. @classmethod:在Python類中定義類方法
在Python類中,有3種可能的方法類型:
實例方法:綁定到實例的方法??梢栽L問和修改實例數據。在類的實例上調用實例方法,可以通過
self
參數訪問實例數據類方法:綁定到類的方法。不能修改實例數據。在類本身上調用類方法,接收類作為第一個參數,通常命名為
cls
靜態(tài)方法:未綁定到實例或類的方法
實例方法可以定義為普通的Python函數,只要第一個參數是self
但是,要定義一個類方法,需要使用@classmethod
裝飾器
為了演示,以下示例定義了一個類方法,可用于通過radius獲取Circle
實例:
7. @staticmethod:在Python類中定義靜態(tài)方法
如前所述,靜態(tài)方法不綁定到實例或類
被包含在一個類中只是因為在邏輯上屬于那個類
靜態(tài)方法通常用于執(zhí)行一組相關任務(例如數學計算)的實用程序類中
通過將相關函數組織到類中的靜態(tài)方法中,代碼將變得更有條理且更易于理解
要定義一個靜態(tài)方法,只需要使用@staticmethod
裝飾器
看一個例子:
8. @dataclass:用更少的代碼定義特殊類
@dataclass
裝飾器(Python 3.7引入)可以自動為一個類生成幾個特殊的方法,如__init__
、__repr__
、__eq__
、__lt__
等
因此,可以節(jié)省大量編寫這些基本方法的時間
如果一個類主要用于存儲數據,那么@dataclass
裝飾器是最需要被考慮的
下面的示例只定義了一個名為Point
的類的兩個數據字段
9. @atexit.register:注冊一個在程序正常終止時執(zhí)行的函數
來自atexit
模塊的@register
裝飾器可以在Python解釋器退出時執(zhí)行一個函數
這個裝飾器對于執(zhí)行最終任務非常有用,例如釋放資源
例如:
輸出是:
如示例所示,由于使用@register
裝飾器,終端打印了“Bye bye!”
即使沒有顯式調用goodbye
函數