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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python的闭包及装饰器

發布時間:2025/4/16 python 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python的闭包及装饰器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

閉包:


閉包(Closure)是詞法閉包(Lexical Closure)的簡稱,是引用了自由變量的函數。這個被引用的自由變量將和這個函數一同存在,即使已經離開了創造它的環境也不例外。所以,有另一種說法認為閉包是由函數和與其相關的引用環境組合而成的實體

1、函數是一個對象

2、函數執行完成后內部變量回收

3、函數屬性

4、函數的返回值

實例一、

分別檢測分數科目總分為100、150兩種情況的成績

初級代碼如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #?-*-?coding:utf-8?-*- ###檢測分數總數為100分的及格情況 def?ck_100(val): ????passline?=?60 ????if?val?>=?passline: ????????print?"當前科目總分為100,你的成績為:?%d,成績通過?"?%val ????else: ????????print?"當前科目總分為100,你的成績為:?%d,成績不通過?"?%val ###檢測分數總數為150分的及格情況 def?ck_150(val): ????passline?=?90 ????if?val?>=?passline: ????????print?"當前科目總分為150,你的成績為:?%d,成績通過?"?%val ????else: ????????print?"當前科目總分為100,你的成績為:?%d,成績不通過"?%val #100總分科目 ck_100(90) ck_100(55) #150總分科目 ck_150(110) ck_150(88)

執行結果如下:

1 2 3 4 5 6 7 >>>?================================?RESTART?================================ >>>? 當前科目總分為100,你的成績為:?90,成績通過? 當前科目總分為100,你的成績為:?55,成績不通過? 當前科目總分為150,你的成績為:?110,成績通過? 當前科目總分為100,你的成績為:?88,成績不通過 >>>


使用閉包優化后的代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 #?-*-?coding:utf-8?-*- ###根據不同科目設置及格線 def?set_passline(passline): ###檢測傳入分數是否及格 ????def?cmp(val): ????????if?val?>=?passline: ????????????print?"及格線為:?%d,?您的分數為:?%d?,恭喜及格"?%(passline,val) ????????else: ????????????print?"及格線為:?%d,?您的分數為:?%d?,遺憾不及格"?%(passline,val) ????return?cmp #總分為100的科目 score_100?=?set_passline(60) score_100(89) score_100(55) #總分為150的科目 score_150?=?set_passline(90) score_150(99) score_150(88)


執行結果:

1 2 3 4 5 6 >>>?================================?RESTART?================================ >>>? 及格線為:?60,?您的分數為:?89?,恭喜及格 及格線為:?60,?您的分數為:?55?,遺憾不及格 及格線為:?90,?您的分數為:?99?,恭喜及格 及格線為:?90,?您的分數為:?88?,遺憾不及格


Tips:

可以看代碼量少了一半;

閉包就是我們內置函數對 enclosing 作用域??變量? 的使用


實例二、

1 2 3 4 5 6 7 8 9 10 11 #?-*-?coding:utf-8?-*- ###求成績總分 def?my_sum(*args): ????return?sum(args) ###求成績平均分 def?my_average(*args): ????return?sum(args)/len(args) print?my_sum(1,2,3,4,5) print?my_average(1,2,3,4,5)

執行結果:

1 2 3 4 5 >>>?================================?RESTART?================================ >>>? 15 3 >>>

發現上述代碼不夠健壯,如果你傳入字符串或空的列表就會報錯

1 print?my_sum(1,2,3,4,5,'6')
1 2 3 ????return?sum(args) TypeError:?unsupported?operand?type(s)?for?+:?'int'?and?'str' >>>

修改代碼,進行檢查傳入數據的類型及長度

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #?-*-?coding:utf-8?-*- ###求成績總分 def?my_sum(*args): ????if?len(args)?==?0: ????????return?0 ????for?val?in?args: ????????if?not?isinstance(val,int): ????????????print?"傳入參數有非整數性..." ????????????return?0 ????return?sum(args) ###求成績平均分 def?my_average(*args): ????if?len(args)?==?0: ????????return?0 ????for?val?in?args: ????????if?not?isinstance(val,int): ????????????print?"傳入參數有非整數性..." ????????????return?0 ????return?sum(args)/len(args) print?my_sum(1,2,3,4,5) print?my_average(1,2,3,4,5) print?my_sum(1,2,3,4,5,'6')

執行結果:

1 2 3 4 5 6 >>>?================================?RESTART?================================ >>>? 15 3 傳入參數有非整數性... 0

健壯性是可以了,不過發現其中有一部門代碼是重復的,但是執行的 函數 又是不同的,分別為 my_sum 、my_average


