前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何使用闭包进行一次降维打击?

如何使用闭包进行一次降维打击?

作者头像
青南
发布2020-04-26 14:48:13
5620
发布2020-04-26 14:48:13
举报
文章被收录于专栏:未闻Code未闻Code

一个函数内部又定义一个函数,内层函数能够读写外层函数中的变量,外层函数把这个内层函数作为值返回出来。这个内层函数就叫做闭包(Closure)。

闭包本质上就是一个函数。

我们来看一个简单例子:

代码语言:javascript
复制
def outer():
    a = 1
    def inner():
        print(f'外层函数中的变量 a 的值为:{a}')
    return inner

我们用上面这段代码来解释一下闭包的定义:

一个函数(outer)内部又定义一个函数(inner),内层函数inner能够读写外层函数outer中的变量a。外层函数outer把内层函数inner作为值返回。

我们来运行一下这段代码:

可以看到,直接运行outer()以后,返回的是一个函数对象,我们需要再次运行这个函数对象,才能运行最里面的函数的代码。

由于 Python 有作用域的规定,所以在闭包里面是默认只能读取,但不能修改外层函数的变量。我们来测试一下:

当你在闭包里面只有读,没有写的时候,闭包可以正确读取外层的变量值。但是当你尝试给外层变量赋值的时候,如果你在赋值语句上方尝试读取这个变量,就会报错。就像是没有定义变量一样。

并且,即使在赋值语句上方没有读取变量值的操作,你的赋值语句也不能修改外层函数的变量。在闭包中是另外创建一个同名的变量而已,对它的修改不能影响外层变量。

为了在闭包中修改外层变量,我们需要使用一个关键词:nonlocal,它可以获取上一层的作用域。

我们来看一下:

基于这个特性,我们用闭包来实现一个计算斐波那契数列的程序:

代码语言:javascript
复制
def calc_fib():
    a = 0
    b = 1
    def calc():
        nonlocal a, b
        a, b = b, a + b
        return a
    return calc

你肯定很奇怪,怎么没有指定返回斐波那契数列第几项啊?

实际上,你自己想要几项就有几项。我们在外面写个 for 循环,依次获得1-40项:

大家注意,每一次我获取值的时候,都是直接运行fib(),不需要传入具体的值。也就是说,这个函数fib它自己知道自己当前运行到第几个值了。

这种计算斐波拉契数列的方式,速度也非常快,我们来看看计算1-40项,一共需要多长时间:

总共需要的时间是秒,也就是0.000077秒。大家对比我们之前的一篇文章:一日一技:立竿见影地把你的 Python 代码提速7倍我们已经知道,使用原始递归算法计算第40项,需要36秒。即使使用 C 语言加速,也需要5秒钟。

而使用闭包,只需要0.000077秒,速度足足提高了10万倍不止。可以称得上是降维打击了。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 未闻Code 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档