一、装饰器
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。
装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
装饰器功能: 1. 自动执行装饰器函数 并且将被装饰函数当做参数对象本身,传递进去
2. 将装饰器函数的返回值,重新赋值给被装饰的函数
用伪代码就是如下表示:
# 装饰器是一个函数,而其参数为另外一个函数def my_shiny_new_decorator(a_function_to_decorate) : # 在内部定义了另外一个函数:一个封装器。 # 这个函数将原始函数进行封装,所以你可以在它之前或者之后执行一些代码 def the_wrapper_around_the_original_function() : # 放一些你希望在真正函数执行前的一些代码 print "Before the function runs" # 执行原始函数 a_function_to_decorate() # 放一些你希望在原始函数执行后的一些代码 print "After the function runs" #在此刻,"a_function_to_decrorate"还没有被执行,我们返回了创建的封装函数 #封装器包含了函数以及其前后执行的代码,其已经准备完毕 return the_wrapper_around_the_original_functiondef a_stand_alone_function() : print "I am a stand alone function, don't you dare modify me"# 好了,你可以封装它实现行为的扩展。可以简单的把它丢给装饰器# 装饰器本质:动态地把它和你要的代码封装起来,并且返回一个新的可用的函数。a_stand_alone_function_decorated = my_shiny_new_decorator(a_stand_alone_function)a_stand_alone_function_decorated()#输出 :#Before the function runs#I am a stand alone function, don't you dare modify me#After the function runs
二、案例
2.1 案例1.被装饰函数无参数的装饰器
1 def outer(func): 2 def inner(): 3 return func() 4 return inner 5 6 def outer(func): 7 def inner(): 8 print("Start") 9 ret = func()10 print("End")11 return ret12 return inner13 14 @outer15 def f1():16 print("f1")17 18 f1()19 20 out: 21 Start22 f123 End
从上边的案例可以看出,装饰器的本质是:自动执行装饰器函数,并且将被装饰函数当做参数对象本身,传递进去,等同于如下代码
1 def f1(): 2 print("123") 3 def outer(xxx): 4 print('start') 5 xxx() 6 print('end') 7 8 outer(f1) 9 10 out:11 start12 12313 end
-------等同于
1 def outer(func): 2 return "111" 3 @outer 4 def f1(): 5 print("f1") 6 7 print(f1) 8 9 out: 11110 # 将outer函数的return值,赋值给函数f1,这里很直白的体现了出来
1 def outer(func): 2 def inner(): 3 print("before") 4 func() 5 print("End") 6 return inner() 7 #在inner中,return inner() 这样会让inner直接执行,返回值就变成了None 8 9 @outer10 def f1():11 print(123)12 13 print(f1)14 15 out: 16 before17 12318 End19 None
1 def outer(func): 2 def inner(): 3 print("before") 4 r = func() 5 print("End") 6 return r 7 return inner 8 @outer 9 def f1():10 print(123)11 return "函数的返回值"12 print("返回值:" ,f1())13 14 out: 15 before16 12317 End18 返回值: 函数的返回值
2.2 案例2.被装饰函数有参数的装饰器
1 def outer(func): 2 def inner(arg): 3 print("before") 4 r = func(arg) 5 print("End") 6 return r 7 return inner 8 @outer 9 def f1(arg):10 print(arg)11 return "单参数装饰器返回值"12 print("返回值:" ,f1('xxoo'))13 14 out: 15 before16 xxoo17 End18 返回值: 单参数装饰器返回值
2.3 被装饰参数有多个参数装饰器
1 def outer(func): 2 def inner(*args, **kwargs): 3 print("before") 4 r = func(*args, **kwargs) 5 print("End") 6 return r 7 return inner 8 @outer 9 def f1(arg1, arg2):10 print(arg1, arg2)11 return "多参数装饰器返回值"12 print("返回值:" ,f1('xxoo', '你大爷'))13 14 out:15 before16 xxoo 你大爷17 End18 返回值: 多参数装饰器返回值
2.4 多个装饰器装饰函数
多个装饰器装饰的话,本质和一个装饰器是一样的,记住要领:解析顺序是自下而上,执行顺序是自上而下。
2.5 带参数的装饰器函数
1 def Before(request,kargs): 2 print('before') 3 4 def After(request,kargs): 5 print('after') 6 7 8 def Filter(before_func,after_func): 9 def outer(main_func):10 def wrapper(request,kargs):11 12 before_result = before_func(request,kargs)13 if(before_result != None):14 return before_result;15 16 main_result = main_func(request,kargs)17 if(main_result != None):18 return main_result;19 20 after_result = after_func(request,kargs)21 if(after_result != None):22 return after_result;23 24 return wrapper25 return outer26 27 @Filter(Before, After)28 def Index(request,kargs):29 print('index')30 31 a = Index('1','2')32 print(a)33 34 out: 35 before36 index37 after38 None
三、python内置装饰器函数
python还有几个内置装饰器函数分别是staticmethod、classmethod和property,作用分别是把类中定义的实例方法变成静态方法、类方法和类属性。