美文网首页
Python 闭包

Python 闭包

作者: eeert2 | 来源:发表于2020-05-03 22:57 被阅读0次

在提到闭包之前,我们需要对函数做一些梳理:
函数的局部参数是无法保存的,每次执行函数都是将参数初始化并执行

闭包可以使函数拥有自己的环境上下文,在其中保存执行后的信息。使函数表现的像一个对象,丰富了函数的功能。

0、引言


我们现在要实现一个具有缓存功能的函数,"如果后续传入相同的参数,则不再计算,直接返回结果"

如果是在对象中,这种缓存非常简单就能实现。但是在函数中则异常麻烦:

  • 1 幻想中的写法, [实际上并不能起到作用]
import time


def cache_sum(a, b):
    """这是一个具有缓存功能的求和函数"""
    cache = {}

    key = str(a) + str(b)
    if key in cache:            # 1. 具有缓存结果,则直接返回
        return cache.get(key)
    else:
                                # 2. 计算
        time.sleep(1)
        ret = a + b
        cache[key] = ret        # 3. 将结果存储进缓存

使用cache_sum

if __name__ == '__main__':
    print(datetime.datetime.now())  # 2020-05-04 09:13:13.239913
    cache_sum(1, 5)
    print(datetime.datetime.now())  # 2020-05-04 09:13:14.242900
    cache_sum(1, 5)
    print(datetime.datetime.now())  # 2020-05-04 09:13:15.246474

可以看出,在函数中cache = {}作为局部变量,每次都会被初始化,根本起不到作用 [ 两次执行都耗时一秒,说明缓存没有起作用]。

    1. 改进写法
def cache_sum(a, b):
    """这是一个具有缓存功能的求和函数"""

    key = str(a) + str(b)
    if key in cache:  # 1. 这里的 cache 由使用者提供
        return cache.get(key)
    else:
        # 2. 计算
        time.sleep(1)
        ret = a + b
        cache[key] = ret  # 3. 将结果存储进缓存

使用 cache_sum

if __name__ == '__main__':
    cache = {}

    print(datetime.datetime.now())  # 2020-05-04 09:19:43.842472
    cache_sum(1, 5)
    print(datetime.datetime.now())  # 2020-05-04 09:19:44.846783
    cache_sum(1, 5)
    print(datetime.datetime.now())  # 2020-05-04 09:19:44.846864

[ 第二次没有耗时,说明缓存起作用了]
在这种写法中,我们执行cache_sum还需要提供 cache = {}这样一个变量,这样会引起很多问题:

  • 使用者会不会忘记提供 cache = {}?

  • 使用者会不会在外部修改 cache?
    这些都是无法预料的问题。显然不能作为这个问题的解决方式

    1. 使用闭包完成
import time


def as_cache_sum():
    """返回一个具有缓存功能的函数

    你应该这样使用它

    cache_sum = as_cache_sum()
    ret = cache_sum(1,4)
    print(ret)  # 5
    """
    cache = {}

    def cache_sum(a, b):
        key = str(a) + str(b)
        if key in cache:  # 1. 具有缓存结果,则直接返回
            return cache.get(key)
        else:
            # 2. 计算
            time.sleep(1)
            ret = a + b
            cache[key] = ret  # 3. 将结果存储进缓存

    return cache_sum

第二种写法相比,这里提供变量cache是指外部函数中完成的,而使用者是接触不到这个变量的。

细细的品,你是不是有点明白闭包的这个


一、使用“闭包”

“闭包”的本质是函数的嵌套定义,即在函数内部再定义函数。

在下面这个函数中

 def make_averager():
        """返回一个计算平均值的函数"""
        series = []

        def averager(new_value):
            series.append(new_value)

            total = sum(series)
            return total / len(series)

        return averager

调用 make_averager 时,返回一个 averager 函数对象。每次调用 averager 时,它会 把参数添加到系列值中,然后计算当前平均值。

averager = make_averager()
print(averager(10))  # 10
 
print(averager(12))  # 11

print(averager(14))  # 12

在上述函数中make_averager并不包含真正的执行逻辑,它只做了两件事情

  • 为真正的执行函数提供环境上下文
  • 返回执行函数

averager函数才是真正执行逻辑的地方,它使用了make_averager为它提供了series环境变量,averagerseries的修改会被保存起来(伴随着averager,直到其被销毁)

相关文章

  • python闭包学习

    参考文章 python闭包python闭包一步一步教你认识Python闭包深入浅出python闭包

  • python函数之闭包

    目录 python函数之闭包什么是闭包python中的namespace闭包的条件闭包的优点 python函数之闭...

  • Python 闭包使用注意点

    1 Python 闭包 今天,聊下 python 的闭包。在函数编程中经常用到闭包。 闭包是什么,它是怎么产生的及...

  • python高级之闭包

    python高级之闭包 什么是闭包? 闭包(closure)是函数式编程的重要的语法结构。闭包也是一种组织代码的结...

  • Python 中的闭包

    Python 中的闭包:+ http://python.jobbole.com/82296/

  • python之理解闭包和装饰器

    python之理解闭包和装饰器 1、闭包函数 1.1 python中函数都是对象 结果: 上面定义一个shut函数...

  • 闭包

    浅谈 python 的闭包思想 首先 python的闭包使用方法是:在方法A内添加方法B,然后return 方法B...

  • 2018-11-20

    python函数的闭包 闭包: 嵌套函数调用外部函数的变量 注意: 闭包必须是内部函数调用外部函数定义的变量,这其...

  • Python 入门之 闭包

    Python 入门之 闭包 1、闭包 (1)在嵌套函数内使用(非本层变量)和非全局变量就是闭包 (2)_ clos...

  • Python装饰器(Decorator)完全指南-基础篇

    Decorator基本指南 前提知识 Python中的闭包(closure) 所谓闭包,指的是附带数据的函数对象。...

网友评论

      本文标题:Python 闭包

      本文链接:https://www.haomeiwen.com/subject/nvpowhtx.html