热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python教程分享Python中闭包和自由变量的使用与注意事项

1.定义在函数内部再定义一个函数,并且这个函数用到了外部函数的变量(legb),最后返回新建函数的函数名索引,那么将这样的能够访问其定义时所在的作用域的函数以及用到的一些变量称之为

1.定义

在函数内部再定义一个函数,并且这个函数用到了外部函数的变量(legb),最后返回新建函数的函数名索引,那么将这样的能够访问其定义时所在的作用域的函数以及用到的一些变量称之为闭包。被引用的非全局变量也称为自由变量 。这个自由变量保存在外部函数的只读属性 __closure__ 中,会与内层函数产生一个绑定关系,也就是自由变量将不会在内存中轻易消失。如下例所示:

2.nonlocal 关键字

上面代码中的 cnt 变量是一个列表,可变对象,但如果是不可变对象,如:numer、tuple 等呢?

以上实例输出结果:

可以看出,此时 cnt 不再是自由变量,而是变成了局部变量,且提示 unboundlocalerror 未绑定局部错误。为什么不是自由变量了呢?为什么列表就没问题呢?

这是因为 python 中并没有要求先声明一个变量才能使用它,python 解释器认为:在函数体内,只要对一个变量进行赋值操作,那么这个变量就是局部变量。
python的模块代码执行之前,并不会经过预编译,模块内的函数体代码在运行前会经过预编译,因此不管变量名的绑定发生在作用域的那个位置,都能被编译器知道。

而 cnt += 1 相当于 cnt = cnt + 1,对 cnt 进行了赋值操作,所以 python 解释器认为 cnt 是函数内的局部变量,但是执行的时候,先执行 cnt+1 时发现:
因为先前已经认定 cnt 为局部变量了,现在在局部作用域内找不到 cnt 的值,也不会再到外部作用域找了,就会报错。所以说现在 cnt 已经不是自由变量了。

那么 tuple 类型的 cnt 呢?首先 cnt[0] = cnt[0] + 1,虽然有赋值,但是其左边也是 cnt[0],cnt 是从外边作用域索引了的。
所以,你看它显示的结果:此时,cnt 确实也是自由变量的,但是它是不可变对象啊,所以报了 typeerror 错误。这下列表为什么行,你应该知道了。

或者你使用 nonolocal 关键字,这个关键字的用法与 global 很像,让你能够给外部作用域(非全局作用域)内的变量赋值。它可以使得一个被赋值的局部变量变为自由变量,并且 nonlocal声明的变量发生变化时,__closure__中存储的值也会发生变化:

nonlocal 和 global

3.注意事项

lambda 自由参数之坑,特别是和列表解析或for循环结合使用时。lambda para_list : expression == > def (para_list): return expression

首先,case1 和 case3 显然都是每循环一次,就添加一个 lambda 函数到列表中,不同的是,case1 添加的 lambda 函数中的 i 每次并没有接收 for 循环中 i 的值,它只是定义的时候指了下 i,所以说,case1 中的几个 lambda 函数的 i,是最后调用的时候,也就是 f(2) 时才到外层作用域找它的值的,此时找到的 i 的值就是里面 for 循环结束时的 i 的值。case3 则是一开始定义、添加的时候就给 i 赋好了初值。case2 则是因为 map 每次迭代的时候都会将一个可迭代对象的元素传给了 i,所以 case2 里面的每个 lambda 函数的 i 也是各有各的值的。

像这种 lambda 的自由参数的问题的话,如果你不是故意这么做的话,还是转为默认参数的好:

另外,就是列表解析里面的作用域是一个全新的作用域,和普通的 for 循环则有所不同:

4.使用场景

  • 装饰器

  • 惰性求值,比较常见的是在数据库访问的时候,可参考 django 的 queryset 的实现

  • 需要对某个函数的参数提前赋值的情况;当然也可以使用 functools.parial 的偏函数:functools.partial(func, *args, **kw),返回一个 partial 函数对象。

简单总结functools.partial的作用就是:其能把一个函数的某些参数给固定住(也就是设置默认值),并返回一个新的函数,调用这个新函数会更简单。

总结

到此这篇关于python中闭包和自由变量的文章就介绍到这了,更多相关python闭包和自由变量内容请搜索<编程笔记>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<编程笔记>!

需要了解更多python教程分享Python中闭包和自由变量的使用与注意事项,都可以关注python教程分享栏目&#8212;编程笔记


