Python 3.6.4 (v3.6.4:d48ecebad5, Dec 18 2017, 21:07:28)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> c = [1, 2]
>>> c += map(lambda n: n *2, range(1, 3))
>>> c
[1, 2, 2, 4]
>>> c = [1, 2]
>>> c += map(lambda n: n *2, c)
Killed!
但是,python2也是如此,它的map结果是一个列表,这与python3中的生成器不同。那为什么c += map(lambda n: n *2, range(1, 3))
会起作用呢?你知道吗
c += foo
与c = c.__iadd__(foo)
等价。如果c
是一个列表,list.__iadd__
方法接受任何iterable,包括一个生成器表达式:即使
list.__add__
不支持生成器表达式:python3中的代码崩溃是因为
map
生成器在被扩展的相同的列表上迭代,但是当前位置总是尾部后面的两个元素。从迭代器中提取新元素时,list.__iadd__
始终会将新元素逐个添加到末尾;此时,map
生成器持有的列表迭代器使用的索引将递增。。。但是在列表的末尾添加了一个新元素,所以在当前迭代位置之后总是有2个元素,最终Python会耗尽内存或者计算机会因为交换而停止运行。你知道吗也就是说,这种行为与
(以Wim为荣)
Python2版本的工作原理正是因为
map
将在调用c.__iadd__
之前创建一个列表;一个包含2个元素的新列表将传递给c.__iadd__
。同样地,c += map(lambda n: n * 2, range(1, 3))
也可以工作,因为在python2中,range(1, 3)
将创建一个新列表,而在python3中,它将创建一个range sequence对象,两者都是不同的如果将
map
替换为生成器表达式,也可以触发Python 2中的病理行为:相关问题 更多 >
编程相关推荐