(1)变量的域

  要了解闭包需要先了解变量的域,也就是变量在哪一段“上下文”是有效的(类似局部变量和全局变量的区别),举一个很简单的例子。(例子不重要,就是涉及闭包就要时刻关注这个域)

 def test():
msg2 = 'test中的'
print('====',msg1) # ==== 非test中的
msg1 = '非test中的'
test()
print(msg1) # 非test中的
print(msg2) # 报错

  

(2)什么是闭包

  维基百科定义:闭包(Closure)或闭包函数(function Closure),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。

  定义可以反复体会,先看一个比较有意思的例子:

 def test():
msg = '我是test中的'
def test2():
print(msg)
return test2
g = test()
g() # 我是test中的

  这段代码执行到第七行的时候,输出了msg的内容。

  我们在对比【(1)变量的域】中的代码例子,那个例子中,同样是第七行的时候是报错,因为很好理解,上一个例子msg2已经脱离了test()函数,也就是局部变量只能在内部使用,不能够全局使用。

  然后回到这个例子,这就是闭包存在的意义,我们可以在外部访问局部变量。闭包就是:函数+上下文。注意到我这个例子第五行返回的是test2,是一个函数对象(in Python everything is an object )。这里的 g 就是闭包。而我所说的上下文:就是各种变量环境。所以第七行的return,返回的function不是普通function,是带着上下文环境一起的(也就是test2() 函数中带有msg,而msg其实实在test()中定义的,但是也会被test2()带在身边)。不单单只返回第三第四行两行简单的内容。

(3)闭包疑点

  我们再看几个 stockoverflow和 官网上的几个关于闭包的例子与疑点:

 1.例子一

 adders=[0,1,2,3]

 for i in [0,1,2,3]:
adders[i]=lambda a: i+a print(adders[1](3)) #

  这个里之中adders列表存储了匿名函数,adders[1](3) 就是访问adders[1] 中的匿名函数,参数是3,也就是lambda a:i+a(3传递给a,i 是for...in 循环给的,计算结果是 i + a)。

  奇怪的是结果adders[1](3) = 6.我们可能会想应该是4阿,1 + 3 = 4。

  我的理解是这样的:因为我们需要注意这里的 i 到底是属于谁的,i 是在 for...in 中定义的,一个循环至始至终只有一个 i ,也就是  i 的引用是不变的,变得是 i 得值,所以lambda中的 i ,adders[0],adders[1]....中的 i 都是指向同一个 i ,而最后 i 是三。adders[0,1,2,3] 中的 lambda 匿名函数的参数 i 全都是同一个,这个 i 因为循环最终值是3.  所以3+3=6.(也就是 i 是什么时候定义的?这个问题考虑好,是在调用lambda之前,也就是for循环开始的时候定义好的)

  改进方案:

 adders=[0,1,2,3]

 for i in [0,1,2,3]:
adders[i]=lambda a, b = i: b+a print(adders[0](3)) #
print(adders[1](3)) #
print(adders[2](3)) #
print(adders[3](3)) #

  那我们就在lambda之中定义一个b,这个b是记录i,但是adders[ ....] 数组中的 b 是各不相同的引用哦。

2.例子二

 squares = []
for x in range(5):
squares.append(lambda: x**2) print(squares[2]()) #
print(squares[3]()) #

  情况一模一样。最后全都算 4 *4 = 16。改进如下:

 squares = []
for x in range(5):
squares.append(lambda b = x: b**2) print(squares[2]()) #
print(squares[3]()) #

  