推荐阅读
  • 在Ubuntu系统中配置Python环境变量是确保项目顺利运行的关键步骤。本文介绍了如何将Windows上的Django项目迁移到Ubuntu,并解决因虚拟环境导致的模块缺失问题。通过详细的操作指南,帮助读者正确配置虚拟环境,确保所有第三方库都能被正确识别和使用。此外,还提供了一些实用的技巧,如如何检查环境变量配置是否正确,以及如何在多个虚拟环境之间切换。 ... [详细]
  • 深入解析 Django 中用户模型的自定义方法与技巧 ... [详细]
  • Python Flask学习之安装SQL,python3,Pycharm(网上下载安装即可)
    1,下载时更改pypi源。可以额外安装虚拟化环境:pipinstall-ihttp:pypi.douban.comsimple--trusted-hos ... [详细]
  • 深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案
    深入剖析Java中SimpleDateFormat在多线程环境下的潜在风险与解决方案 ... [详细]
  • 在Cisco IOS XR系统中,存在提供服务的服务器和使用这些服务的客户端。本文深入探讨了进程与线程状态转换机制,分析了其在系统性能优化中的关键作用,并提出了改进措施,以提高系统的响应速度和资源利用率。通过详细研究状态转换的各个环节,本文为开发人员和系统管理员提供了实用的指导,旨在提升整体系统效率和稳定性。 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 深入理解排序算法:集合 1(编程语言中的高效排序工具) ... [详细]
  • 本文深入解析了Java面向对象编程的核心概念及其应用,重点探讨了面向对象的三大特性:封装、继承和多态。封装确保了数据的安全性和代码的可维护性;继承支持代码的重用和扩展;多态则增强了程序的灵活性和可扩展性。通过具体示例,文章详细阐述了这些特性在实际开发中的应用和优势。 ... [详细]
  • Python内置模块详解:正则表达式re模块的应用与解析
    正则表达式是一种强大的文本处理工具,通过特定的字符序列来定义搜索模式。本文详细介绍了Python内置的`re`模块,探讨了其在字符串匹配、验证和提取中的应用。例如,可以通过正则表达式验证电子邮件地址、电话号码、QQ号、密码、URL和IP地址等。此外,文章还深入解析了`re`模块的各种函数和方法,提供了丰富的示例代码,帮助读者更好地理解和使用这一工具。 ... [详细]
  • Django框架下的对象关系映射(ORM)详解
    在Django框架中,对象关系映射(ORM)技术是解决面向对象编程与关系型数据库之间不兼容问题的关键工具。通过将数据库表结构映射到Python类,ORM使得开发者能够以面向对象的方式操作数据库,从而简化了数据访问和管理的复杂性。这种技术不仅提高了代码的可读性和可维护性,还增强了应用程序的灵活性和扩展性。 ... [详细]
  • Django新手指南:第三步——构建你的首个项目
    在本教程中,我们将引导你完成创建第一个Django应用的步骤。通过实际操作,你将逐步了解Django框架的核心概念和基本功能。从项目结构到视图和模板的实现,我们将详细介绍每个环节,帮助你快速上手并构建出一个功能完整的Web应用。 ... [详细]
  • 本文深入分析了Django框架中模型应用与非模型应用的区别与应用场景,详细对比了两者在数据处理、性能表现及开发灵活性等方面的特点。同时,文章还介绍了如何在视图函数中有效利用这些特性,结合PostgreSQL、MySQL、SQLite3和Oracle等不同数据库的配置与使用方法,为开发者提供了全面的参考指南。 ... [详细]
  • 优化Django应用中的MySQL连接池配置方法
    django设置mysql连接池 导库 pipinstalldjango-db-connection-poolsettings.py设置 将ENGINEdjango.db.back ... [详细]
  • 浅谈Python3中打开文件的方式(With open)
    浅谈Python3中打开文件的方式(With open)-目录0.背景知识1.常规方式:读取文件-----open()2.推荐方式:读取文件-----WithOpen1).读取方式 ... [详细]
  • python教程分享python单例模式之selenium driver实现单例
    一、使用装饰器实现单例二、web自动化driver实现单例模式2.1编写单例模式的装饰器2.2driver使用装饰器,实现单例模式2.3获取driver的实例,就是单例了三、在自动 ... [详细]
author-avatar
走ln方
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有