Python Language
Funkcja mapy
Szukaj…
Składnia
- mapa (funkcja, iterowalna [, * dodatkowe_poznania])
- future_builtins.map (funkcja, iterowalne [, * dodatkowe_poznania])
- itertools.imap (funkcja, iterowalny [, * dodatkowe_poznania])
Parametry
Parametr | Detale |
---|---|
funkcjonować | funkcja mapowania (musi przyjmować tyle parametrów, ile jest iterowalnych) ( tylko pozycyjne ) |
iterowalne | funkcja jest stosowana do każdego elementu iterowalnego ( tylko pozycyjnego ) |
* dodatkowe_podstawy | zobacz iterowalne, ale tyle, ile chcesz ( opcjonalnie , tylko pozycja ) |
Uwagi
Wszystko, co można zrobić za pomocą map
można również zrobić ze comprehensions
:
list(map(abs, [-1,-2,-3])) # [1, 2, 3]
[abs(i) for i in [-1,-2,-3]] # [1, 2, 3]
Chociaż potrzebujesz zip
jeśli masz wiele iteracji:
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]
Rozumienie listy jest wydajne i w wielu przypadkach może być szybsze niż map
, więc przetestuj czasy obu podejść, jeśli prędkość jest dla Ciebie ważna.
Podstawowe użycie map, itertools.imap i future_builtins.map
Funkcja mapowania jest najprostsza spośród wbudowanych Pythona używanych do programowania funkcjonalnego. map()
stosuje określoną funkcję do każdego elementu w iterowalnym:
names = ['Fred', 'Wilma', 'Barney']
map(len, names) # map in Python 3.x is a class; its instances are iterable
# Out: <map object at 0x00000198B32E2CF8>
map
zgodna z Python 3 znajduje się w module future_builtins
:
from future_builtins import map # contains a Python 3.x compatible map()
map(len, names) # see below
# Out: <itertools.imap instance at 0x3eb0a20>
Alternatywnie, w Pythonie 2 można użyć imap
z itertools
aby uzyskać generator
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>
Wynik można jawnie przekonwertować na list
aby usunąć różnice między Pythonem 2 i 3:
list(map(len, names))
# Out: [4, 5, 6]
map()
można zastąpić równoważnym zrozumieniem listy lub wyrażeniem generatora :
[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>
Mapowanie każdej wartości w iterowalnym
Na przykład możesz wziąć wartość bezwzględną każdego elementu:
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]
Anonimowa funkcja obsługuje również mapowanie listy:
map(lambda x:x*2, [1, 2, 3, 4, 5])
# Out: [2, 4, 6, 8, 10]
lub konwertując wartości dziesiętne na wartości procentowe:
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]
lub przeliczając dolary na euro (biorąc pod uwagę kurs wymiany):
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
to wygodny sposób na ustalenie parametrów funkcji, dzięki czemu można ich używać z map
zamiast z wykorzystaniem lambda
lub tworzenia niestandardowych funkcji.
Wartości mapowania różnych iteracji
Na przykład obliczanie średniej każdego i
elementu wielu iteracji:
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]
Istnieją różne wymagania, jeśli więcej niż jedna iterowalna jest przekazywana do map
zależności od wersji Pythona:
Funkcja musi przyjmować tyle parametrów, ile jest iterowalnych:
def median_of_three(a, b, c): return sorted((a, b, c))[1] list(map(median_of_three, measurement1, measurement2))
TypeError: median_of_three () brakuje 1 wymaganego argumentu pozycyjnego: „c”
list(map(median_of_three, measurement1, measurement2, measurement3, measurement3))
TypeError: median_of_three () przyjmuje 3 argumenty pozycyjne, ale podano 4
map
: mapowanie iteruje tak długo, jak jedna iterowalna nadal nie jest w pełni wykorzystana, ale zakłada, żeNone
z w pełni wykorzystanych iteracji:import operator measurement1 = [100, 111, 99, 97] measurement2 = [102, 117] # Calculate difference between elements list(map(operator.sub, measurement1, measurement2))
TypeError: nieobsługiwane typy operandów dla -: „int” i „NoneType”
itertools.imap
ifuture_builtins.map
: Mapowanie zatrzymuje się, gdy tylko jeden iterowalny zatrzymuje się: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]
Mapowanie kończy się, gdy tylko jeden iterowalny zatrzymuje się:
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]
Transponowanie za pomocą mapy: użycie „Brak” jako argumentu funkcji (tylko 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
list(map(None, *image))
TypeError: Obiekt „NoneType” nie jest wywoływalny
Ale istnieje obejście mające na celu uzyskanie podobnych wyników:
def conv_to_list(*args):
return list(args)
list(map(conv_to_list, *image))
# Out: [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
Mapowanie szeregowe i równoległe
map () to wbudowana funkcja, co oznacza, że jest dostępna wszędzie bez potrzeby używania instrukcji „import”. Jest dostępny wszędzie tak jak print (). Jeśli spojrzysz na przykład 5, zobaczysz, że musiałem użyć instrukcji importu, zanim mogłem użyć ładnego wydruku (import pprint). Dlatego pprint nie jest funkcją wbudowaną
Mapowanie serii
W takim przypadku każdy argument iterowalny jest dostarczany jako argument funkcji mapującej w porządku rosnącym. Powstaje, gdy mamy tylko jedną iterowalną mapę, a funkcja mapowania wymaga jednego argumentu.
Przykład 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
prowadzi do
['fly is an insect', 'ant is an insect', 'beetle is an insect', 'cankerworm is an insect']
Przykład 2
print(list(map(len, insects))) # the len function is executed each item in the insect list
prowadzi do
[3, 3, 6, 10]
Równoległe mapowanie
W tym przypadku każdy argument funkcji mapowania jest pobierany równolegle ze wszystkich iteracji (po jednym z każdej iterowalnej). Tak więc liczba dostarczonych iteracji musi być zgodna z liczbą argumentów wymaganych przez funkcję.
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)
Przykład 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)))
prowadzi do
TypeError: len() takes exactly one argument (4 given)
Przykład 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)))
prowadzi do
TypeError: animals() missing 3 required positional arguments: 'x', 'y', and 'z'
Przykład 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)))
prowadzi do
['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']