本文实例讲述了Python闭包思想与用法。分享给大家供大家参考,具体如下:
浅谈 python 的闭包思想
首先 python的闭包使用方法是:在方法A内添加方法B,然后return
方法B 注意,return
的时候不要添加任何参数,包括()
这样,通过调用方法A 返回的是一个function 对象,如 demo=方法A 可以直接使用 demo(参数) 将调用方法B 这里不用关注方法B的方法名,
只需要关注参数就可以了,demo(参数) 这里的参数其实就是闭包的方法B的参数,可以多个参数或者元祖一起使用。
其次 在Python中创建一个闭包可以归结为以下三点:
- 闭包函数必须有内嵌函数
- 内嵌函数需要引用该嵌套函数上一级namespace中的变量
- 闭包函数必须返回内嵌函数
对,没错,python的装饰器就是使用了闭包。
好吧,最后再举个栗子:
1
2
3
4
5
6
7
8
|
def test1(prefix):
def test2(name):
print ( 'test2闭包内:' ,name)
def test3( * name1):
print ( 'test3 闭包内:' ,name1)
return test3
m = test1( 'prefix' )
m( "haha" , 'heihei' )
|
打印结果:
D:\python\python.exe D:/Python_day/day1.py
test3 闭包内: ('haha', 'heihei')
这个例子说明,当函数 test1 的生命周期结束之后,test1('prefix')
中的参数 prefix 这个变量依然存在,生命周期不会随着函数调用结束而消失。
为啥要用闭包呢? 感觉这个功能一般啊,毕竟回调函数是死的,只能回调一个,但是有个函数就是能生成无数个对象,嗯,是的,这玩意和类的功能有点相似。闭包可以被理解为一个只读的对象,你可以给他传递一个属性,但它只能提供给你一个执行的接口,这就牵扯到的另一个特性:惰性求值
如:
1
2
3
4
5
6
7
8
9
10
11
12
|
# 伪代码示意
class QuerySet( object ):
def __init__( self , sql):
self .sql = sql
self .db = Mysql.connect().corsor() # 伪代码
def __call__( self ):
return db.execute( self .sql)
def query(sql):
return QuerySet(sql)
result = query( "select name from user_app" )
if time > now:
print result # 这时才执行数据库访问
|
上面这个不太恰当的例子展示了通过闭包完成惰性求值的功能,但是上面query返回的结果并不是函数,而是具有函数功能的类。有兴趣的可以去看看Django的queryset的实现,原理类似。
还有另一种用处:需要对某个函数的参数提前赋值的情况,当然在Python中已经有了很好的解决访问 functools.parial
,但是用闭包也能实现。
如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
def partial( * * outer_kwargs):
def wrapper(func):
def inner( * args, * * kwargs):
for k, v in outer_kwargs.items():
kwargs[k] = v
return func( * args, * * kwargs)
return inner
return wrapper
@partial (age = 15 )
def say(name = None , age = None ):
print name, age
say(name = "the5fire" )
# 当然用functools比这个简单多了
# 只需要: functools.partial(say, age=15)(name='the5fire')
|
对于工厂函数的理解,感觉和闭包类似,在创建主函数后返回的对象,可以直接传参使用,其实这里返回的对象,就是一个类。
希望本文所述对大家Python程序设计有所帮助。
原文链接:https://blog.csdn.net/guoxinjie17/article/details/77838851