博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python中的闭包-closure
阅读量:2433 次
发布时间:2019-05-10

本文共 1731 字,大约阅读时间需要 5 分钟。

 版权声明:本文为博主原创文章,转载请声明出处并添加原文链接。    https://blog.csdn.net/azsx02/article/details/78430709

闭包的概念
在一个函数中可以(嵌套)定义另一个函数时,如果内部的函数引用了外部的函数的变量,则可能产生闭包。

简单的说,就是某个内部函数被当做对象返回时,夹带了这个内部函数之外的变量,这就形成了一个闭包。

def logging(level):

    def say(words):
        print '{} is a outer variable'.format(level)
        print "say {0} is {1}".format(words, level) # 夹带外部变量level
    return say # 返回的是say这个函数,它夹带了它之外的level变量

say = logging('right')

say('hello') # right is a outer variable
             # say hello is right

print say.__closure__ #(<cell at 0x00000000025C7138: str object at 0x00000000025CCBE8>,)

print say.func_closure[0].cell_contents # right
通过闭包,运行say(‘hello’),不仅能够完美运行say函数的功能,还可以在say函数中引用了外部的一个变量,进而可以实现更加多样化的功能。试想一下,如果外部变量不是level,而是一个函数对象呢?这里就引出了装饰器的概念。
在上面的例子中,内部函数say就是闭包函数,其实闭包函数相对与普通函数会多出一个closure的属性,里面定义了一个元组用于存放所有的cell对象,每个cell对象一一保存了这个闭包中所有的外部变量。
Python闭包之经典的for循环问题
上个例子中,内部函数引用的外部变量是外部函数的参数,而下面这个例子,引用的是外部函数中的局部变量,它们相对于内部函数,都是外部变量,符合闭包的定义。

# 希望一次返回3个函数,分别计算1x1,2x2,3x3

# 可以用列表接收这3个函数,然后返回列表。
def count():
    fs = []
    for i in range(1, 4):
        def f():
            return i*i
        fs.append(f)
    return fs

f1, f2, f3 = count() # 将fs中的三个f分别传递给f1,f2,f3

print(f1()), print(f2()), print(f3()) # 9 9 9
f1(), f2(), f3() 结果不应该是 1, 4, 9 吗,实际结果为什么都是 9 呢?

原因就是当 count() 函数返回了 3 个函数时,这 3 个函数所引用的变量 i 的值已经变成了 3。由于 f1、f2、f3 并没有被调用,所以,此时他们并未计算 i*i,当 f1 被调用时,i 已经变为 3 了。

如何修改?

方法一
为变量 i 创建一个封闭的作用域,将i传递到封闭的作用域内,即将 i 传递给 j。

def count():

    fs = []
    for i in range(1, 4):
        def f(j):
            def g():
                return j*j
            return g
        r = f(i)
        fs.append(r)
    return fs
方法二
思路比较巧妙,用到了默认参数 j 在函数定义时可以获取到 i 的值,虽然没有用到闭包,但是和方法一有异曲同工之处。

def count():

    fs = []
    for i in range(1, 4):
        def f(j=i):
            return j*j
        fs.append(f)
    return fs
--------------------- 
作者:huhu8812 
来源:CSDN 
原文:https://blog.csdn.net/azsx02/article/details/78430709 
版权声明:本文为博主原创文章,转载请附上博文链接!

你可能感兴趣的文章
链表算法面试题---交换链表的节点II
查看>>
链表算法面试题---链表的插入排序
查看>>
链表算法面试题---链表的归并排序
查看>>
链表算法面试题---合并N个有序链表
查看>>
链表算法面试题---分割链表
查看>>
总结、归类---使用二分处理旋转数组的问题
查看>>
分布式常用技术
查看>>
uniapp DES加解密
查看>>
小程序DES加解密
查看>>
Vue 路由 导航守卫(全局守卫、路由独享守卫)
查看>>
ajax图片上传
查看>>
小程序数组去重
查看>>
微信小程序生成分享海报
查看>>
值得收藏的 CSS 形状
查看>>
H5屏幕宽度大小自适应方式
查看>>
中秋诗歌两首
查看>>
计算机学科一些重要算法的列表
查看>>
进站画面:1q84音乐电台
查看>>
回复旦
查看>>
二十世纪计算机十大著名算法
查看>>