成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

裝飾器為什么難以理解?

開發 開發工具
無論項目中還是面試都離不開裝飾器話題,裝飾器的強大在于它能夠在不修改原有業務邏輯的情況下對代碼進行擴展,但為什么初學者對裝飾器的理解如此困難,我認為本質上是對Python函數理解不到位,因為裝飾器本質上還是函數。

[[196195]]

無論項目中還是面試都離不開裝飾器話題,裝飾器的強大在于它能夠在不修改原有業務邏輯的情況下對代碼進行擴展,權限校驗、用戶認證、日志記錄、性能測試、事務處理、緩存等都是裝飾器的***應用場景,它能夠***程度地對代碼進行復用。

但為什么初學者對裝飾器的理解如此困難,我認為本質上是對Python函數理解不到位,因為裝飾器本質上還是函數。

函數的定義

理解裝飾器前,需要明白函數的工作原理,我們先從一個最簡單函數定義開始:

  1. def foo(num): 
  2.     return num + 1 

上面定義了一個函數,名字叫foo,也可以把 foo 可理解為變量名,該變量指向一個函數對象

調用函數只需要給函數名加上括號并傳遞必要的參數(如果函數定義的時候有參數的話)

  1. value = foo(3) 
  2. print(value) # 4 

變量名 foo 現在指向 函數對象,但它也可以指向另外一個函數。

  1. def bar(): 
  2.     print("bar") 
  3. foo = bar 
  4. foo() # bar 

函數作為返回值

 

在Python中,一切皆為對象,函數也不例外,它可以像整數一樣作為其它函數的返回值,例如:

  1. def foo(): 
  2.     return 1 
  3.  
  4. def bar(): 
  5.     return foo 
  6.  
  7. print(bar()) # <function foo at 0x10a2f4140> 
  8.  
  9. print(bar()()) # 1  
  10. # 等價于 
  11. print(foo()) # 1 

bar() 的返回值是一個函數對象,所以我們可以繼續對返回值進行調用,調用bar()()等價于調用 foo(),因為 變量 foo 指向的對象與 bar() 的返回值是同一個對象。

函數作為參數

函數還可以像整數一樣作為函數的參數,例如:

  1. def foo(num): 
  2.     return num + 1 
  3.  
  4. def bar(fun): 
  5.     return fun(3) 
  6.  
  7. value = bar(foo) 
  8. print(value)  # 4 

函數 bar 接收一個參數,這個參數是一個可被調用的函數對象,把函數 foo 傳遞到 bar 中去時,foo 和 fun 兩個變量名指向的都是同一個函數對象 。所以調用 fun(3) 相當于調用 foo(3)。

函數嵌套

函數不僅可以作為參數和返回值,函數還可以定義在另一個函數中,作為嵌套函數存在,例如:

  1. def outer(): 
  2.     x = 1 
  3.     def inner(): 
  4.         print(x) 
  5.     inner() 
  6.  
  7. outer() # 1 

inner做為嵌套函數,它可以訪問外部函數的變量,調用 outer 函數時,發生了3件事:

  • 給 變量 x 賦值為1
  • 定義嵌套函數 inner,此時并不會執行 inner 中的代碼,因為該函數還沒被調用,直到第3步
  • 調用 inner 函數,執行 inner 中的代碼邏輯。

閉包

再來看一個例子:

  1. def outer(x): 
  2.     def inner(): 
  3.         print(x) 
  4.  
  5.     return inner 
  6. closure = outer(1) 
  7. closure() # 1 

同樣是嵌套函數,只是稍改動一下,把局部變量 x 作為參數了傳遞進來,嵌套函數不再直接在函數里被調用,而是作為返回值返回,這里的 closure就是一個閉包,本質上它還是函數,閉包是引用了自由變量(x)的函數(inner)。

裝飾器

繼續往下看:

  1. def foo(): 
  2.     print("foo") 

上面這個函數這可能是史上最簡單的業務代碼了,雖然沒什么用,但是能說明問題就行。現在,有一個新的需求,需要在執行該函數時加上日志:

  1. def foo(): 
  2.     print("記錄日志開始") 
  3.     print("foo") 
  4.     print("記錄日志結束") 

