Python装饰器的个人小理解
个人对Python的装饰器小理解
标签: Python 装饰器 设计模式
刚刚开始学Python的时候看的廖雪峰先生的学习笔记,囫囵吞枣看了一遍就撸起袖子开干了,对Python很多特殊功能的理解其实并没有多深入。相信很多人也是一样,只是为了使用Python的某个库而入坑,而没有深入的学习Python这门语言。那么就让我们从装饰器开始,由浅入深吧。
什么是装饰器?
装饰器我将它理解为在不修改函数内部的前提下,对函数的一个“强化”。装饰器的使用其实一开始我还是挺懵逼的,后来慢慢开始理解到闭包、函数对象之后,对装饰器又有了新的理解,原来装饰器能做的事情还是很多的。那么我们就一步步的去理解到底什么是装饰器吧。
闭包的概念
大家都知道,在函数式编程中,函数内部就是一个作用域,更底层的讲,一个函数被调用时,它的内存空间其实只在进程内存空间的一个栈中。当函数调用完成返回时,操作系统就会回收这个栈,所以函数内部的所有变量的生存期只存在于这个函数被调用的时候。
在Python中,函数是可以嵌套定义的,比如说:
def outer(value):
def inner():
value = 10
print value
inner()
return value
ans = outer(20)
print ans
运行得到的结果:
10
20
而在Python中,一切皆为对象,因此函数也能够作为对象被返回,进而被调用。举个栗子:
def outer():
def inner():
print "I'm inner!!!"
return inner
obj = outer()
obj()
运行得到的结果:
I'm inner!!!
那么如果这个返回的函数内部使用了作用域仅在outer()函数中的变量,按理说这样调用inner()是会出错的。但是在Python中的闭包特性,令这一“违反常理”的操作可执行:
def outer(value):
def inner():
print "value is "%value
return inner
obj_fun = outer(0) #照理说value在这次函数调用后就应该被释放了
obj_fun()
运行得到的结果:
outer_value is 0
在这里,函数inner()就是一个闭包,这个“包”里不仅仅装了函数的逻辑,也装了函数运行所需要的数据(或者说对象)。到目前来看,闭包好像还是没什么卵用,但是你想想,如果我们的参数不是一个“value”,而是一个“function”,那会怎么样?比如说:
def outer(func, value):
def inner():
print "run parameter of function before."
func(value)
print "run parameter of function after."
return inner
def speak(value):
print "+%ds "%(value)
new_speak = outer(speak, 1)
new_speak()
运行结果为:
run parameter of function before.
+1s
run parameter of function after.
装饰器
可能有的同学到现在还不理解到底闭包能干什么,那好我们现在设想一个情景:
之前在我们的网站中,某一个URI对于所有外来的的get请求都可以返回一句“苟利国家生死以”,但是现在觉得有些人不是同道中人,需要对这些请求加一些验证,只有请求头中包含
Agent : real fans
字段的用户才能收到这句话。
如果要在处理请求的函数里直接修改,那函数显然会越来越臃肿,让之后的人看着蛋疼,这时候装饰器就大派用场了:
from server import handler #handler is a function
from Request import get_request
from log import log_input
new_request = get_request()
def wrapper(func, request):
def checker():
if not request.header.CheckHeader({"Agent":"real fans"}):
log_input("this guy is not hasi")
return None
else:
log_input("real fans!")
return func(request)
return checker
new_handler = wrapper(handler, new_request)
new_handler()
这样,在完全不修改函数handler()的前提下,解决了这个问题。如果之后要扩大福利,不需要验证,那样也不需要对代码进行多少修改就能达到效果。什么?你还觉得太麻烦?!幸好程序员的懒惰就是业界进步的阶梯,Python为了让大家能更早的收工,增加了一个对装饰器的语法糖:
def outer(func):
def inner(value):
print "run parameter of function before."
func(value)
print "run parameter of function after."
return inner
@outer
def speak(value):
print "+%ds "%(value)
speak(1)
运行结果为:
run parameter of function before.
+1s
run parameter of function after.
是不是更简单了呢。
以上是个人粗浅的一点认识,之后有更深入了解会及时回来更新的
2017.7.3