对于不返回值的函数,请使用map()

时间:2017-12-08 21:53:35

标签: python python-3.x

我有一个简单的问题:

如果我有一个功能:

a = [1,2,3,4,5,6,7]
def f(x):
    return (x**2)
result = list(map(f, a))
print(result)
>>> [1, 4, 9, 16, 25, 36, 49]

但如果我:

result = []
a = [1,2,3,4,5,6,7]
def f(x):
    result.append(x**2)
map(f, a)
print(result)
>>> []

它不会工作。

但是,如果我以这种方式编写函数,它将起作用:

result = []
a = [1,2,3,4,5,6,7]
def f(x):
    result.append(x**2)
for i in a:
    f(i)
print(result)
>>> [1, 4, 9, 16, 25, 36, 49]

即使我为其包含一个返回值:

result = []
a = [1,2,3,4,5,6,7]
def f(x):
    result.append(x**2)
    return x**2
map(f, a)
print(result)           # >>> []
print(list(map(f,a)))   # >>> [1,2,3,4,5,6,7]

我应该理解它,因为map()必须应用于具有返回值且仅返回值的函数。

3 个答案:

答案 0 :(得分:9)

您在这里看到的是lazy-evaluation的效果。 Python 3使大多数这样的函数(mapfilterzip等)懒得工作,他们曾经在Python 2中热切地工作,也就是说,而不是立即返回并实现数据-structure当你调用map(f, some_iterable)时,map会返回一个map-object,然后可以将其迭代到实现数据结构或逐个使用元素(让你工作)以记忆效率的方式)。

>>> result = []
>>> m = map(lambda x: result.append(x), range(10))
>>> m
<map object at 0x10a0b7278>
>>> result
[]
>>> next(m)
>>> result
[0]
>>> next(m)
>>> result
[0, 1]
>>> list(m)
[None, None, None, None, None, None, None, None]
>>> result
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

然而!

你应该使用mapfilter或列表推导来解决他们的副作用。这些都是功能结构,你应该避免在使用时改变状态。这只是糟糕的风格,而且,正如你在我的地图对象上调用list时所注意到的那样,它会创建并立即丢弃一个无用的None列表(因为这些函数不会返回任何内容)隐含地返回None)。

所以,回答你的问题,是的,你可以使用&#34; map()来表示不返回值的函数&#34;但你不应该。只需使用for循环。

答案 1 :(得分:3)

map创建一个迭代器。它不会立即执行映射,它会在您使用迭代器时逐个执行它。 list(map(...))会立即使用整个迭代器将其转换为列表。但是在你的测试中它不起作用,你永远不会使用迭代器,所以f永远不会被调用一次。

换句话说:不起作用:

map(f, a)
print(result)

使用:

list(map(f, a))  # ← list consumes the iterator
print(result)

答案 2 :(得分:0)

使用 Python 2 它将有效...

我尝试了所有这些,这是我的结果集:

[1, 4, 9, 16, 25, 36, 49]
[1, 4, 9, 16, 25, 36, 49]
[1, 4, 9, 16, 25, 36, 49]
[1, 4, 9, 16, 25, 36, 49]
[1, 4, 9, 16, 25, 36, 49]