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。

  

学无止境,戒骄戒躁。

Python中late-binding-closures的更多相关文章

  1. Python中的内置函数

    2.1 Built-in Functions The Python interpreter has a number of functions built into it that are alway ...

  2. 可爱的 Python : Python中的函数式编程,第三部分

    英文原文:Charming Python: Functional programming in Python, Part 3,翻译:开源中国 摘要:  作者David Mertz在其文章<可爱的 ...

  3. 可爱的 Python : Python中函数式编程,第二部分

    英文原文:Charming Python: Functional programming in Python, Part 2,翻译:开源中国 摘要:  本专栏继续让David对Python中的函数式编 ...

  4. 使用RSA加密在Python中逆向shell

    i春秋翻译小组-Neo(李皓伟) 使用RSA加密在Python中逆向shell 这是一个关于使用RSA加密编程逆向shell的python教程. 我想提一下,这篇文章更多的是关于理解shell中涉及的 ...

  5. python 中关于descriptor的一些知识问题

    这个问题从早上日常扫segmentfault上问题开始 有个问题是 class C(object): @classmethod def m(): pass m()是类方法,调用代码如下: C.m() ...

  6. python之name binding

    [python之name binding] 1. 名字   名字是对一个对象的称呼,一个对象可以只有一个名字,也可以没有名字或取多个名字.但对象自己却不知道有多少名字,叫什么,只有名字本身知道它所指向 ...

  7. python中的作用域与名称空间

    python中的名称空间以及作用域分析 从Python解释器开始执行之后,就在内存中开辟一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征 ...

  8. Python中的__name__和__main__含义详解

    1背景 在写Python代码和看Python代码时,我们常常可以看到这样的代码: ? 1 2 3 4 5 def main():     ......   if __name == "__m ...

  9. UnboundLocalError,探讨Python中的绑定

    绑定 将python闭包之前,先梳理一下闭包中的绑定操作. 先看看2个相关的错误 NameError 和UnboundLocalError When a name is not found at al ...

  10. [转]Python中的str与unicode处理方法

    早上被python的编码搞得抓耳挠腮,在搜资料的时候感觉这篇博文很不错,所以收藏在此. python2.x中处理中文,是一件头疼的事情.网上写这方面的文章,测次不齐,而且都会有点错误,所以在这里打算自 ...

随机推荐

  1. Linux 通过Shell 查找问题进程 [转]

    背景介绍: 最近公司服务器不太稳定,总是在凌晨某个时段突发高负载情况,因为客观环境比较复杂,所以很难猜测出到底是哪个进程出现了问题,加之故障发生时,通常我在睡觉,等我被报警短信吵醒,通过公司 VPN ...

  2. k短路模板(洛谷P2483 [SDOI2010]魔法猪学院)(k短路,最短路,左偏树,priority_queue)

    你谷数据够强了,以前的A*应该差不多死掉了. 所以,小伙伴们快来一起把YL顶上去把!戳这里! 俞鼎力的课件 需要掌握的内容: Dijkstra构建最短路径树. 可持久化堆(使用左偏树,因其有二叉树结构 ...

  3. FlatList

    FlatList 之前使用的组件是ListView,当时要添加一个下拉刷新,上拉加载的功能,所以对ListView做了一些封装,但是后来看官方文档,不建议再使用ListView,因为效率问题,做过An ...

  4. [luogu3628][bzoj1911][APIO2010]特别行动队【动态规划+斜率优化DP】

    题目描述 给你一个数列,让你将这个数列分成若干段,使其每一段的和的\(a \times sum^2 + b \times sum + c\)的总和最大. 分析 算是一道斜率优化的入门题. 首先肯定是考 ...

  5. 自适应PC端网页制作使用REM

    做一个PC端的网页,设计图是1920X1080的. 要在常见屏上显示正常(比例正确可) 1280X720 1366X768 1440X900 1920X1080 使用了几种办法 1.内容在一屏内显示的 ...

  6. 使用jvisualVm监控本地和远程的jvm

    jvisualVm是jdk自带的可视化监控工具,功能很强大,可安装各种扩展插件.本篇不打算讲解如果使用详细的功能,只讲在windows环境怎么监控本地和远端(一般是无界面的linux系统)的java进 ...

  7. redis 指令文档

    参考:https://redis.io/commands http://www.runoob.com/redis/redis-lists.html redis: 打开一个 cmd 窗口 使用cd命令切 ...

  8. QTREE5 - Query on a tree V——LCT

    QTREE5 - Query on a tree V 动态点分治和动态边分治用Qtree4的做法即可. LCT: 换根后,求子树最浅的白点深度. 但是也可以不换根.类似平常换根的往上g,往下f的拼凑 ...

  9. 跟我一起使用android Studio打包react-native项目的APK

    使用的是react-native的hello-world项目 第一步:创建项目 npm install -g yarn react-native-cli react-native init Aweso ...

  10. Python之函数--命名空间、作用域、global、nonlocal、函数的嵌套和作用域链

    命名空间 -------‘’存放名字与值的关系”的空间 代码在运行伊始,创建的存储“变量名与值的关系”的空间叫做全局命名空间: 在函数的运行中开辟的临时的空间叫做局部命名空间. 命名空间一共分为三种: ...