国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Python > 正文

12步入門Python中的decorator裝飾器使用方法

2019-11-25 16:42:50
字體:
來源:轉載
供稿:網友

裝飾器(decorator)是一種高級Python語法。裝飾器可以對一個函數、方法或者類進行加工。在Python中,我們有多種方法對函數和類進行加工,比如在Python閉包中,我們見到函數對象作為某一個函數的返回結果。相對于其它方式,裝飾器語法簡單,代碼可讀性高。因此,裝飾器在Python項目中有廣泛的應用。

裝飾器最早在Python 2.5中出現,它最初被用于加工函數和方法這樣的可調用對象(callable object,這樣的對象定義有call方法)。在Python 2.6以及之后的Python版本中,裝飾器被進一步用于加工類。

1. 函數
在python中,函數通過def關鍵字、函數名和可選的參數列表定義。通過return關鍵字返回值。我們舉例來說明如何定義和調用一個簡單的函數:

>>> def foo():...   return 1>>> foo()1

方法體(當然多行也是一樣的)是必須的,通過縮進來表示,在方法名的后面加上雙括號()就能夠調用函數

2. 作用域
在python中,函數會創建一個新的作用域。python開發者可能會說函數有自己的命名空間,差不多一個意思。這意味著在函數內部碰到一個變量的時候函數會優先在自己的命名空間里面去尋找。讓我們寫一個簡單的函數看一下 本地作用域 和 全局作用域有什么不同:

>>> a_string = "This is a global variable">>> def foo():...   print locals()>>> print globals(){..., 'a_string': 'This is a global variable'}>>> foo() # 2{}

內置的函數globals返回一個包含所有python解釋器知道的變量名稱的字典(為了干凈和洗的白白的,我省略了python自行創建的一些變量)。在#2我調用了函數 foo 把函數內部本地作用域里面的內容打印出來。我們能夠看到,函數foo有自己獨立的命名空間,雖然暫時命名空間里面什么都還沒有。

3. 變量解析規則
當然這并不是說我們在函數里面就不能訪問外面的全局變量。在python的作用域規則里面,創建變量一定會一定會在當前作用域里創建一個變量,但是訪問或者修改變量時會先在當前作用域查找變量,沒有找到匹配變量的話會依次向上在閉合的作用域里面進行查看找。所以如果我們修改函數foo的實現讓它打印全局的作用域里的變量也是可以的:

>>> a_string = "This is a global variable">>> def foo():...   print a_string # 1>>> foo()This is a global variable

在#1處,python解釋器會嘗試查找變量a_string,當然在函數的本地作用域里面是找不到的,所以接著會去上層的作用域里面去查找。
但是另一方面,假如我們在函數內部給全局變量賦值,結果卻和我們想的不一樣:

>>> a_string = "This is a global variable">>> def foo():...   a_string = "test" # 1...   print locals()>>> foo(){'a_string': 'test'}>>> a_string # 2'This is a global variable'

我們能夠看到,全局變量能夠被訪問到(如果是可變數據類型(像list,dict這些)甚至能夠被更改)但是賦值不行。在函數內部的#1處,我們實際上新創建了一個局部變量,隱藏全局作用域中的同名變量。我們可以通過打印出局部命名空間中的內容得出這個結論。我們也能看到在#2處打印出來的變量a_string的值并沒有改變。

4. 變量生存周期
值得注意的一個點是,變量不僅是生存在一個個的命名空間內,他們都有自己的生存周期,請看下面這個例子:

>>> def foo():...   x = 1>>> foo()>>> print x # 1Traceback (most recent call last): ...NameError: name 'x' is not defined

#1處發生的錯誤不僅僅是因為作用域規則導致的(盡管這是拋出了NameError的錯誤的原因)它還和python以及其它很多編程語言中函數調用實現的機制有關。在這個地方這個執行時間點并沒有什么有效的語法讓我們能夠獲取變量x的值,因為它這個時候壓根不存在!函數foo的命名空間隨著函數調用開始而開始,結束而銷毀。

5. 函數參數
python允許我們向函數傳遞參數,參數會變成本地變量存在于函數內部。

