真实情况:
昨晚写到这样的代码
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的迭代器
[button href="https://www.w3schools.com/python/python_iterators.asp"]itertors[/button]
从中你会发现:创建一个迭代器和停止自己看吧,这里只讲一点
列表,元组,字典和集合都是可迭代的对象。它们是可迭代的 容器,您可以从中获得迭代器。
(区别可迭代和迭代器)
所有这些对象都有一个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[collapse title=""]
迭代器对象实现了 __next__() 方法并通过 StopIteration 异常标识迭代的完成。
[/collapse],这是因为next不到值了,这就说明了list map对象后指针已经到了最后一个,所以再去使用r是空。而print(r)type(r) 这样内置的是重新审查了一遍整体r,因此有值。
而list 字符串等其它可迭代对象,却没有这样的问题,这是因为
这些部分将创建一个新的可迭代对象,然后next对于这些新的
而map本身就是迭代器!!!!
list后返回的是本身,因此next自然是末尾!
于是乎,我们似乎明白了些什么(´இ皿இ`)