Python LanguageФункция карты

Синтаксис

  • map (function, iterable [, * Additional_iterables])
  • future_builtins.map (function, iterable [, * Additional_iterables])
  • itertools.imap (функция, iterable [, * дополнительные_имя)]

параметры

параметр подробности
функция функция для отображения (должна принимать столько параметров, сколько есть итераций) ( только для позиции )
итерируемый функция применяется к каждому элементу итерабельного ( только для позиции )
* additional_iterables см. iterable, но сколько угодно ( необязательно , только для позиции )

замечания

Все, что можно сделать с помощью map также можно сделать с comprehensions :

list(map(abs, [-1,-2,-3]))    # [1, 2, 3]
[abs(i) for i in [-1,-2,-3]]  # [1, 2, 3]

Хотя вам понадобится zip если у вас много итераций:

import operator
alist = [1,2,3]
list(map(operator.add, alist, alist))  # [2, 4, 6]
[i + j for i, j in zip(alist, alist)]  # [2, 4, 6]

Учет списков эффективен и может быть быстрее, чем map во многих случаях, поэтому проверяйте время обоих подходов, если скорость важна для вас.

Основное использование карты, itertools.imap и future_builtins.map

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

names = ['Fred', 'Wilma', 'Barney']
Python 3.x 3.0
map(len, names)  # map in Python 3.x is a class; its instances are iterable
# Out: <map object at 0x00000198B32E2CF8>

3-совместимая map Python включена в модуль future_builtins :

Python 2.x 2.6
from future_builtins import map  # contains a Python 3.x compatible map()
map(len, names)                  # see below
# Out: <itertools.imap instance at 0x3eb0a20>

В качестве альтернативы, в Python 2 можно использовать imap из itertools для получения генератора

Python 2.x 2.3
map(len, names)   # map() returns a list
# Out: [4, 5, 6]

from itertools import imap
imap(len, names)  # itertools.imap() returns a generator
# Out: <itertools.imap at 0x405ea20>

Результат может быть явно преобразован в list чтобы удалить различия между Python 2 и 3:

list(map(len, names))
# Out: [4, 5, 6]

map() можно заменить эквивалентным пониманием списка или выражением генератора :

[len(item) for item in names] # equivalent to Python 2.x map()
# Out: [4, 5, 6]

(len(item) for item in names) # equivalent to Python 3.x map()
# Out: <generator object <genexpr> at 0x00000195888D5FC0>

Отображение каждого значения в итерабельном

Например, вы можете принять абсолютное значение каждого элемента:

list(map(abs, (1, -1, 2, -2, 3, -3))) # the call to `list` is unnecessary in 2.x
# Out: [1, 1, 2, 2, 3, 3]

Анонимная функция также поддерживает отображение списка:

map(lambda x:x*2, [1, 2, 3, 4, 5])
# Out: [2, 4, 6, 8, 10]

или преобразование десятичных значений в проценты:

def to_percent(num):
    return num * 100

list(map(to_percent, [0.95, 0.75, 1.01, 0.1]))
# Out: [95.0, 75.0, 101.0, 10.0]

или конвертации долларов в евро (с учетом обменного курса):

from functools import partial
from operator import mul

rate = 0.9  # fictitious exchange rate, 1 dollar = 0.9 euros
dollars = {'under_my_bed': 1000,
           'jeans': 45,
           'bank': 5000}

sum(map(partial(mul, rate), dollars.values()))
# Out: 5440.5

functools.partial - удобный способ исправить параметры функций, чтобы их можно было использовать с map вместо использования lambda или создания настраиваемых функций.

Отображение значений разных итераций

Например, вычисляя среднее значение каждого i элемента из множества итераций:

def average(*args):
    return float(sum(args)) / len(args)  # cast to float - only mandatory for python 2.x

measurement1 = [100, 111, 99, 97]
measurement2 = [102, 117, 91, 102]
measurement3 = [104, 102, 95, 101]

list(map(average, measurement1, measurement2, measurement3))
# Out: [102.0, 110.0, 95.0, 100.0]

Существуют разные требования, если более чем один итерабельный передается на map зависимости от версии python:

  • Функция должна принимать столько параметров, сколько есть итераций:

    def median_of_three(a, b, c):
        return sorted((a, b, c))[1]
    
    list(map(median_of_three, measurement1, measurement2))
    

    TypeError: median_of_three () отсутствует 1 требуемый позиционный аргумент: 'c'

    list(map(median_of_three, measurement1, measurement2, measurement3, measurement3))
    

    TypeError: median_of_three () принимает 3 позиционных аргумента, но 4 даны

