首先给出闭包函数的必要条件:

闭包函数必须返回一个函数对象

闭包函数返回的那个函数必须引用外部变量(一般不能是全局变量),而返回的那个函数内部不一定要return

几个典型的闭包例子:

#ENV>>> Python 3.6

#NO.1

defline_conf(a, b):defline(x):return a * x +breturnline#NO.2

defline_conf():

a= 1b= 2

defline(x):print(a * x +b)returnline#NO.3

def_line_(a,b):defline_c(c):defline(x):return a*(x**2)+b*x+creturnlinereturn line_c

不包括print语句的代码是4行,闭包写法是6行,看起来有点不对劲啊?怎么闭包实现需要的代码量还多呢?别急,我现在有个需求:

再定义100条直线!

那么现在谁的代码量更少呢?很明显这个是可以简单计算出来的,采用闭包的方式添加一条直线只需要加一行代码,而普通做法需要添两行代码,定义100条直线两种做法的代码量差为:100+6 -(100*2+4) = -98。需要注意的是,实际环境中定义的单个函数的代码量多达几十上百行,这时候闭包的作用就显现出来了,没错,大大提高了代码的可复用性!

注意:闭包函数引用的外部变量不一定就是其父函数的参数,也可以是父函数作用域内的任意变量,如“热身”中的第二段代码:

二、如何显式地查看“闭包”

接上面的代码块:

L=line_conf()print(line_conf().__closure__) #(,

#)

for i in line_conf().__closure__: #打印引用的外部变量值

print(i.cell_contents) #1 ; #2

__closure__属性返回的是一个元组对象,包含了闭包引用的外部变量。

若主函数内的闭包不引用外部变量,就不存在闭包,主函数的_closure__属性永远为None:defline_conf():

a= 1b= 2

defline(x):print(x+1) #<<<------

returnline

L=line_conf()print(line_conf().__closure__) #None

for i in line_conf().__closure__: #抛出异常

print(i.cell_contents)

三、为何叫闭包?

如你所见,line_A对象作为line_conf返回的闭包对象,它引用了line_conf下的变量b=1,在print时,全局作用域下定义了新的b变量指向20,最终结果仍然引用的line_conf内的b。这是因为,闭包作为对象被返回时,它的引用变量就已经确定(已经保存在它的__closure__属性中),不会再被修改。

是的,闭包在被返回时,它的所有变量就已经固定,形成了一个封闭的对象,这个对象包含了其引用的所有外部、内部变量和表达式。当然,闭包的参数例外。

四、闭包可以保存运行环境

思考下面的代码会输出什么?

关于这个问题的深入探讨(python新手理解起来可能需要点时间),我们先看下面的代码(2019/5/19增):

_list =[]for i in range(3):deffunc():return i+1func.__doc__ =i

func.__hash__ =i

func.__repr__ =i

func.__defaults__ = tuple([i]) #这个属性必须是tuple类型

func.__name__ = f'{i}'func.hello= i #自定义一个属性并赋值

#不能再玩了

_list.append(func)for f in_list:print(f.__doc__,

f.__hash__,

f.__repr__,

f.__defaults__,

f.__name__,

f.hello,

f(),

)#输出#0 0 0 (0,) 0 0 3#1 1 1 (1,) 1 1 3#2 2 2 (2,) 2 2 3

代码中我在保存函数时,修改了函数的一些属性(前几个叫做magic method,是函数对象默认拥有的),使它们等于循环内的变量i,hello属性显然是我自定义的一个属性,也让它等于了i。

然后,我们循环打印每个函数的这些属性,可以发现,咦~ 这些属性居然可以保存这个变量i :)

嗯,是的,函数的一些基本属性在定义时就会有一个初始的确定值(不论这个值是由可变或不可变对象构成,都是一个完整拷贝,不受源变量变动影响); 闭包保存这个变量的原理是一样的,它用的是函数的__closure__属性,这个属性还有一点特殊,它是只读的,不能由人为修改。(function还有一个__code__属性,这个对象很牛)

这部分内容是对闭包和函数对象的更深一层的探讨,理解后更上一层楼;

不过当你不知道这些属性时是做什么用时,最好不要修改它们。

五、闭包的实际应用

现在你已经逐渐领悟“闭包”了,趁热打铁,再来一个小例子:

看到这里,你也可以试着自己写出一个简单的闭包函数。

OK,现在来看一个真正在实际环境中会用到的案例:

1、【闭包实现快速给不同项目记录日志】

importloggingdeflog_header(logger_name):

logging.basicConfig(level=logging.DEBUG, format='%(asctime)s [%(name)s] %(levelname)s %(message)s',

datefmt='%Y-%m-%d %H:%M:%S')

logger=logging.getLogger(logger_name)def_logging(something,level):if level == 'debug':

logger.debug(something)elif level == 'warning':

logger.warning(something)elif level == 'error':

logger.error(something)else:raise Exception("I dont know what you want to do?")return_logging

project_1_logging= log_header('project_1')

project_2_logging= log_header('project_2')defproject_1():#do something

