Python 基礎(chǔ)教程

Python 流程控制

Python 函數(shù)

Python 數(shù)據(jù)類型

Python 文件操作

Python 對(duì)象和類

Python 日期和時(shí)間

Python 高級(jí)知識(shí)

Python 參考手冊(cè)

Python 裝飾器

裝飾器接受一個(gè)函數(shù),添加一些功能并返回它。 在本文中,您將學(xué)習(xí)如何創(chuàng)建裝飾器以及為什么要使用它。

Python中的裝飾器是什么?

Python有一個(gè)有趣的功能,稱為裝飾器,可將功能添加到現(xiàn)有代碼中。

這也稱為元編程,因?yàn)槌绦虻囊徊糠衷噲D在編譯時(shí)修改程序的另一部分。

學(xué)習(xí)裝飾器的先決條件

為了了解裝飾器,我們必須首先了解Python的一些基本知識(shí)。

我們必須接受這樣一個(gè)事實(shí),即Python中的所有內(nèi)容都是對(duì)象。我們定義的名稱只是綁定到這些對(duì)象的標(biāo)識(shí)符。函數(shù)也不例外,它們也是對(duì)象(帶有屬性)??梢詫⒏鞣N不同的名稱綁定到同一功能對(duì)象。

這是一個(gè)實(shí)例。

def first(msg):
    print(msg)    

first("Hello")

second = first
second("Hello")

當(dāng)您運(yùn)行代碼時(shí),這兩個(gè)函數(shù)first和second給出相同的輸出。在此,名稱first和second指代相同的功能對(duì)象。

現(xiàn)在情況是不是感覺(jué)變復(fù)雜了點(diǎn),可以將函數(shù)作為參數(shù)傳遞給另一個(gè)函數(shù)。

如果您在Python中使用過(guò)map,filter和reduce之類的函數(shù),那么您已經(jīng)知道這一點(diǎn)。

這種以其他函數(shù)為參數(shù)的函數(shù)也稱為高階函數(shù)。這是這種函數(shù)的一個(gè)實(shí)例。

def inc(x):
    return x + 1

def dec(x):
    return x - 1

def operate(func, x):
    result = func(x)
    return result

我們調(diào)用函數(shù)如下。

>>> operate(inc,3)
4
>>> operate(dec,3)
2

此外,一個(gè)函數(shù)可以返回另一個(gè)函數(shù)。

def is_called():
    def is_returned():
        print("Hello")
    return is_returned

new = is_called()

#輸出 "Hello"
new()

在這里,is_returned()是一個(gè)嵌套函數(shù),每次我們調(diào)用is_drawn()時(shí),該函數(shù)都會(huì)定義并返回。

最后,我們必須了解Python中的閉包

回到裝飾器