Python基础(五)——闭包与lambda的结合的更多相关文章

  1. python基础之闭包函数和装饰器

    补充:全局变量声明及局部变量引用 python引用变量的顺序: 当前作用域局部变量->外层作用域变量->当前模块中的全局变量->python内置变量 global关键字用来在函数或其 ...

  2. python基础16_闭包_装饰器

    不了解是否其他语言也有类似 python 装饰器这样的东西. 最近才发现ECMAScript6也是有生成器函数的,也有 yield  generator 装饰器的基础知识是闭包: # 闭包:嵌套函数, ...

  3. 【笔记】Python基础五:装饰器

    一,什么是装饰器 本质就是函数,功能是为其他函数添加附加功能 原则: 1,不修改被修饰函数的源代码 2,不修改被修饰函数的调用方式 例子: import time def timmer(func): ...

  4. Python基础(五) python装饰器使用

    这是在Python学习小组上介绍的内容,现学现卖.多练习是好的学习方式. 第一步:最简单的函数,准备附加额外功能 # -*- coding:gbk -*- '''示例1: 最简单的函数,表示调用了两次 ...

  5. python基础五

    列表生成式 将列表data=[1,2,3]里的元素都乘2 方法一 data=[1,2,3] for index,i in enumerate(data): data[index] *=2 print( ...

  6. Python基础三. 函数、lambda、filter、map、reduce

    一.概述 函数, 就是用一些语句组织起来实现一组特定的功能, 用来重复调用. 函数的作用及意义:最大化的重用代码和最小化的代码冗余以及对流程的分解. Python中有哪些函数: 内建的函数 第三方模块 ...

  7. Python基础(7)闭包函数、装饰器

    一.闭包函数 闭包函数:1.函数内部定义函数,成为内部函数, 2.改内部函数包含对外部作用域,而不是对全局作用域名字的引用 那么该内部函数成为闭包函数 #最简单的无参闭包函数 def func1() ...

  8. Python基础(七) 闭包与装饰器

    闭包的定义 闭包是嵌套在函数中的函数. 闭包必须是内层函数对外层函数的变量(非全局变量)的引用. 闭包格式: def func(): lst=[] def inner(a): lst.append(a ...

  9. Python基础总结之认识lambda函数、map函数、filter() 函数。第十二天开始(新手可相互督促)

    今天周日,白天在学习,晚上更新一些笔记,希望对大家能更好的理解.学习python~ lambda函数,也就是大家说的匿名函数.它没有具体的名称,也可以叫做一句话函数,我觉得也不过分,大家看下代码,来体 ...

  10. Python基础编程闭包与装饰器

    闭包的定义 闭包是嵌套在函数中的函数. 闭包必须是内层函数对外层函数的变量(非全局变量)的引用. 闭包格式: def func(): lst=[] def inner(a): lst.append(a ...

随机推荐

  1. hdu1166-敌兵布阵-分块

    把区间分成√n份降低复杂度. #include<bits/stdc++.h> #define inf 0x3f3f3f3f ; ; using namespace std; int t,n ...

  2. 078 Subsets 子集

    给定一组不同的整数 nums,返回所有可能的子集(幂集).注意事项:该解决方案集不能包含重复的子集.例如,如果 nums = [1,2,3],结果为以下答案:[  [3],  [1],  [2],  ...

  3. SSIS-Dtsx包文件打开时一直验证

    把每个项的DelayValidation设置为true. 也可以直接改文件: 把文件里的 <DTS:Property DTS:Name="DelayValidation"&g ...

  4. C#入门笔记3 表达式及运算符2

    关系运算符,也称布尔比较运算符 注:var1为bool类型,var2与var3可以是其它类型.[数据类型看下一节] 运算符 类别 示例表达式 结果说明 == 二元 var1=var2==var3 如果 ...

  5. Netty之WebSocket和四种IO介绍

    Netty简介 一.什么是netty? 高性能 事件驱动 异步非堵塞 基于NIO的客户端,服务器端编程框架 稳定性和伸缩性 二.Netty的使用场景 高性能领域   多线程并发领域   异步通信领域 ...

  6. css3Transitions 实现的鼠标经过图标位移、旋转、翻转、发光、淡入淡出等多种特效

    HTML如下:   1 <div class="container"> 3 <!--特效1 --> <section id="set-1&q ...

  7. GreenDao的简单使用说明(五)多表n:m

    在设计一些比较复杂的数据库结构的时候,我们会遇到表之间是n:m的关系,就是常说的多对多的关系,最常用的情况,就是用户权限这块,日常最常见的就是学生与老师的关系了,哪么我们来看一下GreenDao中如何 ...

  8. EF6 CodeFirst连接MySql 报nvarchar('max')错误解决办法

    1.在DBContext类加标签[DbConfigurationType(typeof(MySql.Data.Entity.MySqlEFConfiguration))] 2.在Nuget控制台输入u ...

  9. 数据库迁移后报错提示MySQL Error:Can''t find file errno: 13 - Permission denied的解决方法

    用户MYSQL数据库迁移后,遇到报错MySQL Error:Can't find file (errno: 13 - Permission denied)使用以下指令重新设置所有者和权限,依然不能解决 ...

  10. sqlserver创建触发器

    Create TRIGGER [dbo].[tr_Delete_AllocationedDN] --删除指定账户已分配未拣货的任务 ON [dbo].[FRU_PickLocationNew] --触 ...