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...