函數(shù)和方法被稱為可調(diào)用的,因?yàn)樗鼈兛梢员徽{(diào)用。

實(shí)際上,任何實(shí)現(xiàn)特殊方法__call __()的對(duì)象都稱為可調(diào)用的。 因此,從最基本的意義上講,裝飾器是可調(diào)用的,可返回可調(diào)用的。

基本上,裝飾器接受一個(gè)函數(shù),添加一些功能并返回它。

def make_pretty(func):
    def inner():
        print("我被裝飾了")
        func()
    return inner

def ordinary():
    print("我是普通的函數(shù)")

在shell中運(yùn)行以下代碼時(shí),

>>> ordinary()
我是普通的函數(shù)

>>> # 我們來(lái)裝飾一下這個(gè)普通的函數(shù)
>>> pretty = make_pretty(ordinary)
>>> pretty()
我被裝飾了
我是普通的函數(shù)

在上面顯示的示例中,make_pretty()是一個(gè)裝飾器。在分配步驟中。

pretty = make_pretty(ordinary)

函數(shù)ordinary()被修飾,返回的函數(shù)被命名為pretty。

我們可以看到decorator函數(shù)在原來(lái)的函數(shù)中添加了一些新功能。這類似于包裝禮物。裝飾器充當(dāng)包裝器。被裝飾的物品(里面的禮物)的性質(zhì)不會(huì)改變。但是現(xiàn)在,它看起來(lái)很漂亮(自從裝飾之后)。

通常,我們裝飾一個(gè)函數(shù)并將其重新分配為

ordinary = make_pretty(ordinary).

這是一個(gè)常見(jiàn)的構(gòu)造,因此,Python具有簡(jiǎn)化此語(yǔ)法的語(yǔ)法。

我們可以將@符號(hào)與裝飾器函數(shù)的名稱一起使用,并將其放置在要裝飾的函數(shù)的定義上方。例如,

@make_pretty
def ordinary():
    print("我是普通的函數(shù)")

相當(dāng)于

def ordinary():
    print("我是普通的函數(shù)")
ordinary = make_pretty(ordinary)

這只是實(shí)現(xiàn)裝飾器的語(yǔ)法糖。

用參數(shù)裝飾函數(shù)

上面的裝飾器很簡(jiǎn)單,并且只適用于沒(méi)有任何參數(shù)的函數(shù)。如果我們的函數(shù)具有如下所示的參數(shù),該怎么辦?

def divide(a, b):
    return a/b

此函數(shù)有兩個(gè)參數(shù),ab。我們知道,如果我們將b傳遞為0 ,則會(huì)產(chǎn)生錯(cuò)誤。

>>> divide(2,5)
0.4
>>> divide(2,0)
Traceback (most recent call last):
...
ZeroDivisionError: division by zero

現(xiàn)在讓我們做一個(gè)裝飾器來(lái)檢查這種情況是否會(huì)導(dǎo)致錯(cuò)誤。

def smart_divide(func):
   def inner(a,b):
      print("我要做除法",a,"和",b)
      if b == 0:
         print("哎呀!不能除")
         return

      return func(a,b)
   return inner

@smart_divide
def divide(a,b):
    return a/b

如果出現(xiàn)錯(cuò)誤情況,此新實(shí)現(xiàn)將返回None。

>>> divide(2,5)
我要做除法 2 和 5
0.4

>>> divide(2,0)
我要做除法 2 和 0
哎呀!不能除

通過(guò)這種方式,我們可以裝飾帶有參數(shù)的函數(shù)。

敏銳的觀察者會(huì)注意到,inner()裝飾器內(nèi)部的嵌套函數(shù)的參數(shù)與其裝飾的函數(shù)的參數(shù)相同??紤]到這一點(diǎn),現(xiàn)在我們可以使通用裝飾器可以使用任意數(shù)量的參數(shù)。

在Python中,此魔術(shù)是通過(guò)完成的function(*args, **kwargs)。這樣,args是位置參數(shù)的元組,kwargs而是關(guān)鍵字參數(shù)的字典。這樣的裝飾器的一個(gè)實(shí)例是。

def works_for_all(func):
    def inner(*args, **kwargs):
        print("我可以裝飾任何函數(shù)")
        return func(*args, **kwargs)
    return inner

Python 鏈接裝飾器

可以在Python中鏈接多個(gè)裝飾器。

這就是說(shuō),一個(gè)函數(shù)可以用不同(或相同)的裝飾器多次裝飾。我們只需將裝飾器放置在所需函數(shù)之上。

def star(func):
    def inner(*args, **kwargs):
        print("*" * 30)
        func(*args, **kwargs)
        print("*" * 30)
    return inner

def percent(func):
    def inner(*args, **kwargs):
        print("%" * 30)
        func(*args, **kwargs)
        print("%" * 30)
    return inner

@star
@percent
def printer(msg):
    print(msg)
printer("Hello")

這將給出輸出。

******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Hello
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************

上面的語(yǔ)法,

@star
@percent
def printer(msg):
    print(msg)

相當(dāng)于

def printer(msg):
    print(msg)
printer = star(percent(printer))

鏈接裝飾器的順序很重要。如果我們按相反的順序,

@percent
@star
def printer(msg):
    print(msg)

執(zhí)行將發(fā)生在

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
******************************
Hello
******************************
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

                                                                                                                                                                                                   

丰满人妻一级特黄a大片,午夜无码免费福利一级,欧美亚洲精品在线,国产婷婷成人久久Av免费高清