project_1_logging('this is a debug info','debug')#do something

project_1_logging('this is a warning info','warning')#do something

project_1_logging('this is a error info','error')defproject_2():#do something

project_2_logging('this is a debug info','debug')#do something

project_2_logging('this is a warning info','warning')#do something

project_2_logging('this is a critical info','error')

project_1()

project_2()

python闭包详解函数_Python闭包详解相关推荐

  1. 好程序员前端教程之JavaScript闭包和匿名函数的关系详解...

    好程序员前端教程之JavaScript闭包和匿名函数的关系详解 本文讲的是关于JavaScript闭包和匿名函数两者之间的关系,从匿名函数概念到立即执行函数,最后到闭包.下面一起来看看文章分析,希望你 ...

  2. python代码大全表解释-python操作列表的函数使用代码详解

    python的列表很重要,学习到后面你会发现使用的地方真的太多了.最近在写一些小项目时经常用到列表,有时其中的方法还会忘哎! 所以为了复习写下了这篇博客,大家也可以来学习一下,应该比较全面和详细了 列 ...

  3. python中func自定义函数_Python函数之自定义函数作用域闭包

    一 前言 1.1 为什么要用函数 代码的组织结构更清晰,可读性好: 遇到重复的功能不需要重新编写代码,调用函数即可,代码不会冗余: 功能需要扩展时,只需要修改函数内容即可,实现统一管理,降低代码维护难 ...

  4. python闭包的应用场景_Python闭包函数定义与用法分析

    python函数的闭包怎么理解小编憎恨离别.但若,离别能让你牵挂,小编愿意离开你. 1. 闭包的概念 首先还得从基本概念说起,什么是闭包呢?来看下维基上的解释: 复制代码代码如下: 在计算机科学中,闭 ...

  5. python返回绝对值的函数_Python中用于返回绝对值的abs()方法

    Python中用于返回绝对值的abs()方法 方法abs() 返回x的绝对值,-x-零之间的(正极)的距离. 语法 以下是abs()方法的语法: abs( x ) 参数 x -- 这是一个数值表达式 ...

  6. python中的cell函数_python基础-函数

    函数的基本使用 函数的参数详解 名称空间与作用域 闭包函数 装饰器 2020.9.11 小白学习,如有错误欢迎指点 参考自egon大佬Python快速入门神器​www.zhihu.com 函数 使用函 ...

  7. python中的get函数_python之函数用法get()

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法get() #http://www.runoob.com/python/att-dic ...

  8. python语言中有哪些函数_Python语言中的函数

    本文主要向大家介绍了Python语言中的函数,通过具体的内容向大家展示,希望对大家学习Python语言有所帮助. 学了 Python 中的数据类型,语句,接下来就来说一下 Python 中的函数,函数 ...

  9. python中的匿名函数_python匿名函数

    文章导读: 以前自己一直没搞明白Python中的匿名函数,现在拿这个问题基本上搞明白了,拿自己的理解整成一篇文章,附带大量例子,让其更加好理解. 在编程语言中,函数的应用: 1. 代码块重复,这时候必 ...

最新文章

  1. IOS 百度地图获取当前屏幕的经纬度
  2. 2021-12-27
  3. 机器学习 —— python库 —— 使用array创建
  4. 调用接口登录禅道_有java调用api登录并验证禅道的实例吗
  5. 更新SQL Server实例所有数据库表统计信息
  6. Java 中 Vector、ArrayList、List 使用深入剖析
  7. Logistic Regression 之 Sigmoid
  8. python apache mysql_在Linux系统上部署Apache+Python+Django+MySQL环境
  9. python房子代码_基于python的链家小区房价爬取——仅需60行代码!
  10. 360内部监控系统Wonder实践之路
  11. 学习笔记01:《开放平台产品成长之路-POP》
  12. 两分钟教你玩转千图成像Part1~
  13. BAT批处理文件,脚本时间值%time:~0,2%%time:~3,2%%time:~6,2%的用法
  14. R语言基础 | t检验、F检验
  15. Emmagee—开源Android性能测试工具
  16. 全球及中国墙绘机行业运营模式及市场供需预测报告2022-2028年
  17. uvm 糖果爱好者 subscriber调用parent方法解读
  18. 自学篇之如何高效地学习网络安全
  19. 百田游戏策划面试经验
  20. Ubuntu 22.04 LTS 入门安装配置优化、开发软件安装一条龙

热门文章

  1. python动物重量排序_用python画简单的动物代码
  2. 二维Otsu算法的原理与实现
  3. window的pageX,pageY,screenX,sreenY,clientX,clientY的区别描述
  4. 盈建科弹性板6计算_YJK计算参数( 注释)20171011
  5. 计算机毕设Python+Vue用户体验的线上租房系统(程序+LW+部署)
  6. 世界国家,省市区,四级联动前台代码以及json数据
  7. 游险理赔项目有哪些?
  8. Android中需要知道的蓝牙相关常识
  9. nginx 启动关闭命令
  10. 小白如何从零开始运营一个微信公众号?