`
idning
  • 浏览: 139392 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[转]Python闭包的改进 - 很好的分析,之前自己不懂.

 
阅读更多

Python也支持闭包,但在Python3.0以前,闭包不能访问外部函数中的局部变量。Python3.0为此引入了nonlocal关键字,从而完善了闭包访问外部变量的机制。

在Python2.6中,如果像下面这样定义函数:

1 >>> def outerFun():
2     outerVar = 0
3     def innerFun():
4         outerVar += 1
5     print outerVar
6     return innerFun

然后,调用outerFun返回的闭包,会导致错误:

1 >>> f = outerFun()
2 >>> f()
3  
4 Traceback (most recent call last):
5   File "<pyshell#15>", line 1in <module>
6     f()
7   File "<pyshell#12>", line 4in innerFun
8     outerVar += 1
9 UnboundLocalError: local variable 'outerVar' referenced before assignment

把错误消息“UnboundLocalError: local variable ‘outerVar’ referenced before assignment”翻译成中文,就是“未绑定局部变量:引用局部变量’outerVar’之前没有赋值”。啥意思呢?在内部函数innerFun中,outerVar被Python解释器看成是内部函数innerFun中的局部变量,并不是我们认为的外部(函数outerFun中的)变量。即在innerFun中,outerVar只是一个尚未赋值的变量——尽管与外部的outerVar同名,因此不能执行加法计算。Python3.0以前的版本提供了global关键字,通过这个关键字能够在函数内部引用并重新绑定(修改)全局变量:

1 >>> x = 1
2 >>> def c():
3     global x
4     += 1
5     print x
6  
7 >>> c()
8 2


这里通过global关键字在函数c的局部作用域中引用了全局变量x,因此就可以重新绑定(修改)全局变量了。虽然能访问和修改全局变量,但还是不能解决闭包访问外部函数变量的问题。为此,Python3.0增加了一个新关键字——nonlocal,用于在嵌套函数中访问外部变量:

01 >>> def outerFun():
02     outerVar = 0
03     def innerFun():
04         nonlocal outerVar   # 使用nonlocal引用外部函数变量
05         outerVar += 1
06         print(outerVar) # 注意,print在Python3.0中是函数,不是语句
07     return innerFun
08  
09 >>> f = outerFun()
10 >>> f()
11 1
12 >>> f()
13 2

而且,此时的外部变量对于内部的函数而言是共享的:

01 >>> def outerFun():
02     outerVar = 0
03     def innerFun():
04         nonlocal outerVar
05         outerVar += 1
06         print(outerVar)
07     def innerFun2():
08         nonlocal outerVar
09         outerVar *= 2
10         print(outerVar)
11     return [innerFun,innerFun2] # 通过列表返回两个函数
12  
13 >>> ff = outerFun()
14 >>> ff[0]()
15 1
16 >>> ff[1]()
17 2
18 >>> ff[1]()    # 连续调用两次innerFun2
19 4
20 >>> ff[0]()    # 结果表明,两个闭包共享同一个变量
21 5

关于这一点改进的详细内容,请参见PEP(Python Enhancement Proposals,Python改进建议)3104:Access to Names in Outer Scopes

分享到:
评论

相关推荐

    python-3.7.8-amd64.zip

    10. **安装过程**:"python-3.7.8-amd64.exe"安装程序会引导用户完成Python的安装,包括选择安装路径、设置环境变量、选择是否将Python添加到系统路径等选项,使用户能够轻松定制自己的Python环境。 总之,"python-...

    python-3.7.3-amd64_安装包.zip

    此外,它还支持了非本地(nonlocal)关键字的改进,使得在嵌套函数或闭包中更方便地修改外部变量。 2. **类型注解**:Python 3.7增强了类型提示(type hints)的功能,允许开发者在代码中指定变量、参数和返回值的...

    Python-100-Days-master.zip

    11. **数据分析和可视化**:使用pandas进行数据清洗和分析,matplotlib或seaborn进行数据可视化,这对于数据科学家和分析师来说是必不可少的技能。 12. **Web开发**:了解基础的Web框架如Flask或Django,构建简单的...

    Python学习笔记--皮大庆.pdf.zip

    3. **列表、元组、字典与集合**:这些是Python的主要数据结构,列表是可变序列,元组是不可变序列,字典是键值对的集合,集合则是一组不重复的元素。理解它们的特点和操作方法,如索引、切片、增删改查、迭代等。 4...

    python-2.7.15.amd64

    4. **语法改进**:Python 2.7引入了一些3.x系列的新语法特性,比如非本地(nonlocal)关键字,使得在嵌套函数或闭包中修改外部变量变得可能。 5. **异常处理**:Python 2.7 使用`raise`语句可以抛出自定义异常,并...

    Python闭包实例closure.py

    Python闭包实例closure.py 简单示例闭包的使用 简单示例闭包的使用

    python教程马哥-60集全全新马哥教育运维必备python基础语法全讲解-IT教程网....pdf

    《Python基础语法全讲解》是马哥教育推出的一套60集完整的Python教程,专为运维人员设计,旨在提供全面的Python基础知识。本教程涵盖了从Python编程语言的初识、编程环境的准备到高级特性的深入理解,为学习者打造了...

    python-3.7.4-docs-html.zip

    Python 3.7.4 的官方文档是一个非常重要的资源,为开发者提供了详尽的指导和信息,涵盖了语言的所有方面。这个压缩包“python-3.7.4-docs-html.zip”包含了HTML格式的文档,方便在网页浏览器中浏览,使得学习和查阅...

    python高阶闭包练习题

    Python是一种强大的、面向对象的编程语言,其简洁的语法和丰富的库使得它在各种领域都有广泛应用,包括Web开发、数据分析、人工智能等。在Python的世界里,"高阶闭包"是一个高级概念,对于理解函数的内部工作原理和...

    python自学教程-19-修改全局变量.ev4.rar

    此外,Python还有另一种名为`nonlocal`的关键字,用于在嵌套函数(如闭包)中引用或修改外部函数的变量,但不是全局变量。`nonlocal`变量的作用域仅限于包含它的那个函数,比全局变量的作用域小。 总的来说,理解并...

    python自学教程-10-函数嵌套调用.ev4.rar

    通过学习这个主题,你可以更好地理解和掌握Python中的函数组织技巧,提升代码的可读性和复用性。 函数嵌套是指在一个函数内部定义另一个函数。这种结构允许内层函数访问外层函数的所有局部变量,但外部函数无法直接...

    python-3.7.9-docs-pdf.zip

    8. **Python 3.7.9 特有的更新**:这个版本可能有特定的新特性和改进,比如增强型赋值运算符、非本地跳转、类型注解的改进等,文档会专门说明这些变化。 9. **错误和异常**:包括 Python 中的常见错误类型和异常...

    python-3.7.7-amd64.rar

    2. **非局部关键字**:Python3.7新增了`nonlocal`关键字,用于在内嵌函数或闭包中修改外层但不是全局作用域的变量,这对于编写复杂逻辑的函数和类很有用。 3. **f-string**:f-string是一种新的字符串格式化方法,...

    Python入门教程-超详细1小时学会Python.rar_Python 入门_Python入门_python_python

    面向对象编程在Python中也得到了很好的支持。你可以定义类(class),创建对象实例,实现继承、封装和多态。理解类和对象的区别,以及如何使用它们来解决问题,是Python编程的关键。 异常处理是Python中处理错误和...

    数据库-属性闭包代码-python

    数据库老师要求用代码实现求属性闭包,该代码为python代码,注释详细

    (python3.8.5中文手册)python-3.8.5-docs-html.zip

    通过阅读这份Python 3.8.5中文手册,开发者不仅可以掌握Python的基本知识,还能了解到该版本的最新特性,从而更好地利用Python进行软件开发。同时,手册中的示例代码和详细的解释有助于加深理解和提高实践能力。无论...

    python-2.7.9-docs-html.zip

    Python 2.7.9 文档是学习 Python 编程语言的重要资源,尤其对于初学者而言,它提供了全面且详细的指南。这个压缩包包含了 HTML 格式的文档,使得用户可以像浏览网页一样轻松地查阅和搜索相关知识。 Python 2.7.9 是...

Global site tag (gtag.js) - Google Analytics