装饰器是什么意思
一个大牛举的例子:
内裤可以用来遮羞,但是到了冬天它没法为我们防风御寒,聪明的人们发明了长裤,有了长裤后宝宝再也不冷了,装饰器就像我们这里说的长裤,在不影响内裤作用的前提下,给我们的身子提供了保暖的功效。
装饰器本质上是Python函数,可以为已存在的对象添加额外的功能,同时装饰器还可以抽离出与函数无关的重用代码。具体应用场景如:插入日志、性能测试、事务处理、缓存、权限校验等。
举个栗子
需要在某个原有功能上加一层验证
def a():
print 'a'
def b():
print 'a'
a b 方法很多地方调用,不想更改原有调用方式
即:
def a():
权限验证
print 'a'
def b():
权限验证
print 'a'
假如有很多的接口—-
用装饰器来实现:
def auth(func):
def inner():
# 验证1
return func()
return inner
@auth
def a():
print 'a'
@auth
def a():
print 'b'
带参数装饰器
执行方法带参数
def auth(func):
def inner(arg1,arg2):
# 验证1
return func(arg1,arg2)
return inner
@auth
def a(arg1,arg2):
print 'a'
@auth
def b(arg1,arg2):
print 'b'
装饰器带参数
def auth(info):
def decorator(func):
def inner(arg1,arg2):
# 验证1
print info
return func(arg1,arg2)
return inner
return decorator
@auth(info='a')
def a(arg1,arg2):
print 'a'
@auth(info='b')
def b(arg1,arg2):
print 'b'
类装饰器
再来看看类装饰器,相比函数装饰器,类装饰器具有灵活度大、高内聚、封装性等优点。使用类装饰器还可以依靠类内部的__call__方法,当使用 @ 形式将装饰器附加到函数上时,就会调用此方法。
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 bar():
print ('bar') bar()
装饰器执行顺序
@a
@b
@c
def f ():
等于
f = a(b(c(f)))
带来的问题(知乎刘志军大牛)
使用装饰器极大地复用了代码,但是他有一个缺点就是原函数的元信息不见了,比如函数的docstring、name、参数列表
这个问题就比较严重的,好在我们有functools.wraps,wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器函数中,这使得装饰器函数也有和原函数一样的元信息了。
from functools import wraps
def logged(func):
@wraps(func)
def with_logging(*args, **kwargs):
print func.__name__ + " was called"
return func(*args, **kwargs)
return with_logging
@logged
def f(x):
"""does some math"""
return x + x * x
print f.__name__ # prints 'f'
print f.__doc__ # prints 'does some math'