真实情况: #
昨晚写到这样的代码
def chartoNum(s):
dict = {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}
return dict[s]
def fn(x, y):
return x * 10 + y
r = map(chartoNum, "23443")
print(list(r))
r1 = reduce(fn, r)
print(r1)
很不幸的是,报错了 -
TypeError: reduce() of empty sequence with no initial value
可是我明明给你 reduce 值了 --
我将目标锁定在 r 身上,于是将 r 替换成 map(....) 实测正常。那为什么会这样呢?
首先我们得知道 python 的迭代器 #
从中你会发现:创建一个迭代器和停止自己看吧,这里只讲一点
列表,元组,字典和集合都是可迭代的对象。它们是可迭代的容器,您可以从中获得迭代器。
(区别可迭代和迭代器)
所有这些对象都有一个 iter() 方法用于获取迭代器,然后经过 next() 去打印。
并且我们一直使用 for 去遍历一些列表元组字典,实际上就是该 for 循环创建了一个迭代器对象,并为每个循环执行 next() 方法。
所以我们才能去遍历得到值
解释器需要迭代对象 x 时,会自动调用 iter(x)
那为什么要介绍迭代器? 我们再来看下 reduce 的语法
reduce(function, iterable[, initializer])
iterable 就是可迭代的对象
对于 map 在 Python 3.x 返回迭代器。 所以我们一般需要 list(),将其返回列表,bug 就出现在这里。
!!!!!! list() 后迭代器,第一次有值,第二次就没了
list(r) # 有值列表
list(r) # 空列表
以至于我们再去调用 r 的时候为空,但是 print(r) 是有值的 这是为什么呢??? list() 的作用是返回列表,也就是可迭代的对象 list(r) 后再调用 next(r) 会发现报错 StopIteration
迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。
这是因为 next 不到值了,这就说明了 list map 对象后指针已经到了最后一个,所以再去使用 r 是空。而 print(r) type(r) 这样内置的是重新审查了一遍整体 r,因此有值。
而 list、字符串等其它可迭代对象,却没有这样的问题,这是因为 这些部分将创建一个新的可迭代对象,然后 next 对于这些新的
而 map 本身就是迭代器!!!! list() 后返回的是本身,因此 next 自然是末尾!
于是乎,我们似乎明白了些什么 (´இ 皿 இ `)
