Understanding the map function
1 | map(function, iterable, ...) |
将函数应用于iterable的每个项,并返回结果列表。如果传递了额外的可Iterable参数,则函数必须接受如此多的参数,并并行应用于所有Iterable中的项。
如果一个iterable短于另一个iterable,则假定扩展时不包含任何项。
如果函数是
iterable参数可以是序列或任何iterable对象;结果总是一个列表。
它在笛卡尔积的生成中扮演什么角色?
1 | content = map(tuple, array) |
号
在那里放一个元组有什么效果?我还注意到,没有map函数,输出是
我想完全理解这个函数。参考定义也很难理解。太多花哨的绒毛。
1 | map(f, iterable) |
基本上相当于:
1 | [f(x) for x in iterable] |
1 | [(a, b) for a in iterable_a for b in iterable_b] |
语法有点混乱,基本上相当于:
1 2 3 4 | result = [] for a in iterable_a: for b in iterable_b: result.append((a, b)) |
python 3中的
1 2 3 | def map(func, iterable): for i in iterable: yield func(i) |
而在python 2中唯一的区别是,它将构建一个完整的结果列表来一次性返回所有结果,而不是返回
尽管python约定通常倾向于使用列表理解(或生成器表达式)来实现与对
1 | [func(i) for i in iterable] |
例如,您在对问题的注释中要求的内容-"将字符串转换为数组",通过"array",您可能需要一个元组或一个列表(它们的行为与其他语言的数组有些相似)-
1 2 3 4 5 | >>> 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') |
如果从字符串列表而不是单个字符串开始使用
1 2 3 | >>> a = ["foo","bar","baz"] >>> list(map(list, a)) [['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']] |
请注意,在python 2中,
1 2 | >>> [list(b) for b in a] [['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']] |
1 2 3 4 5 6 7 8 9 10 11 | 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元
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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)) |
我在这里使用了
简化一点,你可以想象
1 2 3 4 5 | def mymap(func, lst): result = [] for e in lst: result.append(func(e)) return result |
如您所见,它接受一个函数和一个列表,并返回一个新的列表,结果是将该函数应用于输入列表中的每个元素。我说"简化一点",因为事实上,
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.
对于问题的第二部分:这在笛卡尔积的生成中扮演了什么角色?那么,
1 2 3 4 | lst = [1, 2, 3, 4, 5] from operator import add reduce(add, map(lambda i: map(lambda j: (i, j), lst), lst)) |
…但说实话,使用
1 2 | from itertools import product list(product(lst, lst)) |
不管怎样,结果都是上面定义的
1 2 3 4 5 | [(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)] |
让我们来看一个例子:
假设您有一个函数接受一个数字,向该数字加1并返回它:
1 2 3 | def add_one(num): new_num = num + 1 return new_num |
您还有一个数字列表:
1 | my_list = [1, 3, 6, 7, 8, 10] |
如果要增加列表中的每个数字,可以执行以下操作:
1 2 | >>> map(add_one, my_list) [2, 4, 7, 8, 9, 11] |
注:至少
让我们看看
我们有三个列表:
1 2 3 | list_one = [1, 2, 3, 4, 5] list_two = [11, 12, 13, 14, 15] list_three = [21, 22, 23, 24, 25] |
记住,
1 2 | >>> map(sum, list_one, list_two, list_three) [33, 36, 39, 42, 45] |
记得:在python 2中,
python3-地图(func,iterable)
有一件事没有完全提到(尽管@bloob有点提到过),那就是map返回一个map对象,而不是一个列表。当涉及到初始化和迭代的时间性能时,这是一个很大的区别。考虑这两个测试。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | 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。