91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

python裝飾器如何使用

發布時間:2020-09-24 11:25:37 來源:億速云 閱讀:105 作者:Leah 欄目:編程語言

這篇文章將為大家詳細講解有關python裝飾器如何使用,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

裝飾者模式是常用的軟件設計模式之一。通過此設計模式,我們能夠在不修改任何底層代碼情況下,給已有對象賦予新的職責。python中可以用裝飾器簡單地實現裝飾者模式。

1.1 將函數作為參數傳遞

在C/C++中,函數指針可以將函數作為參數傳遞給另一函數。而在python中,函數也是對象的一種,函數可以被引用,也可直接作為參數傳入函數,以及作為容器對象的元素。python中可以采用如下方法實現裝飾者模式:

#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-

def add(x, y):
    result = x+y
    return result

def log(func):
    def wrapper(*args, **kwargs):
        result = func(*args)
        print(func.__name__,'has been called\n')
        return result
    return wrapper

if __name__ == '__main__':
    print(log(add)(1,2))

上述代碼中,log函數以需要被裝飾的函數作為參數,并返回函數對象。被返回的函數的參數為可變參數*args與**kwargs(*args參數會被封裝成tuple,**kwargs參數則會被封裝成字典對象),以適應不同函數的不同參數,保證通用性。

1.2 裝飾器

上面的實現方法有些繁雜,所有調用被裝飾的函數之處的代碼,都要進行相應修改,自然不符合python簡潔易讀的特性。因此python中給出相應語法糖來增加可讀性和易用性,那便是“裝飾器”。

from functools import wraps

def log(func):
    #@wraps(func)
    def wrapper(*args, **kwargs):
        result = func(*args)
        print(func.__name__,'has been called')
        return result
    return wrapper

#等價于add = log(add)
@log
def add(x, y):
    result = x+y
    return result

if __name__ == '__main__':
    print(add(1,2))
    print(add.__name__)

運行情況如下:

>>print(add(1,2))
add has been called
3
>>print(add.__name__)
wrapper

但上述方法亦有缺陷,原函數add的元數據(比如名字、文檔字符串、注解和參數簽名)會丟失。為避免缺陷,任何時候你定義裝飾器的時候,都應該使用functools庫中的@wraps裝飾器來注解底層包裝函數(代碼中注釋部分)。@wraps有一個重要特征是它能讓你通過屬性 __wrapped__ 直接訪問被包裝函數。

改進后運行情況:

>>print(add(1,2))
add has been called
3
>>print(add.__name__)
add

1.3 解除裝飾器

當裝飾器已經作用于某函數,而你想撤銷它,那么可以訪問 __wrapped__屬性來訪問原始函數

orig_add = add.__wrapped__
orig_add(1,2)

但若使用了多個裝飾器, __wrapped__屬性會變得不可控,應盡量避免使用。
若有如下代碼:

#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-

import functools
import time

def metric(func):
    @functools.wraps(func)
    def wrapper(*args,**kv):
        print('Decorator1')
        f = func(*args,**kv)
        return f
    return wrapper

def logging(func):
    @functools.wraps(func)
    def wrapper(*args,**kv):
        print('Decorator2')
        f = func(*args,**kv)
        return f
    return wrapper

@metric
@logging
def normalize(name):
    sName = name[0:1].upper() + name[1:].lower()
    print(sName)

if __name__ == '__main__':
    normalize('heLlO')
    normalize.__wrapper__('')

運行情況如下:

>>normalize('helLo')
Decorator1
Decorator2
Hello
>>normalize.__wrapped__('world')
Decorator2
World

1.4 定義帶參數的裝飾器

from functools import wraps

def log(text):
    def decorator(func):
        @wraps(func) 
        def wrappering(*args,**kv):
            print('%s %s():'%(text,func.__name__))
            return func(*args,**kv)
        return wrappering
    return decorator

@log('run')
def normalize(name):
    sName = name[0:1].upper() + name[1:].lower()
    print(sName)

裝飾器函數可以帶參數,最外層的函數會將參數傳給內層的裝飾器函數,即wrappering函數是可以使用log的傳入參數的。

裝飾器處理過程與下面是等價的:

normalize = log('run')(normalize)

關于python裝飾器如何使用就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

泾源县| 从化市| 屯昌县| 安乡县| 阿拉尔市| 库车县| 留坝县| 贺兰县| 天柱县| 密云县| 蓬溪县| 晋江市| 包头市| 浦县| 古交市| 永福县| 格尔木市| 洪湖市| 麻栗坡县| 禹城市| 南充市| 舒兰市| 荔浦县| 岗巴县| 买车| 昌吉市| 裕民县| 黎城县| 辛集市| 海城市| 甘南县| 齐河县| 黄骅市| 渭南市| 会同县| 桐庐县| 吉林省| 万宁市| 稷山县| 钟山县| 岫岩|