Python 2文档说:

Built-in Functions: map(function, iterable, ...) Apply function to every item of iterable and return a list of the results. If additional iterable arguments are passed, function must take that many arguments and is applied to the items from all iterables in parallel. If one iterable is shorter than another it is assumed to be extended with None items. If function is None, the identity function is assumed; if there are multiple arguments, map() returns a list consisting of tuples containing the corresponding items from all iterables (a kind of transpose operation). The iterable arguments may be a sequence or any iterable object; the result is always a list.

它在笛卡尔积中起什么作用呢?

content = map(tuple, array)

把一个元组放在那里有什么影响?我还注意到,如果没有map函数,输出是abc,有了它,输出是abc。

我想完全理解这个函数。参考定义也很难理解。太多花哨的绒毛。


当前回答

map()函数用于对可迭代数据结构中的每个项应用相同的过程,如列表、生成器、字符串等。

让我们来看一个例子: Map()可以遍历列表中的每个项并对每个项应用函数,然后它将返回(返回)新列表。

假设你有一个函数,它接受一个数字,将这个数字加1并返回它:

def add_one(num):
  new_num = num + 1
  return new_num

你还有一个数字列表:

my_list = [1, 3, 6, 7, 8, 10]

如果您想增加列表中的每个数字,您可以执行以下操作:

>>> map(add_one, my_list)
[2, 4, 7, 8, 9, 11]

注意:map()至少需要两个参数。首先是函数名,其次是类似于列表的东西。

让我们看看map()可以做的其他一些很酷的事情。 Map()可以接受多个可迭代对象(列表、字符串等),并将每个可迭代对象中的一个元素作为参数传递给函数。

我们有三个列表:

list_one = [1, 2, 3, 4, 5]
list_two = [11, 12, 13, 14, 15]
list_three = [21, 22, 23, 24, 25]

Map()可以生成一个新列表,其中包含在特定索引处添加的元素。

map()需要一个函数。这次我们将使用内置的sum()函数。运行map()得到如下结果:

>>> map(sum, list_one, list_two, list_three)
[33, 36, 39, 42, 45]

记住: 在Python 2 map()中,将根据最长的列表进行迭代(遍历列表中的元素),并将None传递给较短的列表的函数,因此您的函数应该查找None并处理它们,否则将得到错误。在Python 3中,map()将在完成最短列表后停止。另外,在Python 3中,map()返回一个迭代器,而不是一个列表。

其他回答

简化一点,你可以想象map()做这样的事情:

def mymap(func, lst):
    result = []
    for e in lst:
        result.append(func(e))
    return result

如您所见,它接受一个函数和一个列表,并返回一个新列表,其中包含将该函数应用于输入列表中的每个元素的结果。我说“简化一点”是因为在现实中map()可以处理多个迭代对象:

如果传递了额外的可迭代参数,则function必须接受相同数量的参数,并并行应用于所有可迭代对象中的项。如果一个可迭代对象比另一个短,则假定它扩展为None项。

问题的第二部分,这个在笛卡尔积中扮演什么角色?好吧,map()可以用来生成这样一个列表的笛卡尔积:

lst = [1, 2, 3, 4, 5]

from operator import add
reduce(add, map(lambda i: map(lambda j: (i, j), lst), lst))

... 但说实话,使用product()是一种更简单和自然的解决问题的方法:

from itertools import product
list(product(lst, lst))

无论哪种方式,结果都是上面定义的lst的笛卡尔积:

[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5),
 (2, 1), (2, 2), (2, 3), (2, 4), (2, 5),
 (3, 1), (3, 2), (3, 3), (3, 4), (3, 5),
 (4, 1), (4, 2), (4, 3), (4, 4), (4, 5),
 (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)]

Map不是特别python化的。我建议使用列表推导式:

map(f, iterable)

基本上相当于:

[f(x) for x in iterable]

