Python:闭包
闭包(Closure)
在一个函数内部定义另一个函数,然后内部函数用到外部函数的变量,把内部函数以及用到的外部变量,合称闭包。
首先复习一下
命名空间与作用域
我们可以把命名空间看做一个大型的字典类型(Dict),里面包含了所有变量的名字和值的映射关系。在 Python 中,作用域实际上可以看做是“在当前上下文的位置,获取命名空间变量的规则”。在 Python 代码执行的任意位置,都至少存在三层嵌套的作用域:
- local 最内层作用域,最早搜索,包含所有局部变量**(Python 默认所有变量声明均为局部变量)**
- non-local 所有包含当前上下文的外层函数的作用域,由内而外依次搜索,这里包含的是非局部也非全局的变量
- global 一直向上搜索,直到当前模块的全局变量
- built-in 最外层,最后搜索的,内置(built-in)变量
在任意执行位置,可以将作用域看成是对下面这样一个命名空间的搜索:
scopes = |
除了默认的局部变量声明方式,Python 还有global
和nonlocal
两种类型的声明(nonlocal
是Python 3.x之后才有,2.7没有),其中 global
指定的变量直接指向(3)当前模块的全局变量,而nonlocal
则指向(2)最内层之外,global
以内的变量。这里需要强调指向(references and assignments)的原因是,普通的局部变量对最内层局部作用域之外只有**只读(read-only)**的访问权限,比如下面的例子:
>>>x = 100 #该全局变量可被所有函数调用
>>def main():
x += 1
print(x) >>>main()
Traceback (most recent call last):
File "<pyshell#50>", line 1, in <module>
main()
File "<pyshell#49>", line 2, in main
x += 1
UnboundLocalError: local variable 'x' referenced before assignment
这里抛出UnboundLocalError
,是因为main()
函数内部的作用域对于全局变量x
仅有只读权限,想要在main()
中对x
进行改变,不会影响全局变量,而是会创建一个新的局部变量,显然无法对还未创建的局部变量直接使用x += 1
。如果想要获得全局变量的完全引用,则需要global
声明:
>>>x = 100
>>>def main():
global x
x += 1
print(x) >>>main()
print(x) # 全局变量已被改变,后面的全局变量x都为101
101
Python闭包
demo:
# 外部函数
def fun():
print('outer')
# 内部函数
def fun_in():
print('inner')
return fun_in # 调用外部函数
fun()
a = fun()
print(a)
# 调用内部函数
a() # 输出结果
outer
<function fun.<locals>.fun_in at
inner
再写个闭包调用时机的小例子
def fun():
print('---1---')
def fun_in():
print('---2---')
print('---3---')
return fun_in # 注意没有小括号 # fun()
# 输出结果
# ---1---
# ---3--- # 调用 fun_in才输出---2---
a = fun()
print('-------')
a() #输出结果
---1---
---3---
-------
---2---
闭包在内存中的状态
在python函数的使用里,当函数调用结束后,函数对应的内存空间被释放,里面所有东西都被清空
但在闭包中例外,因为函数里面还有东西(内部函数)被引用了。因此外部函数的空间就没被释放(涉及到python回收机制的知识:引用计数)
如果再次调用这个函数,就还会重新生成一份新的内存空间
def fun(number):
def fun_in(number_in):
print('number = %d, number_in = %d' % (number, number_in))
return number + number_in
return fun_in a1 = fun(3)
print(a1(8)) # 11 = 3 + 8 a2 = fun(5)
print(a2(8)) # 13 = 5 + 8 print(a1(9)) # 12 = 3 + 9 print(a2(9)) # 14 = 5 + 9
所以,当通过a1去调用内部函数,和通过a2去调用内部函数的时候,实际上是在不同的内存空间上去跑的。
Python:闭包的更多相关文章
- Python 闭包
什么是闭包? 闭包(closure)是词法闭包(lexical closure)的简称.闭包不是新奇的概念,而是早在高级程序语言开始发展的年代就已产生. 对闭包的理解大致分为两类,将闭包视为函数或者是 ...
- Python闭包与函数对象
1. Python闭包是什么 在python中有函数闭包的概念,这个概念是什么意思呢,查看Wikipedia的说明如下: “ In programming languages, closures (a ...
- 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闭包及其作用域
Python闭包及其作用域 关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域 ...
- Python 闭包小记
闭包就是能够读取其他函数内部变量的函数.例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“.在本质上,闭包是将函数内部和函数外部连接起来 ...
- 理解Python闭包概念
闭包并不只是一个python中的概念,在函数式编程语言中应用较为广泛.理解python中的闭包一方面是能够正确的使用闭包,另一方面可以好好体会和思考闭包的设计思想. 1.概念介绍 首先看一下维基上对闭 ...
- Python闭包举例
Python闭包的条件: 1.函数嵌套.在外部函数内,定义内部函数. 2.参数传递.外部函数的局部变量,作为内部函数参数. 3.返回函数.外部函数的返回值,为内部函数. 举例如下: def line_ ...
- python 闭包和装饰器
python 闭包和装饰器 一.闭包闭包:外部函数FunOut()里面包含一个内部函数FunIn(),并且外部函数返回内部函数的对象FunIn,内部函数存在对外部函数的变量的引用.那么这个内部函数Fu ...
- Python 闭包(Closure)
Python 闭包 (Closure) 这里介绍一下python 的闭包 基本概念 闭包(closure)是函数式编程的重要的语法结构. 函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函 ...
随机推荐
- NetBpm XML解读(5)
原文: nPdl的翻译 在看NetBPM的nPdl文档时做了个翻译,一来是让自己能更好的理解nPdl,二来是希望能得到关心NetBPM的同志的指导. 由于对工作流不熟悉,所以有不少术语翻译没有把 ...
- GreenPlum数据加载
1. copy命令 对于数据加载,GreenPlum数据库提供copy工具,copy工具源于PostgreSQL数据库,copy命令支持文件与表之间的数据加载和表对文件的数据卸载.使用copy命令进行 ...
- scala中隐式转换之隐式转换调用类中本不存在的方法
/** * Created by root * Description : 隐式转换调用类中本不存在的方法 */ class Person(name : String){ def getPersonN ...
- 查找被占用的端口的服务并kill掉
转自:http://blog.csdn.net/gsls200808/article/details/52456136 方法: C:\>netstat -ano|findstr 8000 TCP ...
- 【RF库XML测试】Get Element Text
Name:Get Element TextSource:XML <test library>Arguments:[ source | xpath=. | normalize_whitesp ...
- 系统日志:/var/log/messages
/var/log/messages 存放的是系统的日志信息,它记录了各种事件,基本上什么应用都能往里写日志,在做故障诊断时可以首先查看该文件内容 [root@mirh5_center1_111.231 ...
- redis 缓存类型为map
// 获取分类列表,以及同类品牌 public Map<String, List> getCatalogInfo(Product product) { String key = Cache ...
- 日记整理---->2017-05-14
学习一下知识吧,好久没有写博客了.如果他总为别人撑伞,你又何苦非为他等在雨中. 学习的知识内容 一.关于base64的图片问题 byte[] decode = Base64.base64ToByteA ...
- 【Spring源码分析系列】结构组成和容器的基本实现
beans包的层级结构 src/main/java:用于展现Spring的主要逻辑 src/main/resources:用于存放系统的配置文件 src/test/java:用于对主要逻辑单元进行测试 ...
- linux strace 命令详解
简介 strace常用来跟踪进程执行时的系统调用和所接收的信号. 在Linux世界,进程不能直接访问硬件设备,当进程需要访问硬件设备(比如读取磁盘文件,接收网络数据等等)时,必须由用户态模式切换至内核 ...