使用python差不多已經(jīng)有一年多了,回頭來看.自己有很多地方?jīng)]有理解,一直拖著直到現(xiàn)在.其中python中的裝飾器跟閉包.這倆個(gè)概念就是如此.
今天是2018.06.20號(hào)周三,小目標(biāo)是周五晚上24:00之前將本篇的博文整理出來.(失敗周四到周日墮落了四天,尤其是周末),
不探討別的就是把自己對(duì)于裝飾器跟閉包的理解寫下來.
其中探討一下以下幾個(gè)話題:
- 什么是閉包?
- 什么是裝飾器?
- 它們之間有什么聯(lián)系?
- python 是如何計(jì)算裝飾器方法的锯玛?
- 閉包存在的原因和工作問題妓羊?
什么是閉包?
閉包指的是延伸了作用域的函數(shù),其中包含函數(shù)定義體中引用,但是不在定義體中定義的非全局變量.函數(shù)是不是匿名的沒有關(guān)系,關(guān)鍵是它能訪問定義體之外定義的非全局變量.
這里面有以下幾點(diǎn)需要認(rèn)清楚一下:
a = make_averager()
a(10) -----> 10
a(11) ----->10.5
a(12) ----->11
- 實(shí)例化
make_averager()
,你在運(yùn)行的其實(shí)會(huì)調(diào)用里面的averager()
函數(shù). series是一個(gè)可變對(duì)象,在averager()
之外,調(diào)用averager()
時(shí)它訪問了在它本身定義的非全局變量series
.但是如果series
是一個(gè)不可變對(duì)象則會(huì)出錯(cuò),函數(shù)averager
會(huì)將它變成一個(gè)局部變量,并且報(bào)錯(cuò).
裝飾器(decorate)
關(guān)于裝飾器的小問題.
- 什么是裝飾器史翘?
裝飾器僅僅是這樣的函數(shù):(通常)接受被裝飾的可調(diào)用函數(shù)作為唯一參數(shù),并返回一個(gè)可點(diǎn)用函數(shù).
當(dāng)裝飾器應(yīng)用到裝飾函數(shù)時(shí)(而不是調(diào)用裝飾器時(shí)),會(huì)執(zhí)行裝飾器代碼本身 - 裝飾器的功能是什么?
- 裝飾器的的順序锨侯。
裝飾器的應(yīng)用是自底向上 - 裝飾器的本質(zhì)临燃。
- 何處使用裝飾器橱乱?
如果使用一個(gè)類上的方法不需要這個(gè)這個(gè)類的實(shí)例办成,可以使用@classmethod 或者是@staticmethod裝飾器。 - 編寫裝飾器的理由
裝飾器提供了一種絕妙的方式來告知,"在指定的位置,我想要這個(gè)指定的可重復(fù)使用的功能片段" - 編寫裝飾器的時(shí)機(jī).
- 數(shù)據(jù)的清理或添加
裝飾器可以清理傳遞給被裝飾器函數(shù)的參數(shù)的值.
裝飾器可以改變或清除從函數(shù)中返回的數(shù)據(jù). - 函數(shù)的注冊(cè).
- 數(shù)據(jù)的清理或添加
編寫裝飾器
執(zhí)行時(shí)封裝代碼
這種裝飾器非常簡(jiǎn)單,因?yàn)楸谎b飾函數(shù)實(shí)在未經(jīng)修改的條件下傳遞的.但是,執(zhí)行被裝飾方法時(shí),可能希望運(yùn)行額外的功能.為此,可以返回一個(gè)添加合適功能切在執(zhí)行過程中調(diào)用被裝飾方法的可調(diào)用函數(shù).
一個(gè)簡(jiǎn)單的類型檢查
def requires_ints(deocrated):
def inner(*args, **kwargs):
kwargs_values = [i for i in kwargs.values()]
for arg in list(args) + kwargs_values:
if not isinstance(arg, int):
raise TypeError('{} only accepts interges as arguments'.format(deocrated.__name__))
return deocrated(*args, **kwargs)
return inner
裝飾器自身是requires_ints
.它接受一個(gè)參數(shù):decorated
,即被裝飾的可調(diào)用函數(shù). 在這里裝飾器唯一做的事情就是返回一個(gè)新的可調(diào)用的函數(shù),即本地函數(shù)inner
.該函數(shù)代替了被裝飾方法.
@requires_ints
def foo(x, y):
"""Return the sum of x and y."""
return x + y
運(yùn)行help(foo)
Help on function inner in module __main__:
inner(*args, **kwargs)
將名稱foo賦給inner函數(shù),而不是賦給原來被定義的函數(shù).
如果運(yùn)行foo(3,5)
.
- 首先用傳入的這個(gè)兩個(gè)參數(shù)運(yùn)行
inner
函數(shù). -
inner
函數(shù)執(zhí)行類型檢查. - 然后運(yùn)行被裝飾的方法
- 簡(jiǎn)單的來說運(yùn)行順序?yàn)?
- 裝飾器在調(diào)用那一瞬間便已經(jīng)運(yùn)行了起來.在這里
foo
函數(shù)經(jīng)過requires_ints
裝飾器,已經(jīng)變?yōu)?code>inner函數(shù).(裝飾器唯一做的事情就是返回一個(gè)新的可調(diào)用的函數(shù)) -
foo(3,5)
==>inner(3,5)
來驗(yàn)證傳入的變量是否為integers
- 驗(yàn)證完成之返回
foo(3,5)
即8
,完成整個(gè)過程
- 裝飾器在調(diào)用那一瞬間便已經(jīng)運(yùn)行了起來.在這里
保存幫助信息
裝飾器時(shí)用于添加通用和可重復(fù)使用功能的工具,相對(duì)模糊的注釋是有必要的,如果使用函數(shù)的人相對(duì)函數(shù)執(zhí)行help,那么他只希望了解函數(shù)的核心信息,而不是關(guān)于shell
的信息.
@functools.wraps
的裝飾器將一個(gè)函數(shù)中的重要內(nèi)部元素復(fù)制到另一個(gè)函數(shù).