map本身不能做笛卡尔积,因为它的输出列表的长度总是和它的输入列表的长度相同。你可以简单地用一个列表推导做一个笛卡尔积:

[(a, b) for a in iterable_a for b in iterable_b]

语法有点混乱——基本上相当于:

result = []
for a in iterable_a:
    for b in iterable_b:
        result.append((a, b))

Python3 - map(func, iterable)

有一件事没有完全提到(尽管@BlooB有点提到它)是map返回一个map对象而不是一个列表。当涉及到初始化和迭代的时间性能时,这是一个很大的区别。考虑这两个测试。

import time
def test1(iterable):
    a = time.clock()
    map(str, iterable)
    a = time.clock() - a

    b = time.clock()
    [ str(x) for x in iterable ]
    b = time.clock() - b

    print(a,b)


def test2(iterable):
    a = time.clock()
    [ x for x in map(str, iterable)]
    a = time.clock() - a

    b = time.clock()
    [ str(x) for x in iterable ]
    b = time.clock() - b

    print(a,b)


test1(range(2000000))  # Prints ~1.7e-5s   ~8s
test2(range(2000000))  # Prints ~9s        ~8s

如您所见,初始化map函数几乎不需要花费任何时间。然而,遍历map对象要比遍历iterable花费更长的时间。这意味着传递给map()的函数在迭代中到达元素之前不会应用到每个元素。如果你想要一个列表,使用列表理解。如果您计划在for循环中遍历,并且将在某个点中断,那么请使用map。

Map通过对源的每个元素应用一个函数来创建一个新列表:

xs = [1, 2, 3]

# all of those are equivalent — the output is [2, 4, 6]
# 1. map
ys = map(lambda x: x * 2, xs)
# 2. list comprehension
ys = [x * 2 for x in xs]
# 3. explicit loop
ys = []
for x in xs:
    ys.append(x * 2)

N-ary map相当于将输入可迭代对象压缩在一起,然后对中间压缩列表的每个元素应用转换函数。它不是笛卡尔积

xs = [1, 2, 3]
ys = [2, 4, 6]

def f(x, y):
    return (x * 2, y // 2)

# output: [(2, 1), (4, 2), (6, 3)]
# 1. map
zs = map(f, xs, ys)
# 2. list comp
zs = [f(x, y) for x, y in zip(xs, ys)]
# 3. explicit loop
zs = []
for x, y in zip(xs, ys):
    zs.append(f(x, y))

这里我使用了zip,但是当可迭代对象的大小不同时,map的行为实际上会略有不同——正如它的文档中所指出的,它扩展了可迭代对象以包含None。

map与笛卡尔式的产品完全没有关系,尽管我认为精通函数式编程的人可能会想出一些难以理解的方法来使用map生成一个。

在Python 3中,map等价于:

def map(func, iterable):
    for i in iterable:
        yield func(i)

Python 2中唯一的区别是它会建立一个完整的结果列表,一次返回所有结果,而不是yield。

尽管Python惯例通常更倾向于使用列表推导式(或生成器表达式)来实现与调用map相同的结果,特别是当你使用lambda表达式作为第一个参数时:

[func(i) for i in iterable]

作为你在问题评论中要求的一个例子-“将字符串转换为数组”,通过“数组”,你可能想要一个元组或一个列表(它们的行为有点像其他语言中的数组)-

 >>> a = "hello, world"
 >>> list(a)
['h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd']
>>> tuple(a)
('h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd')

map在这里的用法是,如果你从一个字符串列表开始,而不是一个字符串- map可以单独列出所有字符串:

>>> a = ["foo", "bar", "baz"]
>>> list(map(list, a))
[['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']]

注意,map(list, a)在Python 2中是等效的,但在Python 3中,如果你想做任何事情,而不是将其提供给for循环(或只需要可迭代对象而不需要序列的处理函数,如sum),则需要调用list。但也要再次注意,通常首选列表推导式:

>>> [list(b) for b in a]
[['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']]