日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

闭包与装饰器

發布時間:2023/12/2 编程问答 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 闭包与装饰器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
閉包與裝飾器

一、閉包

閉包是語法閉包的簡稱,是引用自由變量的函數。這個被引用的自由變量將與這個函數一同存在,即使已經離開創造它的環境也不例外。所以,閉包是由函數和與其相關的引用環境組合而成的實體。閉包是函數式編程的重要語法結構。Python也支持這一特性。

假設我們通過配置實現打招呼的函數實現閉包:

def GreetingConfig(prefix):def greeting(postfix):print(prefix,postfix)return greeting res = GreetingConfig('Good morning!') res('alex')

在以上程序中,GreetingConfig()函數嵌套greeting()函數,且greeting()函數作為返回值。greeting()函數訪問上一級函數的變量prefix。此時,GreetingConfig()函數就是閉包。

閉包的總結:

  • 閉包函數必須有嵌套函數;
  • 嵌套函數需要引用上一級函數的變量;
  • 閉包函數必須返回嵌套函數。

二、裝飾器

裝飾器本質上就是函數,功能是為其他函數添加附加功能。

通俗的來講,裝飾器就是等于高階函數+函數嵌套+閉包的綜合實現。

裝飾器有兩大原則:第一,不修改被修飾函數的源代碼;第二,不修改被修飾函數的調用方法。

我們通過實例一步步講解裝飾器的功能,首先我們實現一個簡單的延時函數,并在程序中調用它,即:

import time
def
test():time.sleep(3)print('test函數運行完畢') test()

執行以上程序的運行結果為:

test函數運行完畢

函數功能非常簡單:延時3秒鐘,延時后打印,然后在程序中調用該函數。

假設此時想添加一個新功能:計算出test()函數總共的運行時間,為了使源代碼保持不變,在這里我們就可以用裝飾器來實現,即:

import time
def
timmer(func): #func=testdef wrapper():start_time = time.time()func() #就是在運行test()stop_time = time.time()print('運行時間是%s'%(stop_time-start_time))return wrapper@timmer #相當于test=timmer(test) def test():time.sleep(3)print('test函數運行完畢')test()

執行以上程序的運行結果為:

test函數運行完畢 運行時間是3.000999927520752

在以上程序中,timmer()函數就是一個裝飾器,裝飾器完美地實現了它的兩大原則,既沒有修改源代碼,也沒用修改調用方法。其中@timmer中的@是Python裝飾器的語法糖。@timmer放在test()函數的定義處,相當于執行了語句:test=timmer(test),這就是調用方法為什么沒被修改的原因。

1.被裝飾的函數帶參數

在以上程序中,被裝飾的函數test()沒有參數,如果有參數,則裝飾器該如何構建呢?基于以上程序,修改為如下代碼,即:

import time def timmer(func): #func=testdef wrapper(*args,**kwargs): start_time = time.time()func(*args,**kwargs) #就是在運行test()stop_time = time.time()print('運行時間是%s'%(stop_time-start_time))return wrapper@timmer #test=timmer(test) def test(name,age):time.sleep(3)print('test函數運行完畢,名字是%s,年齡是%s'%(name,age)) test('alex',18)

執行以上程序的運行結果為:

test函數運行完畢,名字是alex,年齡是18 運行時間是3.000999927520752

可以看到,當被裝飾的函數test()有參數時,可將裝飾器的嵌套函數修改為被裝飾器函數的形式即可。

若想要使用共同的裝飾器來修飾多個不同的函數,則這些不同的函數參數形式不同,裝飾器可以通過可變參數(*args,**kwargs)的方式來實現嵌套函數。

2.帶參數的裝飾器

對于裝飾器本身帶參數的情況我們應該如何實現,基于前面的例子,為裝飾器添加一個bool變量,可以通過變量的真假判斷是否調用計時功能,即:

import time def ctime(flag = False):if flag:def timmer(func): #func=testdef wrapper(*args,**kwargs):start_time = time.time()func(*args,**kwargs) #就是在運行test()stop_time = time.time()print('運行時間是%s'%(stop_time-start_time))return wrapperelse:def timmer(func):return funcreturn timmer@ctime(flag = False) #test=timmer(test) def test(name,age):time.sleep(3)print('test函數運行完畢,名字是%s,年齡是%s'%(name,age)) test('alex',18)@ctime(flag = True) #test=timmer(test) def test1(name,age):time.sleep(3)print('test1函數運行完畢,名字是%s,年齡是%s'%(name,age)) test1('lisi',20)

執行以上程序的運行結果為:

test函數運行完畢,名字是alex,年齡是18 test1函數運行完畢,名字是lisi,年齡是20 運行時間是3.000999927520752

分析以上程序可以看出,將同一個裝飾器ctime用于兩個不同的函數:test()和test1()。另外,通過裝飾器的參數可以為裝飾過程添加判斷,@ctime(True)表示進行計時,@ctime(False)不會進行計時,程序運行結果也證明了這一點。

3.裝飾器調用順序

使用多個裝飾器修飾同個函數時,裝飾器的調用順序與語法糖@的聲明順序相反。

轉載于:https://www.cnblogs.com/lzc69/p/11196085.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的闭包与装饰器的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。