Вопрос-Ответ

Understanding the map function

Понимание функции map

В документации Python 2 говорится:


Встроенные функции: map(function, iterable, ...)


Примените функцию к каждому элементу iterable и верните список результатов. Если передаются дополнительные аргументы iterable, функция должна принимать такое количество аргументов и применяться к элементам из всех iterable параллельно.


Если одна итерация короче другой, предполагается, что она расширена элементами None.


Если функция имеет значение None, предполагается функция идентификации; если аргументов несколько, map() возвращает список, состоящий из кортежей, содержащих соответствующие элементы из всех итераций (своего рода операция транспонирования).


Повторяющимися аргументами может быть последовательность или любой повторяющийся объект; результатом всегда является список.


Какую роль это играет в создании декартова произведения?

content = map(tuple, array)

Какой эффект дает помещение кортежа в любое место? Я также заметил, что без функции map вывод будет abc, а с ней - a, b, c.

Я хочу полностью понять эту функцию. Справочные определения также сложны для понимания. Слишком много причудливого мусора.

Переведено автоматически
Ответ 1

map не совсем по-питоновски. Я бы рекомендовал вместо этого использовать понимание списков:

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))
Ответ 2

map doesn't relate to a Cartesian product at all, although I imagine someone well versed in functional programming could come up with some impossible to understand way of generating a one using map.

map in Python 3 is equivalent to this:

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

and the only difference in Python 2 is that it will build up a full list of results to return all at once instead of yielding.

Although Python convention usually prefers list comprehensions (or generator expressions) to achieve the same result as a call to map, particularly if you're using a lambda expression as the first argument:

[func(i) for i in iterable]

As an example of what you asked for in the comments on the question - "turn a string into an array", by 'array' you probably want either a tuple or a list (both of them behave a little like arrays from other languages) -

 >>> 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')

A use of map here would be if you start with a list of strings instead of a single string - map can listify all of them individually:

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

Note that map(list, a) is equivalent in Python 2, but in Python 3 you need the list call if you want to do anything other than feed it into a for loop (or a processing function such as sum that only needs an iterable, and not a sequence). But also note again that a list comprehension is usually preferred:

>>> [list(b) for b in a]
[['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']]
Ответ 3

map creates a new list by applying a function to every element of the source:

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 is equivalent to zipping input iterables together and then applying the transformation function on every element of that intermediate zipped list. It's not a Cartesian product:

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))

I've used zip here, but map behaviour actually differs slightly when iterables aren't the same size — as noted in its documentation, it extends iterables to contain None.

Ответ 4

Simplifying a bit, you can imagine map() doing something like this:

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

As you can see, it takes a function and a list, and returns a new list with the result of applying the function to each of the elements in the input list. I said "simplifying a bit" because in reality map() can process more than one iterable:


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.


For the second part in the question: What role does this play in making a Cartesian product? well, map() could be used for generating the cartesian product of a list like this:

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

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

... But to tell the truth, using product() is a much simpler and natural way to solve the problem:

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

Either way, the result is the cartesian product of lst as defined above:

[(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)]
python