溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

由淺入深,走進(jìn)Python裝飾器-----第一篇:基礎(chǔ),原型

發(fā)布時(shí)間:2020-03-02 15:47:56 來(lái)源:網(wǎng)絡(luò) 閱讀:421 作者:龍翔九天dl 欄目:編程語(yǔ)言

摘要: 本文從學(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ù)(或者新類)

Python萬(wàn)物皆對(duì)象, 可以隨意賦值使用

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

閉包( 延長(zhǎng)局部變量生存時(shí)間 )

# 內(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ù)名可以當(dāng)做參數(shù)傳遞

#新函數(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ù)后顯示

裝飾器的嵌套: 下層裝飾器修飾后的函數(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ù)后顯示
向AI問(wèn)一下細(xì)節(jié)

免責(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)容。

AI