使用閉包優化后的代碼:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #?-*-?coding:utf-8?-*- ###求成績總分 def?my_sum(*args): ????return?sum(args) ###求成績平均分 def?my_average(*args): ????return?sum(args)/len(args) def?dec(func): ????def?in_dec(*args): ????????if?len(args)?==?0: ????????????print?"傳入參數列表為0" ????????????return?0 ????????for?val?in?args: ????????????if?not?isinstance(val,int): ????????????????print?"傳入非整數參數" ????????????????return?0 ????????return?func(*args) ????return?in_dec #重新定義my_sum my_sum?=?dec(my_sum) #此處調用dec,作用就是將?參數為函數的?func?變為?in_dec?函數的一個屬性?(?enclosing?屬性?),并且將?in_dec?函數本身返回,返回的函數還具有?in_dec?本身的功能屬性?(檢測參數的作用) #并且?my_sum?進行了重新定義,返回值為?傳入函數處理后的?返回值 print?my_sum(1,2,3,4,5) print?my_sum() print?my_sum(1,2,3,4,5,'6') #重新定義my_average my_average?=?dec(my_average) print?my_average(1,2,3,4,5) print?my_average() print?my_average(1,2,3,4,5,'6')

執行結果:

1 2 3 4 5 6 7 8 9 10 11 12 13 >>>?================================?RESTART?================================ >>>? 15 傳入參數列表為0 0 傳入非整數參數 0 3 傳入參數列表為0 0 傳入非整數參數 0 >>>

裝飾器:

1、用來裝飾函數

2、返回一個新的函數對象

3、被裝飾函數標識符指向返回的函數對象

4、語法糖: @deco

上述閉包的例子,in_dec 被 dec 所裝飾,那可以說裝飾器其實就是閉包的一個本質使用


為了演示 裝飾器 的功能,以上述代碼為例,進行 裝飾器 寫法

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #?-*-?coding:utf-8?-*- def?dec(func): ????print?"call?dec" ????def?in_dec(*args): ????????print?"call?in_dec" ????????if?len(args)?==?0: ????????????print?"傳入參數列表為0" ????????????return?0 ????????for?val?in?args: ????????????if?not?isinstance(val,int): ????????????????print?"傳入非整數參數" ????????????????return?0 ????????return?func(*args) ????return?in_dec???? @dec ###求成績總分 def?my_sum(*args): ????return?sum(args) ###求成績平均分 def?my_average(*args): ????return?sum(args)/len(args)

所以沒有顯示調用,但是執行以下:

1 2 3 4 >>>?================================?RESTART?================================ >>>? call?dec >>>

結果證明 調用 了 dec 函數,那應該是 裝飾器語法糖 @dec 時進行了調用,但是它返回了一個函數,那被誰接受了呢? 是被他裝飾的 my_sum 接受了。

為了證明,來調用下 my_sum

1 2 print?my_sum(1,2,3,4,5) print?my_sum(1,2,3,4,5,'6')

結果:

1 2 3 4 5 6 7 8 9 >>>?================================?RESTART?================================ >>>? call?dec??????#######?語法糖調用一次裝飾函數?dec call?in_dec 15 call?in_dec 傳入非整數參數 0 >>>

證明是對的;

@dec 相當于上述的?

1 my_sum?=?dec(my_sum)

也就可以認為 被重新賦值的 my_sum 相當于裝飾器 dec 的內部函數 in_dec

裝飾器 dec 的參數 func 相當于 被修飾的函數 my_sum

裝飾器 實例二、

1 2 3 4 5 6 7 8 9 10 11 12 13 14 #?-*-?coding:utf-8?-*- def?dec(func): ????print?"call?dec" ????def?in_dec(): ????????print?"call?in_dec" ????????func() @dec def?test_dec(): ????print?"call?test_dec" print?type(test_dec) test_dec()

執行結果:

1 2 3 4 5 6 7 8 9 10 >>>?================================?RESTART?================================ >>>? call?dec <type?'NoneType'> Traceback?(most?recent?call?last): ??File?"D:\xisuo\xx\q.py",?line?15,?in?<module> ????test_dec() TypeError:?'NoneType'?object?is?not?callable >>>

可以看到這里的 test_dec 是 NoneType類型,無法調用,那是因為我們在裝飾器函數沒有進行顯示的 return ,python 默認返回 None,

所以裝飾器函數必須顯示的進行 return in_func (這里為 return in_dec)


修改后 執行

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #?-*-?coding:utf-8?-*- def?dec(func): ????print?"call?dec" ????def?in_dec(): ????????print?"call?in_dec" ????????func() ????return?in_dec??????#結論:必須返回 @dec def?test_dec(): ????print?"call?test_dec" print?type(test_dec) test_dec()


1 2 3 4 5 6 7 >>>?================================?RESTART?================================ >>>? call?dec <type?'function'> call?in_dec call?test_dec >>>

上面提到了(紅字)函數間的關系(相當于對象引用關系),那賦值的被修飾函數的 參數 就必須三個函數都對應起來

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 #?-*-?coding:utf-8?-*- def?dec(func): ????print?"call?dec" ????def?in_dec(x,y):??????##參數要對應起來 ????????print?"call?in_dec" ????????func(x,y)???????##參數要對應起來 ????return?in_dec @dec def?test_dec(x,y):?????##參數要對應起來 ????print?"call?test_dec?",x?+?y print?type(test_dec) test_dec(3,5)

執行結果:

1 2 3 4 5 6 7 >>>?================================?RESTART?================================ >>>? call?dec <type?'function'> call?in_dec call?test_dec??8 >>>


本文轉自 西索oO 51CTO博客,原文鏈接:http://blog.51cto.com/lansgg/1884913

總結

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

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