Python:list()函数弄乱了map()

时间:2018-09-24 14:52:01

标签: python python-3.x list dictionary filter

我在python 3上使用了map()filter()函数。 我尝试获取一个列表并对其进行过滤,然后在过滤器对象上执行地图功能:

f = list(range(10))
print(f)
print('-----------')
y = filter(lambda a: a > 5, f)
print(list(y))
print(y)
print(type(y))
print('-----------')
x = map(lambda value: value+1, y)
print(list(y))
print(y)
print(type(y))
print('-----------')
print(list(x))
print(x)
print(type(x))

结果是:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-----------
[6, 7, 8, 9]
<filter object at 0x7f46db255ac8>
<class 'filter'>
-----------
[]
<filter object at 0x7f46db255ac8>
<class 'filter'>
-----------
[]
<map object at 0x7f46db3fc128>
<class 'map'>

当我注释掉print(list(y))时,它突然运作良好。 你遇到这个了吗?我究竟做错了什么? 我在ubuntu上运行python 3.6.3。

2 个答案:

答案 0 :(得分:9)

迭代器和生成器只能使用一次。当您调用list(y)时,它将产生序列中的所有值,然后将其耗尽。当您第二次尝试查看内容时,没有任何内容可供使用,因此您将获得一个空列表。

以下内容更清楚地证明了这一点:

f = list(range(10))
print(f)
print('-----------')
y = filter(lambda a: a > 5, f)
print(list(y))
print(list(y))

哪个给:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-----------
[6, 7, 8, 9]
[] # Nothing to yield

如果要将值保留在y中,则需要将其分配给名称:

y = list(filter(lambda a: a > 5, f))

答案 1 :(得分:1)

我同意roganjosh的回答,但是让我看看是否可以添加一些额外内容:

filter()map()reversed()函数有点令人困惑的是,它们不返回列表(如您所料),而是返回迭代器。 (在键入help(filter)help(map)help(reversed)时可以阅读的帮助文本中对此进行了说明。)

因此,既然您知道它们返回的是迭代器而不是列表,您可能想知道:为什么这很重要?好吧,迭代器应该迭代一次(即不超过一次),就像在for i in iterator:这样的for循环中一样。而且要记住的重要一点是,一旦迭代了迭代器,就不再有要迭代的元素了。

为说明起见,请考虑以下代码:

backwards = reversed( [1, 2, 3, 4, 5] )   # creates an iterator; not a list!
myList = list(backwards)   # iterates over the iterator to create a list
print(myList)   # prints "[5, 4, 3, 2, 1]", as you'd expect
myList = list(backwards)   # nothing left to iterate over, so creates an empty list
print(myList)   # prints "[]" (an empty list)

那么,如果您想从filter()map()reversed()而不是迭代器中获取列表,该怎么办?好吧,您可以立即将这些函数调用包装在list()中,并在需要时使用该结果,如下所示:

myList = list( reversed( [1, 2, 3, 4, 5] ) )
# Now use myList whenever you need it, without worrying that it will disappear.

或者,您可以将filter()map()替换为列表理解,例如:

f = list(range(10))
y = [a for a in f if a > 5]  # you can use this instead of filter()
x = [a + 1 for a in f]  # you can use this instead of map()

关于替换reversed()?试试这个:

z = f[::-1]  # you can use this instead of reversed()

您可能想知道:如果我可以使用filter()map()reversed()的替代品,为什么还要使用它们?

答案是因为有时您需要过滤,映射或反转一个巨大的列表,而创建另一个(巨大的)列表仅用于循环/迭代会非常浪费和耗时。因此,返回迭代器可防止另一块巨大的内存用完-只需知道迭代器用完(即遍历)时,其信息就会消失。