python的闭包,装饰器,@
2017-11-05 22:47
309 查看
一、闭包
问题描述:
1)在inner()函数中引用了x,该变量是outer()临时作用域的
2)fun变量是函数inner()的函数对象,在调用fun时,可能outer的内层作用域已经销毁
3)由以上分析这就导致了调用fun()时会出错
而在python中不会出现以上情况,这叫做闭包,也就是在
返回的inner()函数对象不仅仅是一个函数实体,还包括了该函数调用时程序上下文,对于inner()中引用到外部变量,会被保存起来(其实就是函数的调用环境,调用栈别被存起来了),当下一次调用fun的时候,就会重入,恢复之前的环境。这个其实类似于C++中函数对象,lamda,用一个私有变量保存外部参数。
二、装饰器
问题描述:
之所以叫装饰器,肯定是对函数做了一些修饰
def fun():
return 1
decorate = outer(fun)
>>>decorate()
输出:
before fun()
after fun
2
这里outer就是一个装饰器,具体的装饰过程由inner来完成,根据之前提到的闭包来理解,返回了inner()函数(装饰的具体实施者),然后并把它赋值给decorate,在调用decorate时,函数fun()已经被修饰过了的版本,另外要注意inner函数是要被闭包的,才是最后实际执行的函数,被修饰的函数的名其实最后已经是另外一个函数,所以最后调用的时候,被修饰函数的参数一定要复合inner()的参数规定。比如
这里最后调用func()的时候,参数一定要和inner()一致。但是一般不会这么写,那会使得调用很麻烦,还得去了解inner的参数。一种更方便的方法是把inner定义成
这样就可以接受任何参数,那么被修饰的函数的调用也比较随意了。不用刻意和inner匹配
这里进一步
这样就是利用outer装饰了函数自身,用新版本代替旧版本,其实装饰器最主要的作用是把一些不变的东西抽象出去,把变动的部分放进去了,我们只需要关注变动的部分,不变的部分不用太在意,这样提高开发效率。
三、使用@标识符,可以应用装饰器到函数上。
这里的@outer效果和第一行效果一样,都是利用outer来装饰了fun,后续调用fun实际是调用outer中的inner函数。
注意:利用@只不过是第一行的一种省略写法,实际上outer任然被调用了,并且自己执行了自己的逻辑(一般都是一些预热准备工作),如flask的路由@route其实执行了route函数,并且在该函数中添加了URL的路由。这种@的写法会导致python解释器自动的调用route()函数,自动调用装饰函数,有多少个@就会调用多少次。这样完成了一些看不到的繁琐工作(类似于C++编译器自己所做的背后工作)。
问题描述:
def outer()
x = 1
def inner()
print x
return inner
fun = outer()
fun()
1)在inner()函数中引用了x,该变量是outer()临时作用域的
2)fun变量是函数inner()的函数对象,在调用fun时,可能outer的内层作用域已经销毁
3)由以上分析这就导致了调用fun()时会出错
而在python中不会出现以上情况,这叫做闭包,也就是在
fun = outer()
返回的inner()函数对象不仅仅是一个函数实体,还包括了该函数调用时程序上下文,对于inner()中引用到外部变量,会被保存起来(其实就是函数的调用环境,调用栈别被存起来了),当下一次调用fun的时候,就会重入,恢复之前的环境。这个其实类似于C++中函数对象,lamda,用一个私有变量保存外部参数。
二、装饰器
问题描述:
之所以叫装饰器,肯定是对函数做了一些修饰
def outer(fun):
def inner()
print 'before fun()'
ret = fun()
print 'after fun'
ret ret + 1
return inner
def fun():
return 1
decorate = outer(fun)
>>>decorate()
输出:
before fun()
after fun
2
这里outer就是一个装饰器,具体的装饰过程由inner来完成,根据之前提到的闭包来理解,返回了inner()函数(装饰的具体实施者),然后并把它赋值给decorate,在调用decorate时,函数fun()已经被修饰过了的版本,另外要注意inner函数是要被闭包的,才是最后实际执行的函数,被修饰的函数的名其实最后已经是另外一个函数,所以最后调用的时候,被修饰函数的参数一定要复合inner()的参数规定。比如
def outer(func)
def inner(a,b,c)
ret = func(a,b)
return ret + 1
return inner
def func(a,b)
return a + b
func = outer(func)
func(1,2,3)
这里最后调用func()的时候,参数一定要和inner()一致。但是一般不会这么写,那会使得调用很麻烦,还得去了解inner的参数。一种更方便的方法是把inner定义成
def inner(*args,**kwargs):
这样就可以接受任何参数,那么被修饰的函数的调用也比较随意了。不用刻意和inner匹配
这里进一步
func=outer(func)
这样就是利用outer装饰了函数自身,用新版本代替旧版本,其实装饰器最主要的作用是把一些不变的东西抽象出去,把变动的部分放进去了,我们只需要关注变动的部分,不变的部分不用太在意,这样提高开发效率。
三、使用@标识符,可以应用装饰器到函数上。
fun = outer(fun)
@outer
def fun():
return 1
这里的@outer效果和第一行效果一样,都是利用outer来装饰了fun,后续调用fun实际是调用outer中的inner函数。
注意:利用@只不过是第一行的一种省略写法,实际上outer任然被调用了,并且自己执行了自己的逻辑(一般都是一些预热准备工作),如flask的路由@route其实执行了route函数,并且在该函数中添加了URL的路由。这种@的写法会导致python解释器自动的调用route()函数,自动调用装饰函数,有多少个@就会调用多少次。这样完成了一些看不到的繁琐工作(类似于C++编译器自己所做的背后工作)。
相关文章推荐
- Python闭包与装饰器
- python闭包,装饰器,生成器
- [Python 实战] - No.9 Python闭包和装饰器
- python的闭包及装饰器
- Python学习笔记——闭包,装饰器
- Python 返回函数_闭包_装饰器
- python 闭包与装饰器的实现
- 深入学习python(三) 闭包(Decorator)与装饰器(Closure)
- 【python】闭包、@修饰符(装饰器)、
- 21.python中的闭包和装饰器
- python基础7之闭包与装饰器
- Python闭包的高级应用-装饰器的实现
- 简析Python的闭包和装饰器
- python的闭包与装饰器
- Python的高级特性7:闭包和装饰器
- python中闭包和装饰器的理解(关于python中闭包和装饰器解释最好的文章)。
- python----------闭包 、装饰器
- python 闭包 装饰器
- python中函数总结之装饰器闭包
- python 装饰器和闭包