2018-01-03 @望京

示例1

>>> b = []
>>> for i in range(5):
... b.append(lambda :i)
...
>>> for j in b:
... print j()
...
4
4
4
4
4
>>> for m in b:
... print type(m),m
...
<type 'function'> <function <lambda> at 0x7fe4aae708c0>
<type 'function'> <function <lambda> at 0x7fe4aae70938>
<type 'function'> <function <lambda> at 0x7fe4aae709b0>
<type 'function'> <function <lambda> at 0x7fe4aae70b18>
<type 'function'> <function <lambda> at 0x7fe4aae70b90>
>>>
>>>

为什么不是输出 0~4?   

Closures in Python are late-binding,
meaning that each lambda function in the list will only evaluate the variable i when invoked,
and not when defined. That's why all functions return the same value, i.e. the last value of ì (which is 4).

late-binding-closures in Python  http://docs.python-guide.org/en/latest/writing/gotchas/#late-binding-closures

怎么修改使之输出 0~4?   b.append(lambda i=i:i)

>>> b = []
>>> for i in range(5):
... b.append(lambda i=i:i)
...
>>> for j in b:
... print j()
...
0
1
2
3
4
>>>

或者使用 functools.partial

>>> b = []
>>> for i in range(5):
... from functools import partial
... b.append(partial(lambda x:x, i))
...
>>> for j in b:
... print j()
...
0
1
2
3
4
>>>

参考:https://stackoverflow.com/questions/38369470/lambdas-from-a-list-comprehension-are-returning-a-lambda-when-called

lambda补充

>>> foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]
>>>
>>> print filter(lambda x: x % 3 == 0, foo) # 过滤
[18, 9, 24, 12, 27]
>>>
>>> print map(lambda x: x * 2 + 10, foo) # map
[14, 46, 28, 54, 44, 58, 26, 34, 64]
>>>
>>> print reduce(lambda x, y: x + y, foo) # 求和
139
>>>

示例2

>>> def func(arg=[]):
... arg.append(1)
... print arg
...
>>> func()
[1]
>>> func()
[1, 1]
>>>

修改1:在函数调用的时候传入参数

>>> def func(arg=[]):
... arg.append(1)
... print arg
...
>>> func([])
[1]
>>> func([])
[1]
>>>  

修改2:默认参数改为 None (更安全的做法)

>>>
>>> def func(arg=None):
... if not arg:
... arg = []
... arg.append(1)
... print arg
...
>>>
>>> func()
[1]
>>> func()
[1]
>>>

示例3

>>>
>>> def func(x, l=[]):
... for i in range(x):
... l.append(i*i)
... print l
...
>>> func(2)
[0, 1]
>>> func(3)
[0, 1, 0, 1, 4]
>>>

2018-03-12  https://zhuanlan.zhihu.com/p/33376761

今天在地铁上看到公众号推荐这个文章,也是late-binding问题,再补充下:

def foo():
temp = [lambda x : i*x for i in range(4)]
return temp for bar in foo():
print(bar(2)) # 输出
6
6
6
6

其实可以改写成下面这样,这样就比较容易看出是闭包了:lambda本身是一个函数,调用了外面的变量 i

temp = []
for i in range(4):
temp.append(lambda x : i*x) for bar in temp:
print(bar(2))

解决方法1:  [lambda x,i=i : i*x for i in range(4)]

def foo():
temp = [lambda x,i=i : i*x for i in range(4)]
return temp for bar in foo():
print(bar(2))

解决方法2:使用 functools.partial

from functools import partial
from operator import mul def foo():
temp = [partial(mul,i) for i in range(4)]
return temp for bar in foo():
print(bar(2))

解决方法3:把temp改成生成器

def foo():
temp = (lambda x : i*x for i in range(4))
return temp for bar in foo():
print(bar(2)) # 或者用 next() 方式调用
# bar = foo()
# print(next(bar)(2))
# print(next(bar)(2))
# print(next(bar)(2))
# print(next(bar)(2)) # 或者用 next() 方式调用
# bar = foo()
# print(bar.__next__()(2))
# print(bar.__next__()(2))
# print(bar.__next__()(2))
# print(bar.__next__()(2))

解决方法4:使用yield

def foo():
for i in range(4):
yield lambda x : i*x for bar in foo():
print(bar(2))

补充

构造生成器的两种方式:
使用类似列表生成式的方式生成 (2*n + 1 for n in range(3, 11))
使用包含yield的函数来生成 如果计算过程比较简单,可以直接把列表生成式改成generator;
但是,如果计算过程比较复杂,就只能通过包含yield的函数来构造generator。

  

学无止境,戒骄戒躁。

最新文章

  1. 【python之路3】if 语句
  2. jquery实现表格动态添加
  3. 如何加入自定义WebControl
  4. RTSP协议学习笔记
  5. 集合练习——List部分
  6. Course Schedule ——LeetCode
  7. Linux硬盘命名和安装分区
  8. adb :unknown host service
  9. dictionary (key-value) (map容器)
  10. linux android ndk
  11. 【UWP】列表项宽度自适应的实现
  12. 数据结构与算法(c++)——跳跃表(skip list)
  13. C++静态库与动态库(转)
  14. 使用QuertZ组件来搞项目工作流(一)
  15. [物理学与PDEs]第2章第2节 粘性流体力学方程组 2.3 广义 Newton 法则---本构方程
  16. MemCache在网站中的使用
  17. lucene-solr本地调试方法
  18. 分部视图(Partial View)及Html.Partial和Html.Action差异
  19. 详解C#特性和反射(二)
  20. LCT解读(1)

热门文章

  1. python学习日记(文件操作练习题)
  2. 使用 sizeof 获取字符串数组的大小
  3. emwin之错误使用控件函数导致死机现象
  4. 协同过滤算法 teamCF
  5. hdu 2516(Fibonacci博弈博弈)
  6. 封装一个基于NLog+NLog.Mongo的日志记录工具类LogUtil,nloglogutil
  7. java 红黑树
  8. bash 5
  9. 第十三节、SURF特征提取算法
  10. postman 测试套件collection