Pythonで同じままで関数をマップするために複数の引数をどのように行うのですか?


155

次のような関数addがあるとしましょう

def add(x, y):
    return x + y

配列にマップ関数を適用したい

map(add, [1, 2, 3], 2)

セマンティクスは、配列のすべての要素に2を追加することです。ただし、このmap関数では3番目の引数にもリストが必要です。

注:簡単にするために、追加の例を示します。私の元の機能ははるかに複雑です。そしてもちろん、yin add関数のデフォルト値を設定するオプションは、呼び出しごとに変更されるため、問題外です。


20
これはLispのと全く同じである。map(add,[1,2,3],[2]*3) 一般的にはmap、最初の引数としての機能を取り込み、この機能がかかるとKの引数を、あなたがフォローアップする必要がK反復可能:addTriple(a,b,c) -> map(addTriple,[...],[...],[...])
watashiSHUN

回答:


188

1つのオプションはリスト内包表記です。

[add(x, 2) for x in [1, 2, 3]]

より多くのオプション:

a = [1, 2, 3]

import functools
map(functools.partial(add, y=2), a)

import itertools
map(add, a, itertools.repeat(2, len(a)))

1
うん、でも地図機能と比べてどれくらい速いの?
シャン

@シャン:非常によく似ています。特にadd()重要な関数の場合
スヴェンマルナッハ

2
@シャン:この場合はNumPyを見てください。これが本当に問題である場合、リスト内包表記の速度の違いはmap()どちらの方法にも役立ちません。
Sven Marnachの

3
@シャン:前に言ったように、NumPyを見てください。ループをベクトル化できる場合、ループを高速化できる可能性があります。
スヴェンマルナッハ、

1
@abarnert:OPがPython 2または3のどちらを使用しているかは不明です。この例がPython 2で機能することを確認するために、パラメーターを含めました。(注:そのmap()ような挙動zip_longest()のPython 2に、それは同じように動作している間zip()のPython 3の)
スヴェンMarnach

60

ドキュメントは、これがの主な用途であることを明示的に示唆していますitertools.repeat

オブジェクトを繰り返し返すイテレータを作成します。times引数が指定されていない限り、無期限に実行されます。map()呼び出された関数の不変パラメーターの引数として使用されます。zip()タプルレコードの不変部分を作成するためにも使用されます。

そしてlen([1,2,3])times引数としてパスする理由はありません。map最初のイテラブルが消費されるとすぐに停止するため、無限イテラブルは完全に正常です。

>>> from operator import add
>>> from itertools import repeat
>>> list(map(add, [1,2,3], repeat(4)))
[5, 6, 7]

実際、これはrepeatドキュメントの例と同じです:

>>> list(map(pow, range(10), repeat(2)))
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

これは、Pythonイテレータ用語でも完全に読み取り可能な、遅延のある関数型言語の優れたソリューションになります。


2
+1これは受け入れられた答えであるはずです。もちろん、定数やその他のリストやジェネレーターなど、任意の数のパラメーターに拡張できます。例:def f(x,y,z): \\ return '.'.join([x,y,z])次に:をlist(map(f, list('abc'), repeat('foo'), list('defgh')))返します['a.foo.d', 'b.foo.e', 'c.foo.f']
Pierre D

5
Pythonの2では、それはへの長さ引数を提供することが必要だrepeat()から、map()まで実行されます最長のイテレータはPythonのバージョンに排出されるで埋め、Noneすべての欠損値について。パラメータを渡す理由は「理由がない」と言うのは間違っています。
Sven Marnach

@SvenMarnachのコメントはマイナーではありません:Python 3Python 2の動作は大幅に異なります!
アグスティン

36

リスト内包表記を使用します。

[x + 2 for x in [1, 2, 3]]

あなたが本当に本当に本当に使いたいのmapなら、最初の引数として無名関数を与えてください:

map(lambda x: x + 2, [1,2,3])

16

マップは複数の引数を含むことができ、標準的な方法は

map(add, a, b)

あなたの質問では、それは

map(add, a, [2]*len(a))

