Python装饰器
来源:互联网 发布:中囯邮政网络培训学院 编辑:程序博客网 时间:2024/06/06 06:56
由于函数也是一个对象,而且函数对象可以被赋值给变量,所以通过该变量也能调用该函数。
def now(): print('hahah')f=nowf()
hahah
函数对象有一个_ _ name _ _属性,可以拿到该函数的名字
print f.__name__print now.__name__
nownow
现在假设我们要增强now函数的功能,比如,在打印之前自动打印日志,但又不希望改动now()函数定义,这种在代码运行期动态增加功能的方式,称之为装饰器(‘Decorator’)。
本质上,装饰器就是一个返回函数的高阶函数。所以,我们要定义一个能打印日志的decorator,可以定义如下:
def log(func): def wrapper(*args,**kw): print('call %s():'%func.__name__) func(*args,**kw) return wrapper@logdef now(): print "2017-4-15"now()
log是一个装饰器,所以可以接受一个函数为参数,并返回一个参数。
call now():2017-4-15
把@log放到now函数定义的前面相当于执行科语句:
now=log(now)
由于log是一个装饰器返回一个函数,所以原来的函数依然存在,只是现在同名的now变量指向了新的函数,于是调用now()将执行新函数,即在log()中返回wrapper()函数。
wrapper的参数定义为*args,**kw意味着可以接任何参数。在wrapper内先打印日志,在执行now()函数。
如果decorator本身需要传递参数,那就需要编写一个返回decorator的高阶函数。
def log(text): def decorator(func): def wrapper(*args,**kw): print '%s %s():'%(text,func.__name__) func(*args,**kw) return wrapper return decorator@log('execute')def now(): print "2017-4-15"now()
execute now():2017-4-15
三层嵌套相当于
now=log('execute')(now)
首先执行log(‘execute’)返回decorator函数,在调用decorator函数参数为now函数返回值为wrapper函数。
以上两种定义都没错,但换差最后一步。每个函数对象都有_ _ name _ _属性,但是:
print now.__name__
wrapper
因为返回的wrapper()的名字就是wrapper,需要把now的函数属性复制到wra函数中,不要使用:
wrapper.__name__=naw.__name__
python内置的functool.wraps干的就是这个,所以完整的decorator是
import functoolsdef log(func): @functools.wraps(func) def wrapper(*args,**kw): print('call %s():'%func.__name__) func(*args,**kw) return wrapper@logdef now(): print "2017-4-15"now() now.__name__
或
import functoolsdef log(text): def decorator(func): @functools.wraps(func) def wrapper(*args,**kw): print '%s %s():'%(text,func.__name__) func(*args,**kw) return wrapper return decorator@log('execute')def now(): print "2017-4-15"print now.__name__
小结
在面对象(OOP)的设计模式中,decorator也称为装饰模式,OOP的装饰模式通过继承和组合实现,而python除了能支持OOP的装饰模式,直接从语法上支持decorator。python的decorator可以用函数实现也可以用类实现。
import functoolsdef log(obj): if isinstance(obj,str): text=obj def decorator(func): @functools.wraps(func) def wrapper(*args,**kw): print '%s %s():'%(text,func.__name__) func(*args,**kw) return wrapper return decorator else: func=obj @functools.wraps(func) def wrapper(*args,**kw): print '%s():'%func.__name__ func(*args,**kw) return wrapper@log('execute')def now(): print "2017-4-15"now()@logdef now(): print "2017-4-15"now()
execute now():2017-4-15now():2017-4-15
- python装饰器装饰类
- [python]python装饰器
- Python装饰器学习
- Python装饰器
- python 装饰器
- Python装饰器
- python 装饰器 应用
- python 装饰器2
- Python装饰器学习
- python装饰器
- python装饰器
- python 装饰器入门
- python装饰器
- python装饰器
- python 装饰器'@'
- python装饰器
- Python装饰器详解
- python 装饰器
- 在Android中运用RxJava
- 京东高并发抢购系统的核心逻辑与架构实现
- 06-Java面向对象
- Linux系统安装JDK
- Android Studio中FindBugs的使用
- Python装饰器
- codevs 1281 Xn数列 快速幂+快速加防溢出
- ZOJ
- Swift 字典 Dictionary基本用法
- 4.dialog 工具
- 【剑指offer之求1+2+...+n】九度OJ-1506-求1+2+3+...+n
- 笔试
- hdu1176免费馅饼 dp
- List Map Set的比较