Python Language
地図機能
サーチ…
構文
- map(関数、iterable [、* additional_iterables])
- future_builtins.map(関数、iterable [、* additional_iterables])
- itertools.imap(function、iterable [、* additional_iterables])
パラメーター
パラメータ | 詳細 |
---|---|
関数 | マッピングのための関数(iterablesがあるのと同じくらい多くのパラメータを取る必要があります)( 位置限定 ) |
繰り返し可能な | 関数は反復可能( 位置指定のみ )の各要素に適用され、 |
* 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]
複数のiterableがある場合は、 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
よりも速くなる可能性があるため、速度が重要な場合は両方のアプローチの時間をテストします。
map、itertools.imap、future_builtins.mapの基本的な使い方
マップ関数は、関数型プログラミングに使用されるPythonビルトインの中で最も単純なものです。 map()
は、指定された関数を反復可能な要素の各要素に適用します。
names = ['Fred', 'Wilma', 'Barney']
map(len, names) # map in Python 3.x is a class; its instances are iterable
# Out: <map object at 0x00000198B32E2CF8>
future_builtins
モジュールには、Python 3互換map
が含まれて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>
あるいは、Python 2ではitertools
imap
を使ってジェネレータを得ることができます
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とPython 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>
iterableの各値のマッピング
たとえば、各要素の絶対値を取ることができます。
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
は、関数のパラメータをlambda
を使うのではなくmap
で使うか、カスタマイズされた関数を作るかのように修正する便利な方法です。
異なるiterablesの値のマッピング
例えば、複数のイテラブルの各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]
Pythonのバージョンに応じて、複数のiterableがmap
渡された場合の要件は異なります。
この関数は、iterableと同じ数のパラメータを取る必要があります。
def median_of_three(a, b, c): return sorted((a, b, c))[1] list(map(median_of_three, measurement1, measurement2))
TypeError:median_of_three()missing 1必要な位置引数: 'c'
list(map(median_of_three, measurement1, measurement2, measurement3, measurement3))
TypeError:median_of_three()は3つの位置引数を取るが、4つが与えられた
map
:1つのiterableがまだ完全には消費されていないが、完全に消費されたiterableから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
つの反復可能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]
1つの反復可能関数が停止するとすぐにマッピングは停止します。
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]
マップを使った転移:関数の引数として "None"を使う(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: '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'ステートメントを使用することなくどこでも使用できます。例5を見ると、pretty print(import pprint)を使用する前にimport文を使用しなければならないことがわかります。したがって、pprintは組み込み関数ではありません
シリーズマッピング
この場合、イテラブルの各引数は、マッピング関数の引数として昇順に供給されます。これは、マッピングする反復可能性が1つしかなく、マッピング関数が単一の引数を必要とする場合に発生します。
例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]
パラレルマッピング
この場合、マッピング関数の各引数は、すべてのiterable(各iterableから1つ)から並列に引き出されます。したがって、提供されるイテラブルの数は、関数が必要とする引数の数と一致しなければなりません。
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']