Python闭包及其作用域
Python闭包及其作用域
关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记
如果在一个内部函数里,对一个外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被称为闭包(closure),而这个被内部函数引用的变量则被成为自由变量
闭包和函数调用没多少相关,而是关于使用定义在其他作用域的变量
命名空间和作用域
我们把命名空间看做一个大型的字典类型(Dict),里面包含了所有变量的名字和值的映射关系。在 Python 中,作用域实际上可以看做是“在当前上下文的位置,获取命名空间变量的规则”。在 Python 代码执行的任意位置,都至少存在三层嵌套的作用域:
- 最内层作用域,最先搜索,包含所有局部变量(Python 默认所有变量声明均为局部变量)
- 所有包含当前上下文的外层函数的作用域,由内而外依次搜索,这里包含的是非局部也非全局的变量
- 一直向上搜索,直到当前模块的全局变量
- 最外层,最后搜索的,内置(built-in)变量
scopes = {
"local": {"locals": None,
"non-local": {"locals": None,
"global": {"locals": None,
"built-in": ["built-ins"]}}},
}
除了默认的局部变量声明方式,Python还有global和nonlocal两种类型的声明(nonlocal是Python3.x之后才有的),其中nonlocal是指最内层之外,global以内的变量。必须强调的是,最内层局部作用域对外层作用域的变量只有只读(read-only)的访问权限。比如下列的例子
x = 100
def main():
x += 1
print (x)
main()
---------------------------------------------------------------------------
UnboundLocalError Traceback (most recent call last)
<ipython-input-2-9ed43e483a17> in <module>()
3 x += 1
4 print(x)
----> 5 main()
<ipython-input-2-9ed43e483a17> in main()
1 x = 100
2 def main():
----> 3 x += 1
4 print(x)
5 main()
UnboundLocalError: local variable 'x' referenced before assignment
这里抛出UnboundLocalError,是因为main()函数内部的作用域对于全局变量x仅有只读权限,想要在main()中对x进行改变,不会影响全局变量,而是会创建一个新的局部变量,显然无法对还未创建的局部变量直接使用x += 1, 因为x未绑定到任何对象上。如果想要获得全局变量的完全引用,则需要global声明:
x = 100
def main():
global x
x += 1
print(x)
main()
print(x) # 全局变量已被改变
# result:
# 101
# 101
闭包
闭包和函数调用没多少相关,而是关于使用定义在其他作用域的变量。
看了上面的Python作用域规则后,我们可以仿照JavaScript写一个计数器的闭包:
"""
/* JavaScript Closure example */
var inc = function(){
var x = 0;
return function(){
console.log(x++);
};
};
var inc1 = inc()
var inc2 = inc()
"""
# Python
def inc():
x = 0
def inner():
nonlocal x
x += 1
print(x)
return inner
inc1 = inc()
inc2 = inc()
inc1()
inc1()
inc1()
inc2()
# result:
# 1
# 2
# 3
# 1
在这里,全局环境下不能获取到inc()中的局部变量x的,但是我们返回了inc()内部函数inner(),而inner()对inc()中的局部变量是有访问权限的。也就是说inner()将inc()局部作用域打包发送给了inc1和 inc2,从而使他们各自独立拥有了一块封闭起来的作用域,不受其他运行环境和全局变量的影响,因此称之为闭包。
上述代码中inc1和inc2各自有一块封闭起来的作用域,可以通过Online Python Tutor 可视化运行工具看相应的运行结果

