Python装饰器详细介绍-Python教程

资源魔 43 0
装璜器实质上是一个Python函数,它能够让其余函数正在没有需求做任何代码变化的条件下添加额定性能,装璜器的前往值也是一个函数工具.

常常用于有切面需要的场景,比方:拔出日记、功能测试、事务解决、缓存、权限校验等场景。装璜器是处理这种成绩的绝佳设计,有了装璜器,咱们就能够抽离出年夜量与函数性能自身有关的相通代码并持续重用。

先来看一个简略例子:

def now():
    print('2017_7_29')

如今有一个新的需要,心愿能够记载下函数的执行日记,于是正在代码中增加日记代码:

def now():
    print('2017_7_29')
    logging.warn("running")

假定有相似的多个需要,怎样做?再写一个logging正在now函数里?这样就造成年夜量相通的代码,为了缩小反复写代码,咱们能够这样做,从新界说一个函数:专门解决日记 ,日记解决完之后再执行真实的营业代码.

def use_logging(func):     
    logging.warn("%s is running" % func.__name__)     
    func()  
def now():     
    print('2017_7_29')    
use_logging(now)

正在完成,逻辑上没有难, 然而这样的话,咱们每一次都要将一个函数作为参数通报给日记函数。并且这类形式曾经毁坏了原本的代码逻辑构造,以前执行营业逻辑时,执交运行now(),然而如今不能不改为use_logging(now)。

那末有无更好的形式的呢?当然有,谜底就是装璜器。

起首要明确函数也是一个工具,并且函数工具能够被赋值给变量,以是,经过变量也能挪用该函数。例如:

(=

简略装璜器

实质上,decorator就是一个前往函数的高阶函数。以是,咱们要界说一个能打印日记的decorator,能够界说以下:

def log(func):
    def wrapper(*args,**kw):
        print('call %s():'%func.__name__)
        return func(*args,**kw)
    return wrapper
# 因为log()是一个decorator,前往一个函数,以是,原来的now()函数依然存正在,
# 只是如今同名的now变量指向了新的函数,于是挪用now()将执行新函数,即正在log()函数中前往的wrapper()函数。
# wrapper()函数的参数界说是(*args, **kw),因而,wrapper()函数能够承受恣意参数的挪用。
# 正在wrapper()函数内,起首打印日记,再紧接着挪用原始函数。

下面的log,由于它是一个decorator,以是承受一个函数作为参数,并前往一个函数.如今执行:

now = log(now)
now()
输入后果:
call now():
2017_7_28

函数log就是装璜器,它把执行真正营业办法的func包裹正在函数外面,看起来像now被log装璜了。正在这个例子中,函数进入时 ,被称为一个横切面(Aspect),这类编程形式被称为面向切面的编程(Aspect-Oriented Progra妹妹ing)。

应用语法糖:

@logdef now():
    print('2017_7_28')

@符号是装璜器的语法糖,正在界说函数的时分应用,防止再一次赋值操作

这样咱们就能够省去now = log(now)这一句了,间接挪用now()便可失去想要的后果。假如咱们有其余的相似函数,咱们能够持续挪用装璜器来润饰函数,而不必反复修正函数或许添加新的封装。这样,咱们就进步了顺序的可反复行使性,并添加了顺序的可读性。

装璜器正在Python应用如斯不便都要归因于Python的函数能像一般的工具同样能作为参数通报给其余函数,能够被赋值给其余变量,能够作为前往值,能够被界说正在另一个函数内。

带参数的装璜器:

假如decorator自身需求传入参数,那就需求编写一个前往decorator的高阶函数,写进去会复杂一点。比方,要自界说log的文本: 

def log(text):
    def decorator(func):
            def wrapper(*args,**kw):
                        print('%s %s()'%(text,func.__name__))
                        return func(*args,**kw)        
            return wrapper    
     return decorator

这个3层嵌套的decorator用法以下:

@log(()
now()

等价于

now = log('goal')(now)
# 起首执行log('execute'),前往的是decorator函数,再挪用前往的函数,参数是now函数,前往值终极是wrapper函数
now()

由于咱们讲了函数也是工具,它有__name__等属性,但你去看通过decorator装璜之后的函数,它们的__name__曾经从原来的'now'变为了'wrapper'

print(now.__name__)# wrapper

由于前往的阿谁wrapper()函数名字就是'wrapper',以是,需求把原始函数的__name__等属性复制到wrapper()函数中,不然,有些依赖函数署名的代码执行就会犯错。

没有需求编写wrapper.__name__ = func.__name__这样的代码,Python内置的functools.wraps就是干这个事的,以是,一个完好的decorator的写法以下:

import functools

def log(func):
    @functools.wraps(func)
    def wrapper(*args, **kw):
        print('call %s():' % func.__name__)
        return func(*args, **kw)
    return wrapper
import functools

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

类装璜器:

再来看看类装璜器,相比函数装璜器,类装璜用具有灵敏度年夜、高内聚、封装性等优点。应用类装璜器还能够依托类外部的__call__办法,当应用 @ 方式将装璜器附加到函数上时,就会挪用此办法

import time

class Foo(object):     
    def __init__(self, func):     
        self._func = func  
    
    def __call__(self):     
        print ('class decorator runing')     
        self._func()     
        print ('class decorator ending')  

@Foo 
def now():     
    print (time.strftime('%Y-%m-%d',time.localtime(time.time())))  
    
now()

总结:

归纳综合的讲,装璜器的作用就是为曾经存正在的工具增加额定的性能。  

同时正在面向工具(OOP)的设计模式中,decorator被称为装璜模式。OOP的装璜模式需求经过承继以及组合来完成,而Python除了了能支持OOP的decorator外,间接从语法条理支持decorator。Python的decorator能够用函数完成,也能够用类完成。

更多相干常识请存眷python视频教程栏目

以上就是Python装璜器具体引见的具体内容,更多请存眷资源魔其它相干文章!

标签: Python python教程 python编程 python使用问题 装饰器

抱歉,评论功能暂时关闭!