为什么需要将Python 3中的地图对象强制转换为列表才能理解?

时间:2017-03-22 14:21:48

标签: python list-comprehension

这个问题来自基本数据类型的黑客问题。我跑的时候

max(map(int, range(5)))

我得到4的正确输出,但是当我做

if __name__ == '__main__':
    n = int(input()) #this line seems irrelevant to my question, but it was present in the original question so I have included it here for completeness
    arr = map(int, input().split())
    print(max([x for x in arr if x < max(arr)]))

并提供输入

5
2 3 6 6 5

结果是2.但是如果我首先将地图对象转换为列表,我会得到5的正确答案。当我用

替换print参数时,这更令人困惑
print(max(arr))

它给出了6的正确答案,所以很明显max可以工作,但是由于某种原因,我猜测列表中的某些东西会破坏地图对象。如果我这样做,这尤其得到了支持

print([x for x in arr if x < max(arr)])

我得到2.更多测试与其他不太有序的列表显示最后一个语句似乎总是返回列表(arr)[0],所以最终我期望问题是地图对象上的列表理解。所以最终我想知道的是

  • Python 3.5.x如何处理导致失败的地图对象和列表推导?
  • 有没有办法以简单的方式成功处理地图对象,理解不涉及投射?

2 个答案:

答案 0 :(得分:4)

Python 3中map的返回值不是列表,而是可迭代对象。它可以很容易地变成一个列表,但如果你直接使用它,它就不能多次迭代。如果您为了计算max而迭代一次,那么您已经用完了它,并且您不会再次获得所有项目。

在Python 2中,map为您构建了一个列表,因此您没有选择懒惰地评估其中的项目。在Python 3中,您可以将其传递给list函数以获取列表。

答案 1 :(得分:1)

在Python 3中,map为您提供iterator。因此,arr会为您提供数字2,3,6,6和5 一次。当您执行[x for x in arr if x < max(arr)]))时,for x in arr会向arr询问2的下一个元素,并将其分配给x。然后max(arr)越过剩余的数字(3,6,6和5)并返回最大值,即6。由于2小于6,因此会在您的结果中结束。然后for x in arr再次出现,由于arr已经完成了所有内容,我们已经完成了。这就是为什么你的结果是[2]

但是,关于始终包含第一个元素的列表,你错了。例如,如果您输入4 3 2 1,则结果列表为空(因为4并非小于最大值3,2和1)。