>>> def foo(x):...   print locals()>>> foo(1){'x': 1}

在Python里有很多的方式來定義和傳遞參數,完整版可以查看 python官方文檔。我們這里簡略的說明一下:函數的參數可以是必須的位置參數或者是可選的命名,默認參數。

>>> def foo(x, y=0): # 1...   return x - y>>> foo(3, 1) # 22>>> foo(3) # 33>>> foo() # 4Traceback (most recent call last): ...TypeError: foo() takes at least 1 argument (0 given)>>> foo(y=1, x=3) # 52

在#1處我們定義了函數foo,它有一個位置參數x和一個命名參數y。在#2處我們能夠通過常規的方式來調用函數,盡管有一個命名參數,但參數依然可以通過位置傳遞給函數。在調用函數的時候,對于命名參數y我們也可以完全不管就像#3處所示的一樣。如果命名參數沒有接收到任何值的話,python會自動使用聲明的默認值也就是0。需要注意的是我們不能省略第一個位置參數x, 否則的話就會像#5處所示發生錯誤。
目前還算簡潔清晰吧, 但是接下來可能會有點令人困惑。python支持函數調用時的命名參數(個人覺得應該是命名實參)。看看#5處的函數調用,我們傳遞的是兩個命名實參,這個時候因為有名稱標識,參數傳遞的順序也就不用在意了。
當然相反的情況也是正確的:函數的第二個形參是y,但是我們通過位置的方式傳遞值給它。在#2處的函數調用foo(3,1),我們把3傳遞給了第一個參數,把1傳遞給了第二個參數,盡管第二個參數是一個命名參數。
桑不起,感覺用了好大一段才說清楚這么一個簡單的概念:函數的參數可以有名稱和位置。這意味著在函數的定義和調用的時候會稍稍在理解上有點兒不同。我們可以給只定義了位置參數的函數傳遞命名參數(實參),反之亦然!如果覺得不夠可以查看官方文檔

6. 嵌套函數
Python允許創建嵌套函數。這意味著我們可以在函數里面定義函數而且現有的作用域和變量生存周期依舊適用。

>>> def outer():...   x = 1...   def inner():...     print x # 1...   inner() # 2...>>> outer()1

這個例子有一點兒復雜,但是看起來也還行。想一想在#1發生了什么:python解釋器需找一個叫x的本地變量,查找失敗之后會繼續在上層的作用域里面尋找,這個上層的作用域定義在另外一個函數里面。對函數outer來說,變量x是一個本地變量,但是如先前提到的一樣,函數inner可以訪問封閉的作用域(至少可以讀和修改)。在#2處,我們調用函數inner,非常重要的一點是,inner也僅僅是一個遵循python變量解析規則的變量名,python解釋器會優先在outer的作用域里面對變量名inner查找匹配的變量.

7. 函數是python世界里的一級類對象
顯而易見,在python里函數和其他東西一樣都是對象。(此處應該大聲歌唱)啊!包含變量的函數,你也并不是那么特殊!

>>> issubclass(int, object) # all objects in Python inherit from a common baseclassTrue>>> def foo():...   pass>>> foo.__class__ # 1<type 'function'>>>> issubclass(foo.__class__, object)True

你也許從沒有想過,你定義的函數居然會有屬性。沒辦法,函數在python里面就是對象,和其他的東西一樣,也許這樣描述會太學院派太官方了點:在python里,函數只是一些普通的值而已和其他的值一毛一樣。這就是說你

主站蜘蛛池模板: 金乡县| 石台县| 山西省| 临沧市| 青田县| 宜宾县| 陇南市| 安塞县| 内丘县| 泽普县| 南充市| 平原县| 甘南县| 镇安县| 无棣县| 普兰县| 敦化市| 镇沅| 曲靖市| 南阳市| 旬阳县| 达孜县| 桂阳县| 屏东县| 襄垣县| 武定县| 广南县| 英吉沙县| 辉县市| 盐池县| 江达县| 象山县| 平顺县| 永城市| 正定县| 太原市| 洛浦县| 措美县| 东阿县| 鹰潭市| 铁力市|