Python这么优雅的语言,我也是醉了......

事情由一段代码引发,请看:

上述的列表推导式+lambda表达式+for循环,他们碰撞出来的结果搞的人晕头转向,咱们逐步来分析一下他们到底是个什么鬼。

lambda表达式可以表示成:

def func(x):
return x*i
加上for循环:

for i in range(10):
def func(x):
return x*i
加上列表推导式:  # 注释一

到此,就可以看清楚他的结构了,funcs函数里面形成了一个闭包
闭包的两个特性:

①、内部函数使用外部函数的变量(不对外部函数的变量进行重新赋值)

②、外部函数 return 内部函数的函数名(其实是返回内部函数的内存地址)

对上面的函数进行简化:去掉for循环,使用单个变量代替,去掉 列表 li 直接返回内部函数名,它就变成了下面这个样子

简单理解:闭包 = 内部函数 + 环境变量

闭包的特性:当内部函数返回的时候,会把连同内部函数定义时候的环境变量一同返回

了解了闭包,在来看结果为什么全都是18,而不是预期结果:

①区分内部函数的定义和调用:

当我们只到是定义了外部和内部函数,调用了外部函数,并未调用内部函数,也就是到注释一

for循环的作用就是创建10个函数,最后 i 的取值是9

所以我们获得了类似下面的图谱:

当我们进行内部函数调用的时候,此时的情形是:

有一个包含10个函数的列表,变量 i=9

再加上闭包的特性,i 会随着内部函数的一同返回,所以调用依次内部函数的时候,情形就成了下面这样:以调用第1个函数为例

所以结果就成了 2 * 9 = 18

再调用别的内部函数都是如此逻辑。

知乎中此问题的回答者 @Op小剑 提到了延迟绑定

匿名函数的 i 并不是依次顺序指向0,1,2,...的,因为在迭代的过程中,创建匿名函数→创建完成后→才去找i 指向的值。

对上图做了很好的诠释

lambda不传参只有返回值的形式

当我们将表达式修改为下面的样子,预期结果就出现了:

修改到列表推导式+lambda表达式就是下面的情况:

此时调用的情形就像下面的图谱:

当列表推导式遇到lambda(匿名函数)的更多相关文章

  1. day5--装饰器函数的信息打印,迭代器,生成器,列表推导式,内置函数

    本文档主要内容: 一 装饰器函数的信息打印 二 迭代器 三 生成器 四 生成器表达式和列表推导式 五 内置函数 一 装饰器函数的信息打印 一个函数一旦被装饰器给装饰后,这个函数的信息使用原来的命令打印 ...

  2. python---基础知识回顾(一)(引用计数,深浅拷贝,列表推导式,lambda表达式,命名空间,函数参数逆收集,内置函数,hasattr...)

    一:列表和元组(引用计数了解,深浅拷贝了解) 序列:序列是一种数据结构,对其中的元素按顺序进行了编号(从0开始).典型的序列包括了列表,字符串,和元组 列表是可变的(可以进行修改),而元组和字符串是不 ...

  3. Day 14 三元运算符,列表推导式,内置函数

    三目运算符 ```python# 三目(元)运算符:就是 if...else...语法糖# 前提:简化if...else...结构,且两个分支有且只有一条语句# 注:三元运算符的结果不一定要与条件直接 ...

  4. 优雅的使用列表推导式和lambda

    按照条件过滤列表中的数据 过滤出列表中以"KLL","KBB","KHH"开头的数据 1.使用列表推导式 [orderNoOrReturnN ...

  5. Python入门之三元表达式\列表推导式\生成器表达式\递归匿名函数\内置函数

    本章目录: 一.三元表达式.列表推导式.生成器表达式 二.递归调用和二分法 三.匿名函数 四.内置函数 ================================================ ...

  6. python之三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数

    一 三元表达式.列表推导式.生成器表达式 一 三元表达式 name=input('姓名>>: ') res='SB' if name == 'alex' else 'NB' print(r ...

  7. python基础知识15---三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数

    阅读目录 一 三元表达式.列表推导式.生成器表达式 二 递归与二分法 三 匿名函数 四 内置函数 五 阶段性练习 一. 三元表达式.列表推导式.生成器表达式 1 三元表达式 name=input('姓 ...

  8. Python基础-列表推导式、匿名函数、os/sys/time/datetime/pymysql/xlwt/hashlib模块

    列表推导式 [表达式 for 变量 in range(n) if 条件]  等效于 for 变量 in in range(n): if 条件: 表达式 优点:书写方便,缺点:不易读 注意:用的是方括号 ...

  9. python之旅:三元表达式、列表推导式、生成器表达式、函数递归、匿名函数、内置函数

    三元表达式 #以下是比较大小,并返回值 def max2(x,y): if x > y: return x else: return y res=max2(10,11) print(res) # ...

随机推荐

  1. VS2013使用EF6通过ADO.NET 连接mySql成功步骤

    VS2013使用EF6通过ADO.NET 连接mySql成功步骤 1.安装mysql-for-visualstudio-1.2.6(我用的目前最新版,这个一般安装VS2013就已经有了,没有的话下载一 ...

  2. 关于下载文件封装的两个类(Mars)

    首先是文件FileUtils.java package mars.utils; import java.io.File; import java.io.FileOutputStream; import ...

  3. linux安装源文件(.tar.gz)

    安装此类文件,分为7步: 1.首先把依赖的软件给装上,如果依赖perl,先装perl,如果依赖Pathon,现装pathon 2.tar 源软件路径 -C 新软件路径(注意这里一定要-C,不然不能解压 ...

  4. dedecms会员中心编辑器无法上传图片

    文件:include\dialog\config.php 找到这行代码: $cuserLogin = new userLogin(); 把上面代码下面的这些注释掉: if($cuserLogin-&g ...

  5. 如何提高Mysql的查询效率???

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  6. javaSe-线程

    package com.java.chap09.sec02; public class Thread1 extends Thread{ private int baoZi=1; private Str ...

  7. 洛谷——普及练习场 普及组选手可冲刺训练,提高组选手亦可在此巩固基础。(Loading...)

    简单的模拟 关卡2-1,6 道题 开始普及组的训练!所谓模拟,就是直接根据题意编写,思维难度简单. //T1 铺地毯 #include <cstdio> #define N 10005 i ...

  8. (转)SQL注入攻击简介

    如果你是做Javaweb应用开发的,那么必须熟悉那声名狼藉的SQL注入式攻击.去年Sony就遭受了SQL注入攻击,被盗用了一些Sony play station(PS机)用户的数据.在SQL注入攻击里 ...

  9. python基础教程总结14——测试

    1. 先测试,后编码 对程序的各个部分建立测试也是非常重要的(这也称为单元测试).测试驱动编程:Test-driven programming 1)精确的需求说明: 程序设计的理念是以编写测试程序开始 ...

  10. Kippo-Failed to load application: 'module' object has no attribute 'IPluggableAuthenticationModules'

    Kippo-Failed to load application: 'module' object has no attribute 'IPluggableAuthenticationModules' ...