python map 函数的返回值只能读一次?

# 问题

先来看个例子:

>>> a = ["hxhen", ".", "com"]  # 初始化一个字符串列表
>>> b = map(len, a)            # 计算列表中每个字符串的长度
>>> list(b)                    # 转换成列表显示
[5, 1, 3]                      # 正常显示
>>> list(b)                    # 同样的操作再做一次
[]                             # 嗯???数据消失了?

数据消失了吗?其实没有,只不过用这种方式已经获取不到了。

# 原因

map函数的返回值是一个迭代器,list函数等常用操作都会遍历传入的可迭代对象。遍历完迭代器的所有元素之后,索引指针就已经指向了可迭代对象的末尾,此时继续获取它的下一个元素,返回的自然是空值了。

# 解决

解决方式1:一种简单的解决方式是先将结果存成列表,后续可以多次遍历。

>>> a = ["hxhen", ".", "com"]  # 初始化一个字符串列表
>>> b = list(map(len, a))      # 计算列表中每个字符串的长度,并将结果转换成列表
>>> list(b)                    # 转换成列表显示
[5, 1, 3]                      # 正常显示
>>> list(b)                    # 转换成列表显示
[5, 1, 3]                      # 正常显示
>>>                            # 好吧,我必须得承认将一个list对象转成list对象十分多余……
>>>                            # 总之用list或者set等其他非迭代器对象保存结果就好了

解决方式2: Python内置的迭代器对象不支持重置 ,可以改用numpy.nditer对象

>>> a = np.nditer([["hxhen", ".", "com"]])  # 把列表转换成numpy的迭代器,注意传入二维列表
>>> [i.item() for i in a]                   # 遍历一次所有元素
['hxhen', '.', 'com']                       # 结果正常显示
>>> [i.item() for i in a]                   # 再次遍历
[]                                          # 结果为空
>>> a.reset()                               # 重置迭代器
>>> [i.item() for i in a]                   # 再次遍历
['hxhen', '.', 'com']                       # 结果正常显示

# 下面是可以不看的部分

可以用其他方式再次重现这一现象:

>>> a = ["hxhen", ".", "com"]  # 初始化一个字符串列表
>>> c = iter(a)                # 将列表转换成可迭代对象
>>> list(c)                    # 转换成列表显示
['hxhen', '.', 'com']          # 正常显示
>>> list(c)                    # 再次转换成列表显示
[]                             # 为空
>>> [c for item in c]          # 用列表生成式获取元素
[]                             # 同样为空
>>> >>> "|".join(c)            # 用 join 函数拼接各个元素
''                             # 同样为空
>>> next(c)                    # 此时尝试用 next 函数获取下一个元素
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>                            # 报错,说明确实到了迭代器末尾

还可以继续往下尝试:

>>> a = ["hxhen", ".", "com"]  # 初始化一个字符串列表
>>> c = iter(a)                # 将列表转换成可迭代对象
>>> next(c)                    # 先用 next 函数获取一个元素
'hxhen'                        # 获取成功
>>> list(c)                    # 转换成列表显示
['.', 'com']                   # 只有两个元素了
>>> next(c)                    # 再次获取下一个元素
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>>                            # 报错,说明到了迭代器末尾
>>> list(c)                    # 再次转换成列表显示
[]                             # 为空

Glossary — Python 3.7.11 documentation

留下评论

您的邮箱地址不会被公开。 必填项已用 * 标注