python 装饰器、内部函数、闭包简单理解
转载
原文地址:https://www.cnblogs.com/starsea/p/5427021.html
python内部函数、闭包共同之处在于都是以函数作为参数传递到函数,不同之处在于返回与调用有所区别。
1、python内部函数
python内部函数示例:
1
2
3
4
5
6
7
8
|
def test( * args): def add( * args): # 显示的调用外部函数的参数 return args return add( * args) # 返回内部函数的直接调用 运行结果如下: test( 1 , 2 , 3 ) ( 1 , 2 , 3 ) |
内部函数直接引用外部函数参数,外部函数test显示的返回内部函数add的调用。
当需要在函数内部多次执行复杂任务时,内部函数非常有用,从而避免了循环和代码的堆叠重复。
2、python闭包
内部函数可以看作是一个闭包。闭包是一个可以由另一个函数动态生成的函数,并且可以改变和存储函数外创建的变量的值。
python闭包示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
def test(a): def add(): # 没用引用外部函数的参数 return "it's a callable %s" % a # 直接在内部函数使用外部函数的参数 return add # 返回内部函数本身,不返回内部函数调用 运行结果如下: a1 = test( 1 ) # 动态生成的一个可以记录外部变量的函数 <function __main__.add> a1() # 调用此函数 it's a callable 1 test( 1 )() # 本身调用过程,先动态生成一个函数再进行调用 it's a callable 1 |
3、python装饰器
装饰器实质上是一个函数,它把一个函数作为输入并且返回另外一个函数,在装饰器中,通常使用下面这些python技巧:
-
*args 和 **kwargs
-
闭包
-
作为参数的函数
python装饰器示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
def test(func): # 将函数作为参数进行传递 def add( * args, * * kwargs): print “it's a d” return func( * args, * * kwargs) # 内部函数进行相关操作以后,返回传递函数的调用 return add def func(a,b): return a + b 运行结果如下: test(func) # 将func作为函数传递进test函数进行装饰 <function __main__.add> # 装饰后的函数,类似闭包 test(func)( 1 , 2 ) # 显示的对装饰后的函数进行调用 it's a d # 中间被装饰的过程被print出来 3 更简单的方法调用装饰器 @test # 同一个函数可以调用多个装饰器,执行过程中不分先后顺序 def func(a,b): return a + b 无论传入test()的函数func是什么,装饰器都会返回一个新的函数,其中包含test增加的额外语句。<br>实际上,装饰器并不需要执行函数func中的代码,只是在结束前函数add调用函数func以得到的func返回的结果和附加代码的结果 |
装饰器本身需要传递参数的时候:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
def test(cmd): # 将参数传递 def exc(func): # 第二步进行函数作为参数传递 def add( * args, * * kwargs): print "it's a %s" % cmd print "begin" return func( * args, * * kwargs) return add return exc 运行结果如下: test( 'haha' ) <function __main__.exc> test( 'haha' )(func)( 1 , 2 ) # 调用装饰器返回结果 it's a haha begin 3 更简单的方法调用 @test ( 'haha' ) # test函数进行了参数传递 def func(a,b): return a + b |
python装饰器注意事项:
对func进行装饰以后,func的函数命名空间发生了变化
1
2
|
执行 func.__name__ add |
如何指向原来的命名空间呢?python自带了functools库直接调用则行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
import functools def test(func): @functools .wraps(func) def add( * args, * * kwargs): print "it's a decorator" return func( * args, * * kwargs) return add @test def func(a,b): return a + b 再次运行,查看命名空间 func.__name__ func # 返回了本身 |
更进一步理解详见:https://www.cnblogs.com/liyuanhong/articles/14554283.html
博客里大都是转载的内容,其目的主要用户知识的组织和管理。