一、装饰器
装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。
装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
装饰器功能: 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_function def 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.被装饰函数无参数的装饰器
def outer(func):
def inner():
return func()
return inner def outer(func):
def inner():
print("Start")
ret = func()
print("End")
return ret
return inner @outer
def f1():
print("f1") f1() out:
Start
f1
End
从上边的案例可以看出,装饰器的本质是:自动执行装饰器函数,并且将被装饰函数当做参数对象本身,传递进去,等同于如下代码
def f1():
print("")
def outer(xxx):
print('start')
xxx()
print('end') outer(f1) out:
start
123
end
-------等同于
def outer(func):
return ""
@outer
def f1():
print("f1") print(f1) out: 111
# 将outer函数的return值,赋值给函数f1,这里很直白的体现了出来
def outer(func):
def inner():
print("before")
func()
print("End")
return inner()
#在inner中,return inner() 这样会让inner直接执行,返回值就变成了None @outer
def f1():
print(123) print(f1) out:
before
123
End
None
def outer(func):
def inner():
print("before")
r = func()
print("End")
return r
return inner
@outer
def f1():
print(123)
return "函数的返回值"
print("返回值:" ,f1()) out:
before
123
End
返回值: 函数的返回值
2.2 案例2.被装饰函数有参数的装饰器
def outer(func):
def inner(arg):
print("before")
r = func(arg)
print("End")
return r
return inner
@outer
def f1(arg):
print(arg)
return "单参数装饰器返回值"
print("返回值:" ,f1('xxoo')) out:
before
xxoo
End
返回值: 单参数装饰器返回值
2.3 被装饰参数有多个参数装饰器
def outer(func):
def inner(*args, **kwargs):
print("before")
r = func(*args, **kwargs)
print("End")
return r
return inner
@outer
def f1(arg1, arg2):
print(arg1, arg2)
return "多参数装饰器返回值"
print("返回值:" ,f1('xxoo', '你大爷')) out:
before
xxoo 你大爷
End
返回值: 多参数装饰器返回值
2.4 多个装饰器装饰函数
多个装饰器装饰的话,本质和一个装饰器是一样的,记住要领:解析顺序是自下而上,执行顺序是自上而下。
2.5 带参数的装饰器函数
def Before(request,kargs):
print('before') def After(request,kargs):
print('after') def Filter(before_func,after_func):
def outer(main_func):
def wrapper(request,kargs): before_result = before_func(request,kargs)
if(before_result != None):
return before_result; main_result = main_func(request,kargs)
if(main_result != None):
return main_result; after_result = after_func(request,kargs)
if(after_result != None):
return after_result; return wrapper
return outer @Filter(Before, After)
def Index(request,kargs):
print('index') a = Index('','')
print(a) out:
before
index
after
None
三、python内置装饰器函数
python还有几个内置装饰器函数分别是staticmethod、classmethod和property,作用分别是把类中定义的实例方法变成静态方法、类方法和类属性。