管窥python闭包

栏目: Python · 发布时间: 5年前

内容简介:什么是闭包?来看看wiki的解释在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

什么是闭包?

来看看wiki的解释

在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

这个解释比较学术话,我的理解是引用了函数体外部变量的函数,叫做函数闭包,举个栗子:

def func():
    a = 1
    def closure():
        print(a)
    return closure()

对于 func 这个函数来说, closure 就是一个闭包,因为 closure 引用了 func 函数体内部变量 a ,脱离了 func 谈论 closure 是没有意义的。

在python,函数闭包这一概念通过 python 装饰器落地,成为python的一大语法糖。

先来看一下使用实例

def decorator(func):
    print("this is decorator")
    return func
    
@decorator
def func():
    print("this is func")

输出

this is decorator
this is func
@ + decorator (函数名)构成了装饰器,从结果来看 decorator 函数要先于 func 函数执行,从闭包的概念上来看,可以认为 funcdecorator

的闭包,python将这种使用行为标准化为装饰器。这里有疑问, func 并没有使用 decorator 的变量啊(这个示例里面decorator中并没有定义变量)?

别着急,我们先来看一下 func 带参数的情况。

def decorator(func):
    print("this is decorator")
    def wrapper(func_param):
        return func(func_param)
    return wrapper

@decorator
def func(a):
    print(a)

func("this is func param a")

输出

this is decorator
this is func param a

decorator 带参数的情况又该如何?

def decorator(decorator_param):
    print(decorator_param)
    def wrapper(func):
        print("this is wrapper")
        def sub_wrapper(*args, **kwargs):
            print("this is sub_wrapper")
            return func(*args, **kwargs)
        return sub_wrapper
    return wrapper

@decorator("this is decorator param")
def func(a):
    print(a)

func("this is func param")

输出

this is decorator param
this is wrapper
this is sub_wrapper
this is func param

可以看到,为了传递参数,需要层层闭包来实现,写法上是变得更加复杂,但是带来的好处也是很可观的:减少了重复代码

装饰器能做什么?

以上实例无一例外反映了 装饰器 (如上例中的 decorator 函数)会先于 被装饰函数 (也就是上例中的的 func 函数)执行

这有点类似于中间件的概念,比如你想在想在第一个函数执行前打印一下当时时间,写一个装饰器就可以很容易实现,就像下面这样

from datetime import datetime

def decorator(decorator_param):
    print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    def wrapper(func):
        print("this is wrapper")
        def sub_wrapper(*args, **kwargs):
            print("this is sub_wrapper")
            return func(*args, **kwargs)
        return sub_wrapper
    return wrapper

@decorator("this is decorator param")
def func(a):
    print(a)

func("this is func param")

so easy!

ps:

在golang中, defer 函数会在当前函数退出前执行,正好和python中的装饰器功能相对应。可以对比理解。

参考:


以上所述就是小编给大家介绍的《管窥python闭包》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

欲罢不能

欲罢不能

[美] 亚当·奥尔特 / 闾佳 / 机械工业出版社 / 2018-4-1 / 59.00元

全面揭秘和解决“行为上瘾”的奠基之作 美国亚马逊分类图书畅销榜第一名 行为上瘾是什么?诱人上瘾的体验是如何设计出来的? 如何远离行为上瘾?如何用行为上瘾做些好事? ◆ 内容简介 ◆ 欢迎来到“行为上瘾”的时代! 我们中近半数人至少有一种“行为上瘾”:无时无刻盯着手机,不断刷朋友圈,通宵追看电视剧集,没日没夜打游戏,频繁查看邮件,用太多时间工作…… 而那些生......一起来看看 《欲罢不能》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具