裝飾器詳解

2021-09-18 04:56:41 字數 4209 閱讀 1319

1.不能修改被裝飾物件(函式)的源**(封閉)

2.不能更改被修飾物件(函式)的呼叫方式,且能達到增加功能的效果(開放)

把要被裝飾的函式作為外層函式的引數通過閉包操作後返回乙個替代版函式

被裝飾的函式:fn

外層函式:outer(func) outer(fn) => func = fn

替代版函式: return inner: 原功能+新功能

deffn(

):print

("原有功能"

)# 裝飾器

defouter

(tag)

:def

inner()

: tag(

)print

(新增功能")

return inner

fn = outer(fn)

fn()

def

outer

(f):

definner()

: f(

)print

("新增功能1"

)return inner

defwrap

(f):

definner()

: f(

)print

("新增功能2"

)return inner

@wrap # 被裝飾的順序決定了新增功能的執行順序

@outer # <==> fn = outer(fn): inner

deffn()

:print

("原有功能"

)

def

check_usr

(fn)

:# fn, login, inner:不同狀態下的login,所以引數是統一的

definner

(usr, pwd)

:# 在原功能上新增新功能

ifnot

(len

(usr)

>=

3and usr.isalpha())

:print

('賬號驗證失敗'

)return

false

# 原有功能

result = fn(usr, pwd)

# 在原功能下新增新功能

# ...

return result

return inner

@check_usr

deflogin

(usr, pwd)

:if usr ==

'abc'

and pwd ==

'123qwe'

:print

('登入成功'

)return

true

print

('登入失敗'

)return

false

# 總結:

# 1.login有引數,所以inner與fn都有相同引數

# 2.login有返回值,所以inner與fn都有返回值

"""inner(usr, pwd):

res = fn(usr, pwd) # 原login的返回值

return res

login = check_usr(login) = inner

res = login('abc', '123qwe') # inner的返回值

"""

def

wrap

(fn)

:def

inner

(*args,

**kwargs)

:print

('前增功能'

) result = fn(

*args,

**kwargs)

print

('後增功能'

)return result

return inner

@wrap

deffn1()

:print

('fn1的原有功能'

)@wrap

deffn2

(a, b)

:print

('fn2的原有功能'

)@wrap

deffn3()

:print

('fn3的原有功能'

)return

true

@wrap

deffn4

(a,*

, x)

:print

('fn4的原有功能'

)return

true

fn1(

)fn2(10,

20)fn3(

)fn4(

10, x=

20)

# 了解

defouter

(input_color)

:def

wrap

(fn)

:if input_color ==

'red'

: info =

'\033[36;41mnew action\33[0m'

else

: info =

'yellow:new action'

definner

(*args,

**kwargs)

:pass

result = fn(

*args,

**kwargs)

print

(info)

return result

return inner

return wrap # outer(color) => wrap

color =

input

('color: '

)@outer(color)

# @outer(color) ==> @wrap # func => inner

deffunc()

:print

('func run'

)func(

)

is_login =

false

# 登入狀態

deflogin()

: usr =

input

('usr: ')if

not(

len(usr)

>=

3and usr.isalpha())

:print

('賬號驗證失敗'

)return

false

pwd =

input

('pwd: '

)if usr ==

'abc'

and pwd ==

'123qwe'

:print

('登入成功'

) is_login =

true

else

:print

('登入失敗'

) is_login =

false

# 完成乙個登入狀態校驗的裝飾器

defcheck_login

(fn)

:def

inner

(*args,

**kwargs)

:# 檢視個人主頁或銷售功能前:如果沒有登入先登入,反之可以進入其功能

if is_login !=

true

:print

('你未登入'

) login(

)# 檢視個主頁或銷售

result = fn(

*args,

**kwargs)

return result

return inner

# 檢視個人主頁功能

@check_login

defhome()

:print

('個人主頁'

)# 銷售功能

@check_login

defsell()

:print

('可以銷售'

)home(

)

python裝飾器 python 裝飾器詳解

def outer x def inner y return x y return inner print outer 6 5 11 如 所示,在outer函式內,又定義了乙個inner函式,並且inner函式又引用了外部函式outer的變數x,這就是乙個閉包了。在輸出時,outer 6 5 第乙個...

python裝飾器詳解 python裝飾器詳解

按照 python 的程式設計原則,當乙個函式被定義後,如要修改或擴充套件其功能應盡量避免直接修改函式定義的 段,否則該函式在其他地方被呼叫時將無法正常執行。因此,當需要修改或擴充套件已被定義的函式的功能而不希望直接修改其 時,可以使用裝飾器。先來看乙個簡單的例子 def func1 functio...

詳解Python裝飾器

裝飾器的難點 在梳理了裝飾器的整個內容之後,我認為難點不是裝飾器本身,而是直接呼叫被裝飾的函式,讓人無法理解背後究竟發生了什麼。一 引出裝飾器概念 引入問題 定義了乙個函式,想在執行時動態的增加功能,又不想改動函式本身的 示例 希望對下列函式呼叫增加log功能,列印出函式呼叫 def f1 x re...