欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

python必學(xué)知識(shí)之裝飾器詳解

 更新時(shí)間:2023年09月22日 10:19:55   作者:生有涯,知無(wú)涯  
這篇文章主要介紹了python必學(xué)知識(shí)之裝飾器詳解,python的三大器指的是:裝飾器、迭代器、生成器,下面就裝飾器整理一下從各種資源收獲的對(duì)裝飾器的理解,需要的朋友可以參考下

1.函數(shù)引用的概念

理解裝飾器之前先要理解函數(shù)引用的概念

def func():
	print("hello world!")
# 調(diào)用函數(shù)
func()
# 引用函數(shù)
ret = func
print(id(ret))
print(id(func))
# 通過(guò)引用調(diào)用函數(shù)
ret()

運(yùn)行結(jié)果ret和func的id相同,python里一切皆對(duì)象,函數(shù)名也是一個(gè)對(duì)象,ret是func函數(shù)的引用,它也指向func函數(shù)?;蛘呤呛瘮?shù)名僅僅是個(gè)變量,只不過(guò)指向了定義的函數(shù)而已,所以才能通過(guò) 函數(shù)名() 調(diào)用

2.理解閉包的概念

理解:先定義一個(gè)函數(shù),然后在該函數(shù)內(nèi)部再定義一個(gè)函數(shù),并且這個(gè)函數(shù)用到了外邊函數(shù)的變量,那么將這個(gè)函數(shù)以及用到的一些變量稱之為閉包

# 定義一個(gè)函數(shù)
def func(num1):
	 # 在函數(shù)內(nèi)部再定義一個(gè)函數(shù),并且這個(gè)函數(shù)用到了外邊函數(shù)的變量,那么將這個(gè)函數(shù)以及用到的一些變量稱之為閉包
	def wrapper(num2):
		# 在python3中,如果要修改外部函數(shù)的變量,需要加一條申明: nonlocal 外部變量名
		# nonlocal num1
		# num += 1
		print("%s * %s 的積是%s" % (num1, num2, num1 * num2))
		return num1 * num2
	# 其實(shí)這里返回的就是閉包的結(jié)果,即返回內(nèi)層函數(shù)的引用
	return wrapper
# 給func函數(shù)賦值,這個(gè)20就是給參數(shù)num1
ret = func(20)    # 等價(jià)于ret = wrapper
# 注意這里的100其實(shí)給參數(shù)num2
print(ret(100))    # 等同于 print(wrapper(100))

運(yùn)行結(jié)果將會(huì)顯示 20 * 100 的積是2000 注意點(diǎn): 由于閉包引用了外部函數(shù)的局部變量,則外部函數(shù)的局部變量沒(méi)有及時(shí)釋放,消耗內(nèi)存

3.裝飾器

裝飾器是程序開(kāi)發(fā)中經(jīng)常會(huì)用到的一個(gè)功能,用好了裝飾器,開(kāi)發(fā)效率如虎添翼,所以這也是Python面試中必問(wèn)的問(wèn)題。 假設(shè)下以下場(chǎng)景:

1.公司原本開(kāi)發(fā)了一套軟件,各個(gè)部門一起合作開(kāi)發(fā),目前公司有條不紊的進(jìn)行著,但是,以前基礎(chǔ)平臺(tái)的開(kāi)發(fā)人員在寫(xiě)代碼時(shí)候沒(méi)有關(guān)注驗(yàn)證相關(guān)的問(wèn)題,即需要增加以下功能:在所有功能執(zhí)行前,先進(jìn)行權(quán)限驗(yàn)證。

2.老大把工作交給 Low B,他是這么做的: 跟每個(gè)業(yè)務(wù)部門交涉,每個(gè)業(yè)務(wù)部門自己寫(xiě)代碼,調(diào)用基礎(chǔ)平臺(tái)的功能之前先驗(yàn)證。這樣一來(lái)基礎(chǔ)平臺(tái)就不需要做任何修改了。

太棒了,有充足的時(shí)間泡妹子… 當(dāng)天Low B 被開(kāi)除了…

3.老大把工作交給 Low BB,他是這么做的:

############### 基礎(chǔ)平臺(tái)提供的功能如下 ############### 
def f1():
    # 驗(yàn)證1
    # 驗(yàn)證2
    # 驗(yàn)證3
    print('f1')
def f2():
    # 驗(yàn)證1
    # 驗(yàn)證2
    # 驗(yàn)證3
    print('f2')
