题目:

lst = [lambda x: x*i for i in range(4)]
res = [m(2) for m in lst]
print res

实际输出:[6, 6, 6, 6]

想要输出 [0, 2, 4, 6] 应该怎么改?如下:

lst = [lambda x, i=i: x*i for i in range(4)]
res = [m(2) for m in lst]
print res

这个问题涉及到了Python的闭包及延时绑定的知识(Python作用域)。

在Python核心编程里,闭包的定义如下:

如果在一个内部函数里,对外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认定是闭包。

总结为三点:

1、是一个内嵌函数

2、对外部函数变量引用

3、外部函数返回内嵌函数

简单的闭包例子:

def counter(start_at=0):
count = [start_at]
def incr():
count[0] += 1
return count[0]
return incr

上面的那道题,可以写成这样:

def func():
fun_list = []
for i in range(4):
def foo(x):
return x*i
fun_list.append(foo)
return fun_list
for m in func():
  print m(2)

func()是一个包含四个函数的列表:

[<function func at 0x00000000021CE9E8>, <function func at 0x00000000021CEA58>, <function func at 0x00000000021CEAC8>, <function func at 0x00000000021CEB38>]

当我们执行 m(2) 时,运行到foo()内部函数,发现变量 i 并不是foo()中的变量,于是就到外部函数func中寻找变量 i ,但此时外部的 for 已经循环完毕,最后的 i =3 。所以,每次

执行m(2),i 的值都是 3 ,因此,最终结果会是 [6, 6, 6, 6] 。

当在foo()中添加 i=i 后,即:

def func():
fun_list = []
for i in range(4):
def foo(x, i=i):
return x*i
fun_list.append(foo)
return fun_list
for m in func():
  print m(2)

这样的话,for循环执行时,就已经把 i(0, 1, 2, 3) 的值传给了foo()函数,此时的 i 已经是foo()函数的内部变量,运行到foo()函数时,就不会到外部函数寻找变量 i ,直接运行

x*i(0, 1, 2, 3),因此最终结果会是 [0, 2, 4, 6] 。

关于 [lambda x: x*i for i in range(4)] 理解的更多相关文章

  1. fun = [lambda x: x*i for i in range(4)] 本质解析/原理,LEGB规则 闭包原理

    命名空间,闭包原理,参考点击本文 一.问题描述 fun = [lambda x: x*i for i in range(4)] for item in fun: print(item(1)) 上述式子 ...

  2. lambda x:i*x for i in range(4)

    解决方法:冒号前添加接收 i 的变量 return [lambda x,i=i: i * x for i in range(4)]

  3. 「C++11」Lambda 表达式

    维基百科上面对于 lambda 的引入是如下描述的: 在标准 C++,特别是当使用 C++ 标准程序库算法函数诸如 sort 和 find.用户经常希望能够在算法函数调用的附近定义一个临时的述部函数( ...

  4. C++ 11 lambda

    转载:http://www.cnblogs.com/kedebug/p/3224561.html lambda 表达式的简单语法如下:[capture] (parameters) -> retu ...

  5. Python 之 for循环中的lambda

    第一种 f = [lambda x: x*i for i in range(4)]  (如果将x换成i,调用时候就不用传参数,结果都为3) 对于上面的表达式,调用结果: >>> f ...

  6. Python特殊语法:filter、map、reduce、lambda [转]

    Python特殊语法:filter.map.reduce.lambda [转] python内置了一些非常有趣但非常有用的函数,充分体现了Python的语言魅力! filter(function, s ...

  7. python中lambda函数

    1.lambda函数使用如下: lambda语句中,冒号前是参数,可以有多个,用逗号隔开,冒号右侧的是返回值 >>> g=lambda x,y:x*y>>> g(4 ...

  8. Python filter,map,lambda,reduce,列表解析

    filter用法 filter(func,seq) 将seq的元素逐一代入func,通过func的返回值来判断是保留还是过滤 >>> def foo(x): return x> ...

  9. lambda 的使用汇总

    d=lambda x:x+1print(d(10))lambda 相当于一个轻量函数返回 d=lambda x:x+1 if x>0 else "error"print(d( ...

随机推荐

  1. 【调试】Linux下超强内存检测工具Valgrind

    [调试]Linux下超强内存检测工具Valgrind 内容简介 Valgrind是什么? Valgrind的使用 Valgrind详细教程 1. Valgrind是什么? Valgrind是一套Lin ...

  2. CF 1042 F. Leaf Sets

    F. Leaf Sets http://codeforces.com/contest/1042/problem/F 题意: 将所有的叶子节点分配到尽量少的集合,一个可行的集合中两两叶子节点的距离< ...

  3. Ceres优化

    Ceres Solver是谷歌2010就开始用于解决优化问题的C++库,2014年开源.在Google地图,Tango项目,以及著名的SLAM系统OKVIS和Cartographer的优化模块中均使用 ...

  4. Asp.net Web Api开发Help Page 添加对数据模型生成注释的配置和扩展

    在使用webapi框架进行接口开发的时候,编写文档会需要与接口同步更新,如果采用手动式的更新的话效率会非常低.webapi框架下提供了一种自动生成文档的help Page页的功能. 但是原始版本的效果 ...

  5. 并发任务管理器AsyncTaskManager

    //-------------------------------------------------------------------------- // // Copyright (c) BUS ...

  6. netty之心跳机制

    1.心跳机制,在netty3和netty5上面都有.但是写法有些不一样. 2.心跳机制在服务端和客户端的作用也是不一样的.对于服务端来说:就是定时清除那些因为某种原因在一定时间段内没有做指定操作的客户 ...

  7. hdu2509Be the Winner(反nim博弈)

    Be the Winner Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  8. Fiddler使用总结(二)

    在上一篇中介绍了Fiddler的基本使用方法.通过上一篇的操作我们可以直接抓取浏览器的数据包.但在APP测试中,我们需要抓取手机APP上的数据包,应该怎么操作呢? Andriod配置方法: .确保手机 ...

  9. Linux命令应用大词典-第24章 任务计划

    24.1 contab:针对个人用户维护crontab文件

  10. 简析@Resource 和 @Autowired的区别

    @Autowird @Autowird 属于spring框架,默认使用类型(byType)进行注入,例如下面代码: @Autowired public IUserService userService ...