功能實現,唯一的問題就是它需要侵入到原來的代碼里面,把日志邏輯加上去,如果還有好幾十個這樣的函數要加日志,也必須這樣做,顯然,這樣的代碼一點都不Pythonic。那么有沒有可能在不修改業務代碼的提前下,實現日志功能呢?答案就是裝飾器。

  1. def outer(func): 
  2.     def inner(): 
  3.         print("記錄日志開始") 
  4.         func() # 業務函數 
  5.         print("記錄日志結束") 
  6.     return inner 
  7.  
  8. def foo(): 
  9.     print("foo") 
  10.  
  11. foo = outer(foo)  
  12. foo() 

我沒有修改 foo 函數里面的任何邏輯,只是給 foo 變量重新賦值了,指向了一個新的函數對象。***調用 foo(),不僅能打印日志,業務邏輯也執行完了。現在來分析一下它的執行流程。

這里的 outer 函數其實就是一個裝飾器,裝飾器是一個帶有函數作為參數并返回一個新函數的閉包,本質上裝飾器也是函數。outer 函數的返回值是 inner 函數,在 inner 函數中,除了執行日志操作,還有業務代碼,該函數重新賦值給 foo 變量后,調用 foo() 就相當于調用 inner()

foo 重新賦值前:

重新賦值后:

另外,Python為裝飾器提供了語法糖 @,它用在函數的定義處:

  1. @outer 
  2. def foo(): 
  3.     print("foo") 
  4.  
  5. foo() 

這樣就省去了手動給foo重新賦值的步驟。

到這里不知你對裝飾器理解了沒有?當然,裝飾器還可以更加復雜,比如可以接受參數的裝飾器,基于類的裝飾器等等。

【本文是51CTO專欄作者“劉志軍”的原創文章,作者微信公眾號:Python之禪(VTtalk)】

戳這里,看該作者更多好文

責任編輯:趙寧寧 來源: 51CTO專欄
相關推薦

2014-12-19 09:59:50

代碼

2021-04-05 14:47:05

裝飾器Python代碼

2023-08-13 19:45:12

DNS

2022-09-19 23:04:08

Python裝飾器語言

2021-02-14 13:38:17

Python開發函數

2018-12-28 14:43:40

物聯網智能IOT

2021-12-03 17:22:09

CC++編程語言

2020-05-12 09:01:30

IPv6IPv4網絡協議

2013-10-11 15:43:30

網絡管理網絡優化

2015-02-09 13:23:17

創業

2020-12-22 10:03:58

黑客勒索軟件網絡攻擊

2024-09-23 09:00:00

裝飾器函數代碼

2023-08-28 16:55:05

2017-03-13 09:50:46

Python裝飾器

2020-01-10 10:14:48

Redis數據庫架構

2023-02-07 07:47:52

Python裝飾器函數

2024-03-15 09:06:48

HTTPSCA私鑰

2010-02-01 17:50:32

Python裝飾器

2023-10-12 13:24:03

云原生容器

2021-09-27 13:50:13

Python裝飾器函數
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产精品久久久久久久久免费 | 亚洲精品区 | 久久久久国产视频 | 老司机久久 | 日本三级在线视频 | 伦理二区| 亚洲成色777777在线观看影院 | 久久亚洲精品国产精品紫薇 | www.伊人.com | 操久久| 国产精品免费一区二区三区四区 | 超碰97免费观看 | 久综合| 精品二区视频 | 影音先锋亚洲资源 | 六月成人网 | 久久精品com | 精品欧美乱码久久久久久1区2区 | 日本精品久久久久久久 | 国产精品地址 | 91久久久久久久久久久久久 | 国产精品亚洲一区二区三区在线观看 | 久久av一区 | 在线免费观看成人 | 日本成人二区 | 亚洲精品一区中文字幕乱码 | 国产精品久久久久一区二区三区 | 国产乱肥老妇国产一区二 | 青青久久av北条麻妃海外网 | 一级欧美 | 欧美成人a∨高清免费观看 欧美日韩中 | 天天躁日日躁xxxxaaaa | 久久久久免费精品国产小说色大师 | 久久久久久av | 日韩欧美在线免费 | av片在线免费看 | 视频一区二区中文字幕日韩 | 中文字幕乱码亚洲精品一区 | 精品一二三区在线观看 | 久久久久久黄 | 国产精品日本一区二区在线播放 |