0

python中闭包示例

 2 years ago
source link: https://www.hi-roy.com/posts/python%E4%B8%AD%E9%97%AD%E5%8C%85%E7%A4%BA%E4%BE%8B/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

python中闭包示例

2016-03-18

概念上的东西这里就不详细解释了,为什么需要闭包(Closures)呢?个人理解就是某些情况下你需要在外部访问函数内部的变量时,闭包就该大显身手了。闭包的一种典型表现就是函数内部定义了新的函数。这里举几个例子以记录使用闭包时的几个注意点,例子来源于这里,大神用javascript写的示例,这里改成python的,也顺便说说遇到的坑。

例子1:闭包中局部变量是引用而非拷贝

def say667():
    '''闭包中局部变量是引用而非拷贝'''
    num = 666
    def saynum():
        print "in saynum:", num
    num += 1
    return saynum
temp = say667()
temp()

输出结果是667,有C、C++基础的应该不难理解这个吧?

例子2:多个函数绑定同一个闭包,因为他们定义在同一个函数内。

def setupSomeGlobals():
    '''多个函数绑定同一个闭包,因为他们定义在同一个函数内。'''
    num = [666]
    def get_num():
        print "num:", num
    def add_num():
        num[0] += 1
    def set_num(x):
        num[0] = x
    global getnum
    getnum = get_num
    global addnum
    addnum = add_num
    global setnum
    setnum = set_num
setupSomeGlobals()
getnum()
addnum()
getnum()
setnum(10)
getnum()

注意这个例子中使用py2有坑,见这里。如果你定义一个比如整型这种不可变类型,则在py2中报错“UnboundLocalError: local variable ‘num’ referenced before assignment”。解决办法就是定义列表、字典甚至类,在py3中使用nonlocal关键字。

例子3:当在一个循环中赋值函数时,这些函数将绑定同样的闭包

def buildlist(mylist):
    '''当在一个循环中赋值函数时,这些函数将绑定同样的闭包,可以理解为上一个例子的变体'''
    result = []
    for one in mylist:
        item = "item:%s" % one
        result.append(lambda :(item,one))
    return result
def testlist():
    fnlist = buildlist([1,2,3])
    for i in fnlist:
        print i()
testlist()

这个例子中python和javascript的返回结果不同,因为python的for循环结束时就是值就是最后一个,而不会再+1。

例子4:外部函数所有局部变量都在闭包内,即使这个变量声明在内部函数定义之后。

def sayAlice():
    '''外部函数所有局部变量都在闭包内,即使这个变量声明在内部函数定义之后。'''
    def say():
        print "hello,",name
    name = "Alice"
    return say
helloAlice = sayAlice()
helloAlice()

这个我以前还真没注意到……

例子5:每次函数调用的时候创建一个新的闭包

def newClosure(someNum,someRef):
    '''每次函数调用的时候创建一个新的闭包'''
    num = [someNum] #注意这里,理由同示例2
    arr = [1,2,3]
    ref = someRef
    def fun(x):
        num[0] += x
        arr.append(x)
        print "num:",num,"arr:",arr,"ref:",ref
    return fun
closure1=newClosure(40,{'someVar':'closure 1'});
closure2=newClosure(1000,{'someVar':'closure 2'});
closure1(5)
closure2(-10)

至于应用,我第一个想到的就是python中各种装饰器了。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK