Python中late-binding-closures
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
>>>
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的更多相关文章
- Python中的内置函数
2.1 Built-in Functions The Python interpreter has a number of functions built into it that are alway ...
- 可爱的 Python : Python中的函数式编程,第三部分
英文原文:Charming Python: Functional programming in Python, Part 3,翻译:开源中国 摘要: 作者David Mertz在其文章<可爱的 ...
- 可爱的 Python : Python中函数式编程,第二部分
英文原文:Charming Python: Functional programming in Python, Part 2,翻译:开源中国 摘要: 本专栏继续让David对Python中的函数式编 ...
- 使用RSA加密在Python中逆向shell
i春秋翻译小组-Neo(李皓伟) 使用RSA加密在Python中逆向shell 这是一个关于使用RSA加密编程逆向shell的python教程. 我想提一下,这篇文章更多的是关于理解shell中涉及的 ...
- python 中关于descriptor的一些知识问题
这个问题从早上日常扫segmentfault上问题开始 有个问题是 class C(object): @classmethod def m(): pass m()是类方法,调用代码如下: C.m() ...
- python之name binding
[python之name binding] 1. 名字 名字是对一个对象的称呼,一个对象可以只有一个名字,也可以没有名字或取多个名字.但对象自己却不知道有多少名字,叫什么,只有名字本身知道它所指向 ...
- python中的作用域与名称空间
python中的名称空间以及作用域分析 从Python解释器开始执行之后,就在内存中开辟一个空间,每当遇到一个变量的时候,就把变量名和值之间对应的关系记录下来,但是当遇到函数定义的时候,解释器只是象征 ...
- Python中的__name__和__main__含义详解
1背景 在写Python代码和看Python代码时,我们常常可以看到这样的代码: ? 1 2 3 4 5 def main(): ...... if __name == "__m ...
- UnboundLocalError,探讨Python中的绑定
绑定 将python闭包之前,先梳理一下闭包中的绑定操作. 先看看2个相关的错误 NameError 和UnboundLocalError When a name is not found at al ...
- [转]Python中的str与unicode处理方法
早上被python的编码搞得抓耳挠腮,在搜资料的时候感觉这篇博文很不错,所以收藏在此. python2.x中处理中文,是一件头疼的事情.网上写这方面的文章,测次不齐,而且都会有点错误,所以在这里打算自 ...
随机推荐
- ARC 086 E - Smuggling Marbles(dp + 启发式合并)
题意 Sunke 有一棵 \(N + 1\) 个点的树,其中 \(0\) 为根,每个点上有 \(0\) 或 \(1\) 个石子, Sunke 会不停的进行如下操作直至整棵树没有石子 : 把 \(0\) ...
- 【BZOJ5318】[JSOI2018]扫地机器人(动态规划)
[BZOJ5318][JSOI2018]扫地机器人(动态规划) 题面 BZOJ 洛谷 题解 神仙题.不会.... 先考虑如果一个点走向了其下方的点,那么其右侧的点因为要被访问到,所以必定只能从其右上方 ...
- module_loader.py
# few functions that make it possible to import functions # from jupyter notebooks as from modules; ...
- html图像、绝对路径和相对路径,链接
html图像 <img>标签可以在网页上插入一张图片,它是独立使用的标签,通过"src"属性定义图片的地址,通过"alt"属性定义图片加载失败时显示 ...
- 分离式部署LNMP
-------Nginx----------PHP+NFS------------MySql------192.168.56.202 192.168.56.201 192.168.56.200安装My ...
- HDU 6319 Problem A. Ascending Rating(单调队列)
要求一个区间内的最大值和每次数过去最大值更新的次数,然后求每次的这个值异或 i 的总和. 这个序列一共有n个数,前k个直接给出来,从k+1到n个数用公式计算出来. 因为要最大值,所以就要用到单调队列, ...
- 20165223 结对编程之四则运算week2-整体总结
目录 一.结对对象 二.需求分析 三.设计思路 四.核心代码 五.功能截图 六.结对感受 一.结对对象 担任角色(本周交换角色,流动学习) 驾驶员(Driver):20165218 赵冰雨(是控制键盘 ...
- 20165223 week6测试错题总结
由于时间预估错误及手机自身卡顿问题,虽然已经作答完成,却在最后提交时出现错误,错失提交时间,所以没能按时提交答案,也就没有纠错,以下仅凭印象列出错题: Q1:若超出JVM运行能力,如"byt ...
- 简明的Python教程中的几个疑惑点分析#2
#1简明的Python教程当中第十四章Python标准库介绍中的使用sys模块 假如你没看懂sys模块这一章节,那么没关系,看下面一段代码再看简明的Python教程中的sys模块实例你将很容易看懂 代 ...
- Electron一学习资源收集和练习demo
1.近日为了做项目查资料学习electron,简直头都要炸了,就官方的electron-quick-start的例子进行了基本的练习之后,不断的查资料终于发现一些有用的demo来看源代码学习,一遍看代 ...