第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定

python裝飾器的使用

標(biāo)簽:
Python

1. 装饰者模式

装饰者模式是常用的软件设计模式之一。通过此设计模式,我们能够在不修改任何底层代码情况下,给已有对象赋予新的职责。python中可以用装饰器简单地实现装饰者模式。

1.1 将函数作为参数传递

C/C++中,函数指针可以将函数作为参数传递给另一函数。而在python中,函数也是对象的一种,函数可以被引用,也可直接作为参数传入函数,以及作为容器对象的元素。python中可以采用如下方法实现装饰者模式:

#!/usr/bin/env python3.6# -*- coding: utf-8 -*-def add(x, y):
    result = x+y    return resultdef log(func):
    def wrapper(*args, **kwargs):
        result = func(*args)
        print(func.__name__,'has been called\n')        return result    return wrapperif __name__ == '__main__':
    print(log(add)(1,2))

上述代码中,log函数以需要被装饰的函数作为参数,并返回函数对象。被返回的函数的参数为可变参数*args**kwargs*args参数会被封装成tuple**kwargs参数则会被封装成字典对象),以适应不同函数的不同参数,保证通用性。

1.2 装饰器

上面的实现方法有些繁杂,所有调用被装饰的函数之处的代码,都要进行相应修改,自然不符合python简洁易读的特性。因此python中给出相应语法糖来增加可读性和易用性,那便是“装饰器”。

#!/usr/bin/env python3.6# -*- coding: utf-8 -*-from functools import wrapsdef log(func):
    #@wraps(func)
    def wrapper(*args, **kwargs):
        result = func(*args)
        print(func.__name__,'has been called')        return result    return wrapper#等价于add = log(add)@logdef add(x, y):
    result = x+y    return resultif __name__ == '__main__':
    print(add(1,2))
    print(add.__name__)

运行情况如下

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

但上述方法亦有缺陷,原函数add的元数据(比如名字、文档字符串、注解和参数签名)会丢失。为避免缺陷,任何时候你定义装饰器的时候,都应该使用functools库中的@wraps装饰器来注解底层包装函数(代码中注释部分)。@wraps有一个重要特征是它能让你通过属性 __wrapped__ 直接访问被包装函数。
改进后运行情况

>>print(add(1,2))
add has been called3>>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 functoolsimport timedef metric(func):    @functools.wraps(func)
    def wrapper(*args,**kv):
        print('Decorator1')
        f = func(*args,**kv)        return f    return wrapperdef logging(func):    @functools.wraps(func)
    def wrapper(*args,**kv):
        print('Decorator2')
        f = func(*args,**kv)        return f    return wrapper@metric@loggingdef 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 wrapsdef 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)



作者:lethe_zh
链接:https://www.jianshu.com/p/d307e8ac9e2a


點(diǎn)擊查看更多內(nèi)容
TA 點(diǎn)贊

若覺(jué)得本文不錯(cuò),就分享一下吧!

評(píng)論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評(píng)論
  • 收藏
  • 共同學(xué)習(xí),寫(xiě)下你的評(píng)論
感謝您的支持,我會(huì)繼續(xù)努力的~
掃碼打賞,你說(shuō)多少就多少
贊賞金額會(huì)直接到老師賬戶(hù)
支付方式
打開(kāi)微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊(cè)有機(jī)會(huì)得

100積分直接送

付費(fèi)專(zhuān)欄免費(fèi)學(xué)

大額優(yōu)惠券免費(fèi)領(lǐng)

立即參與 放棄機(jī)會(huì)
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)

舉報(bào)

0/150
提交
取消