您好,登錄后才能下訂單哦!
摘要: 本文從學(xué)習(xí)裝飾器需要用到的基礎(chǔ)知識(shí)入手, 用簡(jiǎn)單代碼附以實(shí)例驗(yàn)證,在徹底理解基礎(chǔ)知識(shí)的情況下幫助逐步理解, 裝飾器的原型
要點(diǎn): 從閉包及函數(shù)名可當(dāng)參數(shù)傳遞作為基礎(chǔ)理解思路, 由淺入深引入Python裝飾器原型, 進(jìn)而引出裝飾器
**裝飾器背景:** 在不改變?cè)瘮?shù)代碼, 且保持原函數(shù)調(diào)用方法不變的情況下, 給原函數(shù)增加新的功能 (或者給類增加新屬性和方法)
**核心思想: ** 用一個(gè)函數(shù)(或者類) 去裝修 一個(gè)舊函數(shù) (或者類) , 造出一個(gè)新函數(shù)(或者新類)
def func():
print("第三: ","我是一個(gè)函數(shù)的輸出結(jié)果")
a = 1
print("第一: 我是一個(gè)變量 ",a)
a = func #將函數(shù)名賦值給變量
print("第二: 我是一個(gè)函數(shù)名 ",a)
a()
>>>第一: 我是一個(gè)變量 1
>>>第二: 我是一個(gè)函數(shù)名 <function func at 0x000000000220AAE8>
>>>第三: 我是一個(gè)函數(shù)的輸出結(jié)果
# 根據(jù) LEGB原則, 內(nèi)函數(shù)使用外函數(shù)的局部變量
def outer():
a = 0
print("我是外部函數(shù)的 a:",a)
def inner():
print("我是內(nèi)部函數(shù)打印的 a:",a)
> > > 我是外部函數(shù)的 a: 0
> > > 我是內(nèi)部函數(shù)打印的 a: 0
# 引入 nonlocal, 內(nèi)函數(shù)可以修改外函數(shù)
def outer():
a = 0
print("我是外部函數(shù)的 a:",a)
def inner():
nonlocal a
a += 1
print("我是內(nèi)部函數(shù)加工過(guò)的 a:",a)
>>>我是外部函數(shù)的 a: 0
>>>我是內(nèi)部函數(shù)加工過(guò)的 a: 1
# 內(nèi)函數(shù) 夾帶 外函數(shù)的局部變量
def outer():
a = 0
print("我是外部函數(shù)打印的 a:",a)
def inner():
print("我是內(nèi)部函數(shù)打印的 a:",a)
return inner
res = outer() # res接收的是一個(gè)函數(shù)名
print("我是返回出來(lái)的內(nèi)函數(shù)名: "res)
res()
>>>我是外部函數(shù)打印的 a: 0
>>>我是返回出來(lái)的內(nèi)函數(shù)名: <function func at 0x000000000220AAE8>
>>>我是內(nèi)部函數(shù)打印的 a: 0
>>>
# 內(nèi)函數(shù) 夾帶 修改后的外函數(shù)的局部變量
def outer():
a = 0
print("我是外部函數(shù)打印的 a:",a)
def inner():
nonlocal a
a += 1
print("我是內(nèi)部函數(shù)修改過(guò)的 a:",a)
return inner
res = outer() # res接收的是一個(gè)函數(shù)名
print("我是返回出來(lái)的內(nèi)函數(shù)名: "res)
res()
>>>我是外部函數(shù)打印的 a: 0
>>>我是返回出來(lái)的內(nèi)函數(shù)名: <function func at 0x000000000220CA97>
>>>我是內(nèi)部函數(shù)修改過(guò)的 a: 1
#新函數(shù)對(duì)舊函數(shù)修飾
def old():
print('我是 舊函數(shù)')
def new(f):
print('我是 新函數(shù), 我可以輸出 舊函數(shù)')
f()
new( old ) #把舊函數(shù)名當(dāng)做參數(shù), 傳遞給新函數(shù), 在新函數(shù)內(nèi)產(chǎn)生變化
>>>我是 新函數(shù), 我可以輸出 舊函數(shù)
>>>我是 舊函數(shù)
# ### 利用閉包,將函數(shù)名當(dāng)參數(shù)傳遞
def outer(f):
def inner():
print("我是外部傳進(jìn)來(lái)的old :",f)
f()
print("我是修飾工,我在舊函數(shù)后顯示")
return inner
def old():
print("我是舊函數(shù)")
print("我是最初的old: ",old)
print("我是返回出來(lái)的內(nèi)函數(shù)inner: ",outer(old)) #outer把函數(shù)名old當(dāng)參數(shù)傳回函數(shù)內(nèi)部進(jìn)行加工, 把函數(shù)名inner返回
old = outer(old) #實(shí)際上, 舊函數(shù)名old已被重新賦值為inner
print("我不是原來(lái)的old了 ",old)
old() #經(jīng)過(guò)改造, 雖然調(diào)用結(jié)果不變, 但是運(yùn)行結(jié)果已變化
>>>我是最初的old: <function old at 0x00000000021CAA60>
>>>我是返回出來(lái)內(nèi)函數(shù)inner: <functionouter<locals>.inner at 0x00000000021CAAE8>
>>>我不是原來(lái)的old了 <function outer.<locals>.inner at 0x00000000021CAAE8>
>>>我是外部傳進(jìn)來(lái)的old : <function old at 0x00000000021CAA60>
>>>我是舊函數(shù)
>>>我是修飾工,我在舊函數(shù)后顯示
# ### 用 @outer 修飾
def outer(f):
def inner():
print("我是外部傳進(jìn)來(lái)的old :",f)
f()
print("我是修飾工,我在舊函數(shù)后顯示")
return inner
@outer #實(shí)際上,將 old = outer(old) 這句改成 @outer, 放在old函數(shù)上方
def old():
print("我是舊函數(shù)")
old()
>>>我是外部傳進(jìn)來(lái)的old : <function old at 0x00000000021CAA60>
>>>我是舊函數(shù)
>>>我是修飾工,我在舊函數(shù)后顯示
def kuozhan(f):
def inner():
print("1我是擴(kuò)展函數(shù),接收外部傳進(jìn)來(lái)的新old :",f)
f()
print("4我是擴(kuò)展函數(shù),我在新old函數(shù)后顯示")
return inner
def outer(f):
def inner():
print("2我是outer函數(shù),接收外部傳進(jìn)來(lái)的old :",f)
f()
print("3我是outer函數(shù),我在old函數(shù)后顯示")
return inner
@kuozhan #old = kuozhan(outer(old))
@outer #old = outer(old)
def old():
print("我是old函數(shù)")
old()
>>>1 我是擴(kuò)展函數(shù),接收外部傳進(jìn)來(lái)的新old : <function outer.<locals>.inner at 0x000000000250AB70>
>>>2 我是外部傳進(jìn)來(lái)的old : <function old at 0x000000000250AAE8>
>>> 我是old函數(shù)
>>>3 我是修飾工,我在舊函數(shù)后顯示
>>>4 我是擴(kuò)展函數(shù),我在新old函數(shù)后顯示
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。