def f3():
    # 驗(yàn)證1
    # 驗(yàn)證2
    # 驗(yàn)證3
    print('f3')
def f4():
    # 驗(yàn)證1
    # 驗(yàn)證2
    # 驗(yàn)證3
    print('f4')
############### 業(yè)務(wù)部門不變 ############### 
### 業(yè)務(wù)部門A 調(diào)用基礎(chǔ)平臺(tái)提供的功能### 
f1()
f2()
f3()
f4()
### 業(yè)務(wù)部門B 調(diào)用基礎(chǔ)平臺(tái)提供的功能 ### 
f1()
f2()
f3()
f4()
過(guò)了一周 Low BB 被開(kāi)除了…

4.老大把工作交給 Low BBB,他是這么做的: 只對(duì)基礎(chǔ)平臺(tái)的代碼進(jìn)行重構(gòu),其他業(yè)務(wù)部門無(wú)需做任何修改

############### 基礎(chǔ)平臺(tái)提供的功能如下 ############### 
def check_login():
    # 驗(yàn)證1
    # 驗(yàn)證2
    # 驗(yàn)證3
    pass
def f1():
    check_login()
    print('f1')
def f2():
    check_login()
    print('f2')
def f3():
    check_login()
    print('f3')
def f4():
    check_login()
    print('f4')

老大看了下Low BBB 的實(shí)現(xiàn),嘴角漏出了一絲的欣慰的笑,語(yǔ)重心長(zhǎng)的跟Low BBB聊了個(gè)天:

5.老大說(shuō): 寫(xiě)代碼要遵循開(kāi)放封閉原則,雖然在這個(gè)原則是用的面向?qū)ο箝_(kāi)發(fā),但是也適用于函數(shù)式編程,簡(jiǎn)單來(lái)說(shuō),它規(guī)定已經(jīng)實(shí)現(xiàn)的功能代碼不允許被修改,但可以被擴(kuò)展,即:

  • 封閉:已實(shí)現(xiàn)的功能代碼塊
  • 開(kāi)放:對(duì)擴(kuò)展開(kāi)發(fā)

如果將開(kāi)放封閉原則應(yīng)用在上述需求中,那么就不允許在函數(shù) f1 、f2、f3、f4的內(nèi)部進(jìn)行修改代碼,老板就給了Low BBB一個(gè)實(shí)現(xiàn)方案:

def w1(func):
    def inner():
        # 驗(yàn)證1
        # 驗(yàn)證2
        # 驗(yàn)證3
        func()
    return inner
@w1
def f1():
    print('f1')
@w1
def f2():
    print('f2')
@w1
def f3():
    print('f3')
@w1
def f4():
    print('f4')

對(duì)于上述代碼,也是僅僅對(duì)基礎(chǔ)平臺(tái)的代碼進(jìn)行修改,就可以實(shí)現(xiàn)在其他人調(diào)用函數(shù) f1 f2 f3 f4 之前都進(jìn)行【驗(yàn)證】操作,并且其他業(yè)務(wù)部門無(wú)需做任何操作。

4.詳解裝飾器

4.1 裝飾器執(zhí)行流程

在這里插入圖片描述

4.2 帶多個(gè)參數(shù)的裝飾器

例如記錄某個(gè)函數(shù)的執(zhí)行時(shí)間

import time
def timer(func):
    def inner(*args,**kwargs):
        start = time.time()
        re = func(*args,**kwargs)
        print(time.time() - start)
        return re
    return inner
@timer   #==> func2 = timer(func2)
def func2(a):
    print('in func2 and get a:%s'%(a))
    return 'fun2 over'
func2('aaaaaa')
print(func2('aaaaaa'))

4.3 給裝飾器帶參數(shù)

def outer(flag):
    def timer(func):
        def inner(*args,**kwargs):
            if flag:
                print('''執(zhí)行函數(shù)之前要做的''')
            re = func(*args,**kwargs)
            if flag:
                print('''執(zhí)行函數(shù)之后要做的''')
            return re
        return inner
    return timer
# 下面的裝飾過(guò)程
# 1. 調(diào)用outer(False)
# 2. 將步驟1得到的返回值,即timer返回, 然后timer(func),這里的func指向定義的func函數(shù)
# 3. 將timer(func)的結(jié)果返回,即inner
# 4. 讓func = inner,即func現(xiàn)在指向inner
@outer(False)    
def func():   
    print(111)
func()

調(diào)用時(shí)候的func()可以理解為:func() ====> outer(Flase)(func)()

