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。

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


当前回答

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。

其他回答

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

让我们来看一个例子: 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))

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。