面向切面编程 AOP 和装饰器
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲, 装饰器的作用就是为已经存在的对象添加额外的功能。
#类似对函数功能上做了一些扩展
#对现有函数进行装饰
import time
def add():
print('调用时间:%s'%time.strftime('%Y-%m-%d %H:%M:%S'))
print('add')
add()
#也可以不用那个time函数
#可以用装饰器
#装饰器函数#就是闭包
def log(func):#把函数当成变量放进去
def wrapper():
#__name__是调用函数名
print('调用%s时间:%s'%(func.__name__,time.strftime('%Y-%m-%d %H:%M:%S')))
func()
return wrapper
add_warp = log(add)#放了add函数进去这个参数里
add_warp()#这样不管想打印什么函数的时间都可以
add = log(add)#z这样就不用重新起一个名字直接让add接收log里的函数
#但此add与里面的add不一样了,只是名字一样,表面看一样,实际不是一个东西
#就是你已经写了两天的程序但是不去乱改程序,那就用闭包来做
@log#yong用它将装饰器作用到指定函数,比前面的用法看起来简洁
#这个装饰器可以放多个是从下执行的
def sub():
print('sub')
sub()#z这样是对原来程序改变最小的了
###这种格式你要记住
import time
import functools
def log(func):
#可以传任意参数
@functools.wraps(func)
def wrapper(*args, **kw):
#其他都是固定的一般就是print这里要改
print('调用%s时间:%s'%(func.__name__,time.strftime('%Y-%m-%d %H:%M:%S')))
return func(*args, **kw)
return wrapper
@log
def add(a, b):
return a + b
v=add(10, 11)
print(v)
#y有了@functools.wraps(func)之后名字就是add。用了functools装饰器
aaa = log(add)#记住这里不要带()除非用了@log
print(aaa.__name__)
print(add.__name__)#因为装饰过了所以这里add的名字就是装饰器内部的名字
def sub(a, b):
return a - b
print(sub.__name__)#z这里没有装饰所以就还是sub
#我们可能经常用系统的装饰器