4.4裝飾器的功能:

在不修改原函數(shù)及其調(diào)用方式的情況下對(duì)原函數(shù)功能進(jìn)行擴(kuò)展。

4.5.裝飾器應(yīng)用場(chǎng)景:

(1)引入日志

(2)函數(shù)執(zhí)行時(shí)間統(tǒng)計(jì)

(3)執(zhí)行函數(shù)前預(yù)備處理

(4)執(zhí)行函數(shù)后清理功能

(5)權(quán)限校驗(yàn)等場(chǎng)景

(6)緩存

4.6 functools的應(yīng)用

正常我們情況下查看函數(shù)的一些信息的方法在此處都會(huì)失效

def outer(func):
    def inner(*args,**kwargs):
        """hello world"""
        return func(*args,**kwargs)
    return inner
@outer
def index():
    '''你好,世界'''
    print('hello world!')
print("函數(shù)注釋:%s" % index.__doc__)    #查看函數(shù)注釋的方法
print("函數(shù)名:%s" % index.__name__)   #查看函數(shù)名的方法

上述代碼返回的結(jié)果是:

在這里插入圖片描述

很顯然,這不是我們需要的結(jié)果。我們希望得到的是被裝飾的函數(shù)的函數(shù)名和注釋。

functools的wraps能夠?qū)⒃械暮瘮?shù)名返回,需要使用functools.wraps在裝飾器中的函數(shù)上把傳進(jìn)來(lái)的這個(gè)函數(shù)進(jìn)行一個(gè)包裹,這樣就不會(huì)丟失原來(lái)的函數(shù)的__name__等屬性.

from functools import wraps
def outer(func):
    @wraps(func)
    def inner(*args,**kwargs):
        """hello world"""
        return func(*args,**kwargs)
    return inner
@outer
def index():
    '''你好,世界'''
    print('hello world!')
print("函數(shù)注釋:%s" % index.__doc__)    #查看函數(shù)注釋的方法
print("函數(shù)名:%s" % index.__name__)   #查看函數(shù)名的方法

運(yùn)行結(jié)果為:

在這里插入圖片描述

5.類裝飾器

class Test(object):
    def __init__(self, func):
        print("---初始化---")
        print("func name is %s"%func.__name__)
        self.__func = func
    def __call__(self):
        print("---裝飾器中的功能---")
        self.__func()
#說(shuō)明:
#1. 當(dāng)用Test來(lái)裝作裝飾器對(duì)test函數(shù)進(jìn)行裝飾的時(shí)候,首先會(huì)創(chuàng)建Test的實(shí)例對(duì)象
#   并且會(huì)把test這個(gè)函數(shù)名當(dāng)做參數(shù)傳遞到__init__方法中
#   即在__init__方法中的屬性__func指向了test指向的函數(shù)
#
#2. test指向了用Test創(chuàng)建出來(lái)的實(shí)例對(duì)象
#
#3. 當(dāng)在使用test()進(jìn)行調(diào)用時(shí),就相當(dāng)于讓這個(gè)對(duì)象(),因此會(huì)調(diào)用這個(gè)對(duì)象的__call__方法
#
#4. 為了能夠在__call__方法中調(diào)用原來(lái)test指向的函數(shù)體,所以在__init__方法中就需要一個(gè)實(shí)例屬性來(lái)保存這個(gè)函數(shù)體的引用
#   所以才有了self.__func = func這句代碼,從而在調(diào)用__call__方法中能夠調(diào)用到test之前的函數(shù)體
@Test
def test():
    print("----test---")
test()
showpy()#如果把這句話注釋,重新運(yùn)行程序,依然會(huì)看到"--初始化--"

運(yùn)行結(jié)果如下:

---初始化---
func name is test
---裝飾器中的功能---
----test---

