詳解Python裝飾器

裝飾器是可調用的對象,其參數是是另一個函數(被裝飾的函數), 

其實...我個人理解.. 裝飾器的提出

說白了就是懶...

懶在我們這卻是是個褒義詞.

因爲懶出現了框架

因爲懶出現了各種包

因爲懶出現裝飾器

裝飾器的原理你可以這麼理解. 說白了就是有10方法都要加上這A的業務..

但是動原代碼. 你有不太想 

但是你又只想寫一遍

那麼裝飾器就來了.

記錄日誌捕獲異常... 你肯定不想一直寫try ex

記錄函數運行時間...  因爲優化時要用

我一般用這兩個用的多

這是一個最簡單的捕獲異常裝飾器例子

下面是重點啊 面試經常問!!!

面試官會問裝飾器有幾種用法?

兩種!

上面和下面一樣,

第二種是傳參效果一樣

嚴格來說裝飾器只是語法糖

說一下運行流程..

運行當前文件. 運行

當前方法testMut()

第一步走到的事@decotatorError

這時候走到了裝飾器中
然後decotatorError這個函數有一個參數 參數就是testMut()函數

然後走裝飾器!

最後返回

面試時候問.. 裝飾器怎麼運行的  答自上到下就夠了!

說說原理

testMut()是一個地址 

decotatorError也是一個地址

被裝飾的任何一個函數

都被拉到decotatorError裏來了.

最後返回的其實並不是 testMut這個函數的地址

而是decotatorError的地址

天天用裝飾器, 其實! 把人家原來的名字都換了!

不信你們用flask用上路由在用上裝飾器!

不用試了! 就是報錯!

報的錯我都知道.. 循環導入

爲什麼呢. flask路由的實現其實就是裝飾器

url爲key fun爲值  咱們每一次寫url 是不是總@app.route(url)

這就是key了.. 而我們每一個被route裝飾的函數 就是value了. 但是!

value的值.. 是function的地址

要解決. 要不把人家的地址還給人家

要不在外層函數上再加一個裝飾器

@functoolwraps(被裝飾函數)

我猜肯定又要問... 爲啥django不會這樣啊

我曾也看過django路由的源碼..

是循環實現的.所以django的路由沒有flask的快

爲啥? 我有一篇文章寫的很詳細

爲什麼dict查詢最快

千萬別忘了... 裝飾器會修改原有fun的地址

最後在提一個非常實用的裝飾器... 做計算的注意啊!

內置的!

functools.lru_cache是一個非常實用的裝飾器, 它實現了備忘功能 這是一項優化技術,

它把耗時的函數的結果保存起來.. 避免傳入相同的參數時重複計算 LRU三個字符是"Least Recently Used"縮寫!

表示緩存不會無限增長 一段時間不用的緩存條目就被扔掉

說白了. 就是一堆數據 要進入這個函數進行計算.. 第一次是進入計算的

第二次..lru發現一樣的數據存在.. 就不進入計算了. 直接返回保留下來的計算值

好神奇這個裝飾器 一起看看源碼吧...

nonlocal關鍵字用來在函數或其他作用域中使用外層(非全局)變量。

"""Least-recently-used cache decorator.

If *maxsize* is set to None, the LRU features are disabled and the cache
can grow without bound.

If *typed* is True, arguments of different types will be cached separately.
For example, f(3.0) and f(3) will be treated as distinct calls with
distinct results.

Arguments to the cached function must be hashable.

View the cache statistics named tuple (hits, misses, maxsize, currsize)
with f.cache_info().  Clear the cache and statistics with f.cache_clear().
Access the underlying function with f.__wrapped__.

See:  http://en.wikipedia.org/wiki/Cache_algorithms#Least_Recently_Used

"""

# Users should only access the lru_cache through its public API:
#       cache_info, cache_clear, and f.__wrapped__
# The internals of the lru_cache are encapsulated for thread safety and
# to allow the implementation to change (including a possible C version).

# Early detection of an erroneous call to @lru_cache without any arguments
# resulting in the inner function being passed to maxsize instead of an
# integer or None.

源碼的註釋

如果 maxsize 設置爲none,則禁用LRU功能並緩存

可以自己設置最大長度

如果 typed 爲true,則將分別緩存不同類型的參數。

例如,F(3.0)和F(3)將被視爲具有

第一個閉包.. 在成功後回調更新數據

第二個不緩存信息

第三個緩存限制

就不一一截圖了太累了>. 自己看源碼吧...這個真的很好用

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章