闭包(Closure)

在一个函数内部定义另一个函数,然后内部函数用到外部函数的变量,把内部函数以及用到的外部变量,合称闭包。

首先复习一下

命名空间与作用域

我们可以把命名空间看做一个大型的字典类型(Dict),里面包含了所有变量的名字和值的映射关系。在 Python 中,作用域实际上可以看做是“在当前上下文的位置,获取命名空间变量的规则”。在 Python 代码执行的任意位置,都至少存在三层嵌套的作用域:

  • local            最内层作用域,最早搜索,包含所有局部变量**(Python 默认所有变量声明均为局部变量)**
  • non-local    所有包含当前上下文的外层函数的作用域,由内而外依次搜索,这里包含的是非局部也非全局的变量
  • global         一直向上搜索,直到当前模块的全局变量
  • built-in        最外层,最后搜索的,内置(built-in)变量

在任意执行位置,可以将作用域看成是对下面这样一个命名空间的搜索:


scopes =
{
"local": {"locals": None,
"non-local": {"locals": None,
"global": {"locals": None,
"built-in": ["built-ins"]}}},
}
 

除了默认的局部变量声明方式,Python 还有globalnonlocal两种类型的声明(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:闭包的更多相关文章

  1. Python 闭包

    什么是闭包? 闭包(closure)是词法闭包(lexical closure)的简称.闭包不是新奇的概念,而是早在高级程序语言开始发展的年代就已产生. 对闭包的理解大致分为两类,将闭包视为函数或者是 ...

  2. Python闭包与函数对象

    1. Python闭包是什么 在python中有函数闭包的概念,这个概念是什么意思呢,查看Wikipedia的说明如下: “ In programming languages, closures (a ...

  3. Python闭包及装饰器

    Python闭包 先看一个例子: def outer(x): def inner(y): return x+y return innder add = outer(8) print add(6) 我们 ...

  4. Python闭包详解

    Python闭包详解 1 快速预览 以下是一段简单的闭包代码示例: def foo(): m=3 n=5 def bar(): a=4 return m+n+a return bar >> ...

  5. Python闭包及其作用域

    Python闭包及其作用域 关于Python作用域的知识在python作用域有相应的笔记,这个笔记是关于Python闭包及其作用域的详细的笔记 如果在一个内部函数里,对一个外部作用域(但不是全局作用域 ...

  6. Python 闭包小记

    闭包就是能够读取其他函数内部变量的函数.例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“.在本质上,闭包是将函数内部和函数外部连接起来 ...

  7. 理解Python闭包概念

    闭包并不只是一个python中的概念,在函数式编程语言中应用较为广泛.理解python中的闭包一方面是能够正确的使用闭包,另一方面可以好好体会和思考闭包的设计思想. 1.概念介绍 首先看一下维基上对闭 ...

  8. Python闭包举例

    Python闭包的条件: 1.函数嵌套.在外部函数内,定义内部函数. 2.参数传递.外部函数的局部变量,作为内部函数参数. 3.返回函数.外部函数的返回值,为内部函数. 举例如下: def line_ ...

  9. python 闭包和装饰器

    python 闭包和装饰器 一.闭包闭包:外部函数FunOut()里面包含一个内部函数FunIn(),并且外部函数返回内部函数的对象FunIn,内部函数存在对外部函数的变量的引用.那么这个内部函数Fu ...

  10. Python 闭包(Closure)

    Python  闭包 (Closure) 这里介绍一下python 的闭包 基本概念 闭包(closure)是函数式编程的重要的语法结构. 函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函 ...

随机推荐

  1. logback -- 配置详解 -- 四 -- <filter>

    附: logback.xml实例 logback -- 配置详解 -- 一 -- <configuration>及子节点 logback -- 配置详解 -- 二 -- <appen ...

  2. mongodb 在 Ubuntu系统上的安装及卸载

    mongodb官网 The mongodb-org-server package provides an initialization script that starts mongod with t ...

  3. Go面向对象(三)

    go语言中的大多数类型都是值予以,并且都可以包含对应的操作方法,在需要的时候你可以给任意类型增加新方法.二在实现某个接口时,无需从该接口集成,只需要实现该接口要求的所有方法即可.任何类型都可以被any ...

  4. CentOS7图形界面启动报错unable to connect to X server

    以前还可以正常启动图形界面,这次启动失败,报错unable to connect to X server 使用的是oracle用户,因为我是在oracle用户下创建的oracle数据库等 解决办法: ...

  5. NFS 简介

    一.NFS 简介 1. NFS(Network File System)网络文件系统,它允许网络中的计算机之间通过 TCP/IP 网络共享资源2. NFS 应用场景:A,B,C 三台机器上需要保证被访 ...

  6. CentOS6.5下安装Oracle11g

    一.安装前系统准备 1. 修改主机名 #sed -i "s/HOSTNAME=localhost.localdomain/HOSTNAME=oracledb.01/" /etc/s ...

  7. N76E003的学习之路(ADC简单小例程篇)

    N76E003内嵌12位逐次逼近寄存器型(SAR)的模拟数字转换器(ADC).模数转换模块负责将管脚上的模拟信号转换为12位二进制数据.N76E003支持8通道单端输入模式.内部带隙电压(band-g ...

  8. XPath的初步认识

    嘿嘿,最近开始上班,不是过于太忙,而是自己一直在学习一些项目中用到的而我暂时还没接触的知识,WCF,log4等,感觉还没有总结的需要吧,虽然都了解啦,但是暂时还是初步的学习,基础的暂时是知道啦,还没有 ...

  9. Android单例模式

    Android设计模式系列(3)--SDK源码之单例模式:http://www.cnblogs.com/qianxudetianxia/archive/2011/08/07/2130306.html ...

  10. Microsoft Security Essentials

    https://support.microsoft.com/zh-cn/help/18900/consumer-antivirus-software-providers-for-windows   适 ...