到此這篇關(guān)于python必學(xué)知識(shí)之裝飾器詳解的文章就介紹到這了,更多相關(guān)python裝飾器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python爬蟲(chóng)框架scrapy實(shí)現(xiàn)downloader_middleware設(shè)置proxy代理功能示例

    Python爬蟲(chóng)框架scrapy實(shí)現(xiàn)downloader_middleware設(shè)置proxy代理功能示例

    這篇文章主要介紹了Python爬蟲(chóng)框架scrapy實(shí)現(xiàn)downloader_middleware設(shè)置proxy代理功能,結(jié)合實(shí)例形式分析了scrapy框架proxy代理設(shè)置技巧與相關(guān)問(wèn)題注意事項(xiàng),需要的朋友可以參考下
    2018-08-08
  • 如何使用Python的Requests包實(shí)現(xiàn)模擬登陸

    如何使用Python的Requests包實(shí)現(xiàn)模擬登陸

    這篇文章主要為大家詳細(xì)介紹了使用Python的Requests包模擬登陸,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • TensorFlow2.0使用keras訓(xùn)練模型的實(shí)現(xiàn)

    TensorFlow2.0使用keras訓(xùn)練模型的實(shí)現(xiàn)

    這篇文章主要介紹了TensorFlow2.0使用keras訓(xùn)練模型的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-02-02
  • python解析中國(guó)天氣網(wǎng)的天氣數(shù)據(jù)

    python解析中國(guó)天氣網(wǎng)的天氣數(shù)據(jù)

    最近學(xué)習(xí)python 感覺(jué)這門腳本語(yǔ)言十分靈活 而且功能十分強(qiáng)大 尤其是他re庫(kù)用于正則匹配十分強(qiáng)大,寫(xiě)了個(gè)例子解析中國(guó)天氣網(wǎng)
    2014-03-03
  • 深度Q網(wǎng)絡(luò)DQN(Deep Q-Network)強(qiáng)化學(xué)習(xí)的原理與實(shí)戰(zhàn)

    深度Q網(wǎng)絡(luò)DQN(Deep Q-Network)強(qiáng)化學(xué)習(xí)的原理與實(shí)戰(zhàn)

    深度Q學(xué)習(xí)將深度神經(jīng)網(wǎng)絡(luò)與強(qiáng)化學(xué)習(xí)相結(jié)合,解決了傳統(tǒng)Q學(xué)習(xí)在高維狀態(tài)空間下的局限性,通過(guò)經(jīng)驗(yàn)回放和目標(biāo)網(wǎng)絡(luò)等技術(shù),DQN能夠在復(fù)雜環(huán)境中學(xué)習(xí)有效的策略,本文通過(guò)CartPole環(huán)境的完整實(shí)現(xiàn),展示了DQN的核心思想和實(shí)現(xiàn)細(xì)節(jié)
    2025-04-04
  • 使用go和python遞歸刪除.ds store文件的方法

    使用go和python遞歸刪除.ds store文件的方法

    使用python和go遞歸刪除.DS_Store文件,.DS_Store (英文全稱 Desktop Services Store)是一種由蘋(píng)果公司的Mac OS X操作系統(tǒng)所創(chuàng)造的隱藏文件,目的在于存貯文件夾的自定義屬性
    2014-01-01
  • 利用Python刪除電腦中重復(fù)文件的方法

    利用Python刪除電腦中重復(fù)文件的方法

    這篇文章主要介紹了利用Python刪除電腦中的重復(fù)文件,下文我們來(lái)分享解決電腦中文件重復(fù)的情況的一個(gè)方法,需要的朋友可以參考一下,希望對(duì)大家日常問(wèn)題解決有所幫助
    2022-05-05
  • 詳解如何使用opencv實(shí)現(xiàn)圖片相似度檢測(cè)

    詳解如何使用opencv實(shí)現(xiàn)圖片相似度檢測(cè)

    這篇文章主要為大家詳細(xì)介紹了如何使用opencv實(shí)現(xiàn)圖片相似度檢測(cè),文中的示例代碼講解詳細(xì),對(duì)于我們學(xué)習(xí)人工智能有一定的幫助,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2023-12-12
  • python超詳細(xì)實(shí)現(xiàn)完整學(xué)生成績(jī)管理系統(tǒng)

    python超詳細(xì)實(shí)現(xiàn)完整學(xué)生成績(jī)管理系統(tǒng)

    讀萬(wàn)卷書(shū)不如行萬(wàn)里路,只學(xué)書(shū)上的理論是遠(yuǎn)遠(yuǎn)不夠的,只有在實(shí)戰(zhàn)中才能獲得能力的提升,本篇文章手把手帶你用Java實(shí)現(xiàn)一個(gè)完整版學(xué)生成績(jī)管理系統(tǒng),大家可以在過(guò)程中查缺補(bǔ)漏,提升水平
    2022-03-03
  • pandas提取數(shù)據(jù)的6種方法匯總

    pandas提取數(shù)據(jù)的6種方法匯總

    這篇文章主要介紹了pandas提取數(shù)據(jù)的6種方法匯總,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08

最新評(píng)論