Python 2.x 2.0.1
  • map : отображение повторяется до тех пор, пока один итерабель еще не полностью поглощен, но принимает значение None из полностью потребляемых итераций:

    import operator
    
    measurement1 = [100, 111, 99, 97]
    measurement2 = [102, 117]
    
    # Calculate difference between elements
    list(map(operator.sub, measurement1, measurement2))
    

    TypeError: неподдерживаемый тип операндов для -: 'int' и 'NoneType'

  • itertools.imap и future_builtins.map : Отображение останавливается, как только один итеративный останавливается:

    import operator
    from itertools import imap
    
    measurement1 = [100, 111, 99, 97]
    measurement2 = [102, 117]
    
    # Calculate difference between elements
    list(imap(operator.sub, measurement1, measurement2))
    # Out: [-2, -6]
    list(imap(operator.sub, measurement2, measurement1))
    # Out: [2, 6]
    
Python 3.x 3.0.0
  • Отображение останавливается, как только один истребитель останавливается:

    import operator
    
    measurement1 = [100, 111, 99, 97]
    measurement2 = [102, 117]
    
    # Calculate difference between elements
    list(map(operator.sub, measurement1, measurement2))
    # Out: [-2, -6]
    list(map(operator.sub, measurement2, measurement1))
    # Out: [2, 6]
    

Транспонирование с помощью карты: использование параметра «Нет» в качестве аргумента функции (только для python 2.x)

from itertools import imap
from future_builtins import map as fmap # Different name to highlight differences

image = [[1, 2, 3],
         [4, 5, 6],
         [7, 8, 9]]

list(map(None, *image))
# Out: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
list(fmap(None, *image))
# Out: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
list(imap(None, *image))
# Out: [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

image2 = [[1, 2, 3],
          [4, 5],
          [7, 8, 9]]
list(map(None, *image2))
# Out: [(1, 4, 7), (2, 5, 8), (3, None, 9)]  # Fill missing values with None
list(fmap(None, *image2))
# Out: [(1, 4, 7), (2, 5, 8)]                # ignore columns with missing values
list(imap(None, *image2))
# Out: [(1, 4, 7), (2, 5, 8)]                # dito
Python 3.x 3.0.0
list(map(None, *image))

TypeError: объект «NoneType» не может быть вызван

Но есть обходное решение для получения аналогичных результатов:

def conv_to_list(*args):
    return list(args)

list(map(conv_to_list, *image))
# Out: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

Серия и параллельное сопоставление

map () - это встроенная функция, что означает, что она доступна повсюду, без необходимости использовать оператор import. Он доступен везде, как print () Если вы посмотрите пример 5, вы увидите, что мне пришлось использовать оператор импорта, прежде чем я смогу использовать довольно печатную (import pprint). Таким образом, pprint не является встроенной функцией

Отображение серии

В этом случае каждый аргумент итерабельности передается в качестве аргумента функции отображения в порядке возрастания. Это возникает, когда у нас есть только одна итерабельность для отображения, а для функции отображения требуется один аргумент.

Пример 1

insects = ['fly', 'ant', 'beetle', 'cankerworm']
f = lambda x: x + ' is an insect'
print(list(map(f, insects))) # the function defined by f is executed on each item of the iterable insects

приводит к

['fly is an insect', 'ant is an insect', 'beetle is an insect', 'cankerworm is an insect']

Пример 2.

print(list(map(len, insects))) # the len function is executed each item in the insect list

приводит к

[3, 3, 6, 10]

Параллельное отображение

В этом случае каждый аргумент функции сопоставления выталкивается из всех итераций (по одному от каждого итеративного) параллельно. Таким образом, количество предоставленных итераций должно соответствовать количеству аргументов, требуемых функцией.

carnivores = ['lion', 'tiger', 'leopard', 'arctic fox']
herbivores = ['african buffalo', 'moose', 'okapi', 'parakeet']
omnivores = ['chicken', 'dove', 'mouse', 'pig']

def animals(w, x, y, z):
    return '{0}, {1}, {2}, and {3} ARE ALL ANIMALS'.format(w.title(), x, y, z)

Пример 3.

# Too many arguments
# observe here that map is trying to pass one item each from each of the four iterables to len. This leads len to complain that
# it is being fed too many arguments
print(list(map(len, insects, carnivores, herbivores, omnivores)))

приводит к

TypeError: len() takes exactly one argument (4 given)

Пример 4.

# Too few arguments
# observe here that map is suppose to execute animal on individual elements of insects one-by-one. But animals complain when
# it only gets one argument, whereas it was expecting four.
print(list(map(animals, insects)))

приводит к

TypeError: animals() missing 3 required positional arguments: 'x', 'y', and 'z'

Пример 5.

# here map supplies w, x, y, z with one value from across the list
import pprint
pprint.pprint(list(map(animals, insects, carnivores, herbivores, omnivores)))

приводит к

 ['Fly, lion, african buffalo, and chicken ARE ALL ANIMALS',
 'Ant, tiger, moose, and dove ARE ALL ANIMALS',
 'Beetle, leopard, okapi, and mouse ARE ALL ANIMALS',
 'Cankerworm, arctic fox, parakeet, and pig ARE ALL ANIMALS']