Python高級--閉包與裝飾器

Python高級--閉包與裝飾器

前言:在Python中,閉包是一種非常有用的功能!它通常與裝飾器一起搭配使用,可以在不改變被裝飾函數的功能的基礎上,完成更多的功能。如權限認證。

一、如何定義閉包

  1.閉包就是兩個嵌套的函數,外層函數返回內層函數的引用,而且外層函數必須攜帶參數!爲什麼外層函數必須要有參數呢?可以思考一下!

  基本格式如下:  

1 def outer_fun(func):
2     def inner_fun():
3         pass
4     return inner_fun

  2.與普通函數的區別:

   閉包的外層函數的變量可以在內存中保存着,有點像類;而普通函數一旦執行完,那麼就要回收內存。

  3.萬能閉包

def outer_func(func):
    def inner_func(*args, **kwargs):
        func(*args, **kwargs)
    return inner_func

 

  

二、裝飾器

  1.什麼是裝飾器:@閉包的外層函數名

  2.裝飾器的作用:不修改被裝飾函數的功能外,再通過閉包的方式添加額外的功能!

  3.基本結構:    

複製代碼
1 def outer_func(func):
2     def inner_func():
3         pass
4     return inner_func
5 
6 
7 @outer_func # test = outer_func(test)
8 def test():
9     pass
複製代碼

  重點:上述代碼的第七行和第八行是重點,看到這個語法糖要想到其本質: test = outer_func(test)

  4.結論:

    (1). 裝飾前的test函數和閉包外層函數的func是一樣的;

    (2). 裝飾後的test函數是閉包內層函數的引用,也就是說此時test指向了inner_func函數體;

    (3). 裝飾器一般不改變原先函數的行爲。

  5.裝飾器的一個小問題

    與其說是裝飾器的問題,不如說是閉包的問題!

    一個函數被裝飾之後,它的函數名會發生變化,變成了閉包的內層函數名。那該怎麼解決這個問題呢?

    使用funtools.wraps()這個裝飾器就可以完美解決這個問題了,因爲這個裝飾器會保留被裝飾函數的一些基本信息。

    

複製代碼
 1 import functools
 2 
 3 
 4 def outer_func(func):
 5     # 使用這個裝飾器,可以保留被裝飾函數的一些基本信息,如名稱不變
 6     @functools.wraps(func)
 7     def inner_func(*args, **kwargs):
 8         func(*args, **kwargs)
 9 
10     # inner_func.__name__ = func.__name__
11     return inner_func
12 
13 
14 @outer_func
15 def test(*args, **kwargs):
16     print('%s 正在運行。。。。' % test.__name__)
17 
18 
19 test()
複製代碼

 

 

三、裝飾器內存圖解

  1.一個裝飾器裝飾一個函數的內存圖解:

  

 

  2.兩個裝飾器裝飾一個函數的內存圖解

    

 四、裝飾器傳參數

  1.結構:由三層函數構成的,即用一個函數把閉包給封裝起來,這個函數必須帶有參數!

      最外層函數(set_args)返回閉包的外層函數的引用;

      閉包的外層函數(outer_fun)還是返回內層函數的引用。

    

複製代碼
1 def set_args(args):
2     def outer_fun(func):
3         def inner_fun(*args, **kwargs):
4             func(*args, **kwargs)
5         return inner_func
6     return outer_fun
複製代碼

 

  2.運行流程:    

複製代碼
1 @set_args('123')
2 def test():
3     print('test')
4 
5 test()
複製代碼

    (1).先執行@右邊的函數,即先執行set_args('123'),

    (2).執行完set_args()後返回outer_fun的引用,此時就是test = outer_fun(test)這個熟悉的語法了,

    (3).接下來就執行被裝飾的函數了。

發佈了14 篇原創文章 · 獲贊 17 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章