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中处理中文,是一件头疼的事情.网上写这方面的文章,测次不齐,而且都会有点错误,所以在这里打算自 ...
随机推荐
- 【HDU - 4340】Capturing a country(树形DP)
BUPT2017 wintertraining(15) #8A 题意 n(<100)个城市组成的树.A攻击i城市需要a[i]代价,B需要b[i].如果一个城市的邻居被A攻击了,那么A攻击它只要A ...
- 【bzoj3456】城市规划(多项式求逆+dp)
Description 求\(~n~\)个点组成的有标号无向连通图的个数.\(~1 \leq n \leq 13 \times 10 ^ 4~\). Solution 这道题的弱化版是poj1737, ...
- Hdoj 1160.FatMouse's Speed 题解
Problem Description FatMouse believes that the fatter a mouse is, the faster it runs. To disprove th ...
- module 'sign.views' has no attribute 'search_name'
百度找到如下链接 http://lovesoo.org/python-script-error-attributeerror-module-object-has-no-attribute-solve- ...
- cf1088E Ehab and a component choosing problem (树形dp)
题意(考试时看错了对着样例wa了好久..):从树上选k个连通块,使得权值的平均值最大的基础上,选的块数最多 如果不考虑块数最多的限制,肯定是只选一个权值最大的块是最好的 然后只要看这个权值最大的块有多 ...
- prufer序列学习笔记
prufer序列是一个定义在无根树上的东西. 构造方法是:每次选一个编号最小的叶子结点,把他的父亲的编号加入到序列的最后.然后删掉这个叶节点.直到最后只剩下两个节点,此时得到的序列就是prufer序列 ...
- kafka清理数据日志
背景问题: 使用kafka的路上踩过不少坑,其中一个就是在测试环境使用kafka一阵子以后,发现其日志目录变的很大,占了磁盘很大空间,定位到指定目录下发现其中一个系统自动创建的 topic,__con ...
- 牛客练习赛43 Tachibana Kanade Loves Game (简单容斥)
链接:https://ac.nowcoder.com/acm/contest/548/F来源:牛客网 题目描述 立华奏是一个天天打比赛的萌新. 省选将至,萌新立华奏深知自己没有希望进入省队,因此开始颓 ...
- 解决Oracle死锁问题步骤
出现问题: 使用jdbc进行批量插入,一直卡在执行界面上,不走代码,预估应该是产生了死锁 1. 使用如下语句查询oracle数据库中的死锁的表和死锁类型 select b.owner,b.object ...
- (七)修改上一条SQL语句,NULL值的滤空函数nvl
修改上一条SQL语句 1.用c命令来修改(c 即 change ) 默认,光标闪烁位置指向上一条SQL语句的第一行.输入二则定位到第二行. c /错误的关键字/正确的关键字 SQL form emp; ...