Python闭包及其作用域的更多相关文章
- Python函数的作用域规则和闭包
作用域规则 命名空间是从名称到对象的映射,Python中主要是通过字典实现的,主要有以下几个命名空间: 内置命名空间,包含一些内置函数和内置异常的名称,在Python解释器启动时创建,一直保存到解释器 ...
- python命名空间、作用域、闭包与传值传引用
(以下内容,均基于python3) 最近在看python函数部分,讲到了python的作用域问题,然后又讲了Python的闭包问题. 在做作业的时候,我遇到了几个问题,下面先来看作业. 一. 作业1: ...
- Python 闭包
什么是闭包? 闭包(closure)是词法闭包(lexical closure)的简称.闭包不是新奇的概念,而是早在高级程序语言开始发展的年代就已产生. 对闭包的理解大致分为两类,将闭包视为函数或者是 ...
- Python闭包及装饰器
Python闭包 先看一个例子: def outer(x): def inner(y): return x+y return innder add = outer(8) print add(6) 我们 ...
- Python闭包详解
Python闭包详解 1 快速预览 以下是一段简单的闭包代码示例: def foo(): m=3 n=5 def bar(): a=4 return m+n+a return bar >> ...
- 详解python命名空间和作用域
1.典型案例 先从几个典型的案例来看下名称空间及作用域对python代码运行的影响,请看下面几个代码实例及其执行结果,是否符合你的预期. 代码1:块作用域 if True: i = 1 print i ...
- Python 闭包小记
闭包就是能够读取其他函数内部变量的函数.例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“.在本质上,闭包是将函数内部和函数外部连接起来 ...
- Python 闭包(Closure)
Python 闭包 (Closure) 这里介绍一下python 的闭包 基本概念 闭包(closure)是函数式编程的重要的语法结构. 函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函 ...
- python闭包和装饰器(转)
一.python闭包 1.内嵌函数 >>> def func1(): ... print ('func1 running...') ... def func2(): ... prin ...
随机推荐
- Android对话框和帧动画
Android对话框 在一个例子中展示四种对话框. 设置四个按钮 <LinearLayout xmlns:android="http://schemas.android.com/apk ...
- HDU 6043 KazaQ's Socks (规律)
Description KazaQ wears socks everyday. At the beginning, he has nn pairs of socks numbered from 11 ...
- rocketmq client for c#
基于ikvm的rocketmq的c#客户端,由于阿里对c#不敏感,对这方面的东西缺少.因为工作需要弄了一个,分享给大家 https://github.com/franknew/RocketMQ-Cli ...
- Spring+SpringMVC+MyBatis+easyUI整合进阶篇(二)RESTful API实战笔记(接口设计及Java后端实现)
写在前面的话 原计划这部分代码的更新也是上传到ssm-demo仓库中,因为如下原因并没有这么做: 有些使用了该项目的朋友建议重新创建一个仓库,因为原来仓库中的项目太多,结构多少有些乱糟糟的. 而且这次 ...
- 初学Python之 字符串 索引 分片
字符串是字符的有序集合,可以通过其位置来获得具体的元素. 在python中,字符串中的字符是通过索引来提取的,索引从0开始. python可以取负值,表示从末尾提取,最后一个为-1,倒数第二个为-2, ...
- Jsp分页的简单制作
Jsp分页的简单制作 运行环境:jsp+tomcat+eclipse 技术:servlet+jsp+mysql 分页技术还区分两个:假分页和真分页 假分页:一次性从数据库读出表的所有数据一次性的返回给 ...
- 用ubuntu的grpb2引导Remix OS
Remix OS游戏版,这里下载:http://youxi.jide.com/ 安装简单.我这里要解决的是安装后用ubunu的grub2菜单去引导它. 方法如下: 进入ubuntu系统里修改其grub ...
- 如何做到 Laravel 配置可以网站后台配置【社交系统ThinkSNS+研发日记四】
距离上一次分享差不多一周了,本文分享下利用 Laravel 的 Bootstrapping 达到网站后台设置 laravel 配置. 需求场景 首先,ThinkSNS+ 作为一个用户可以使用的「社交系 ...
- oracle监控脚本【转】
1. 监控事例的等待 select event,sum(decode(wait_Time,0,0,1)) "Prev", sum(decode(wait_Time,0,1,0)) ...
- 关于mysql增删改查的基本操作
1.注释语法:--,#2.后缀是.sql的文件是数据库查询文件3.保存查询4.在数据库里面 列有个名字叫字段 行有个名字叫记录CRUD操作:create 创建(添加)read 读取update 修 ...