彼の質問が何を意味していたのかわかりませんが、私はadd accept 2の値を考えています。これらの2は修正されておらず、arg1が来るようにユーザーから来るはずです。この場合、マップの下でどのようにadd(x、y)を呼び出す必要がありますか?
Bimlesh Sharma

15

正解は思ったより簡単です。単に行います:

map(add, [(x, 2) for x in [1,2,3]])

そして、タプルを取るようにaddの実装を変更します

def add(t):
   x, y = t
   return x+y

これは、両方の追加パラメーターが動的である複雑な使用例を処理できます。


14

時々、クロージャーを使用して同様の状況(pandas.applyメソッドの使用など)を解決しました

それらを使用するには、関数のラッパーを動的に定義して返す関数を定義し、パラメーターの1つを定数にします。

このようなもの:

def add(x, y):
   return x + y

def add_constant(y):
    def f(x):
        return add(x, y)
    return f

次に、任意の値add_constant(y)に追加するyために使用できる関数を返します。

>>> add_constant(2)(3)
5

これにより、パラメーターが一度に1つずつ与えられる状況でそれを使用できます。

>>> map(add_constant(2), [1,2,3])
[3, 4, 5]

編集する

どこか他の場所でクロージャ関数を書く必要がない場合は、ラムダ関数を使用してその場でそれを構築する可能性が常にあります。

>>> map(lambda x: add(x, 2), [1, 2, 3])
[3, 4, 5]

13

利用できる場合は、numpyの使用を検討します。次のタイプの操作は非常に高速です。

>>> import numpy
>>> numpy.array([1,2,3]) + 2
array([3, 4, 5])

これは、実際のアプリケーションが数学演算(ベクトル化できる)を実行していることを前提としています。


10

本当にマップ関数を使用する必要がある場合(ここでのクラス割り当てのように...)、引数を1つ指定してラッパー関数を使用し、残りを本体の元のラッパーに渡すことができます。すなわち:

extraArguments = value
def myFunc(arg):
    # call the target function
    return Func(arg, extraArguments)


map(myFunc, itterable)

汚くて醜い、それでもトリックをする


1
クロージャー、これは何かプラス1つ追加すると思います。受け入れられた答えがあるように、部分的な機能に似ています。
アーロンホール

1
myFuncする必要がありますreturn Func(arg, extraArguments)
PM 2Ring

私は修正された@ PM2Ringを立てています。コードを更新しました。
Todor Minakov

Funcはどこで定義されていますか?Funcの名前エラーが発生しているため
Nikhil Mishra

Funcは元の関数の名前です-OPの場合、タイトなadd例は次のようになります
Todor Minakov

6

私はスターマップがあなたが必要とするものだと信じています:

from itertools import starmap


def test(x, y, z):
    return x + y + z

list(starmap(test, [(1, 2, 3), (4, 5, 6)]))

あなたの例のタイプミス:list(starmap(test、[(1、2、3)、(
4、5、6

ああ、そうです。ありがとう:)
Shqi.Yang

1

map関数に複数の引数を渡すこと。

def q(x,y):
    return x*y

print map (q,range(0,10),range(10,20))

ここで、qmap()が呼び出す複数の引数を持つ関数です。両方の範囲の長さを確認してください。

len (range(a,a')) and len (range(b,b')) are equal.

1

で:nums = [1, 2, 3]

で:map(add, nums, [2]*len(nums))

でる:[3, 4, 5]


1
これは質問に対する答えを提供しません。同様の質問検索するか、ページの右側にある関連およびリンクされた質問を参照して回答を見つけることができます。関連しているが異なる質問がある場合は、新しい質問をし、この質問へのリンクを含めてコンテキストを提供します。参照:質問して、回答を得て、気を散らさないでください
Tim Diekmann '23


1
def func(a, b, c, d):
 return a + b * c % d
map(lambda x: func(*x), [[1,2,3,4], [5,6,7,8]])

関数呼び出しをラムダでラップし、スターアンパックを使用すると、任意の数の引数でマップを実行できます。


ラムダは非常に遅いので、代わりにfunctoolsを使用してください
Wang

0

別のオプションは:

results = []
for x in [1,2,3]:
    z = add(x,2)
    ...
    results += [f(z,x,y)]

この形式は、複数の関数を呼び出すときに非常に役立ちます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.