質問

使用することを好む理由はありますか map() リスト内包を超えていますか、それともその逆ですか?一般的にどちらかが他方よりも効率的ですか、それとも一般的によりPython的だと考えられますか?

役に立ちましたか?

解決

(あなたは目的のためにラムダを作りますが、マップ内の同じ機能とlistcompを使用していないとき)

mapは、いくつかのケースでは微視的に速いかもしれません。リスト内包はpythonistasはそれらをより直接的かつ明確に検討します。

(すべてではない)他のケースでは速くなり、最も可能

とまったく同じ機能を使用してマップの小さな速度の利点の例:

$ python -mtimeit -s'xs=range(10)' 'map(hex, xs)'
100000 loops, best of 3: 4.86 usec per loop
$ python -mtimeit -s'xs=range(10)' '[hex(x) for x in xs]'
100000 loops, best of 3: 5.58 usec per loop
マップはラムダを必要とするときの性能比較が完全に逆取得する方法の

例:

$ python -mtimeit -s'xs=range(10)' 'map(lambda x: x+2, xs)'
100000 loops, best of 3: 4.24 usec per loop
$ python -mtimeit -s'xs=range(10)' '[x+2 for x in xs]'
100000 loops, best of 3: 2.32 usec per loop

他のヒント

の場合

  • 普通の場合:ほとんどいつも、ご利用についてはリストの理解について python できないことをしてい初心者プログラマーを読んであげます。(この限りではありませんが、その他の言語のイディオムが適用されます。) いつもより明らかに何をやっているpythonプログラマー、リストの理解のデファクトスタンダードにpythonのための繰り返し処理;その が期待.
  • 少ない共通の場合:ただし、 既に定義される関数, しばらくリーズナブルにご利用 map, ものと考えられる'unpythonic'.例えば、 map(sum, myLists) より優雅さ/エッセイは英語で書より [sum(x) for x in myLists].お得に優雅ないダミー変数(例えば sum(x) for x... または sum(_) for _... または sum(readableName) for readableName... する回だけに対して繰り返し処理を実行する.同じ引数を持のために filterreduce とから、 itertools モジュール:持っている人は、手続きをすれば機能お手軽に、見ていて気分が良いものいくつかの機能プラグインです。この利益で読みやすいくつかの状況で、失うのでその他(例:初心者プログラマー、複数の引数なし)...が読みやすくするための工夫コードによって変わっております。
  • ほとんどない:使用する場合がありまし map 機能としての純粋な抽象機能な機能性プログラミング、がんマッピング map, やcurrying map, 他の利益からの話 map としての機能です。にウ例えば、元インタと呼ばれ fmap generalizesマッピングの任意のデータ構造です。これは非常に珍しいpythonでは、pythonの文法は辛いことは沢山のご利用発電機-スタイルの話を繰り返し処理;できな一般化です。(取ることが多いので、良いも悪いものです。) できるのではないでしょうかって珍しいpython例が map(f, *lists) リーズナブルないことだと思います。最近の例でいくとい sumEach = partial(map,sum), では、ワーライナーは非常にほぼ相当する:

def sumEach(myLists):
    return [sum(_) for _ in myLists]
  • だけを使用 forループ:できるものだけを使用します。ないものとしての機能-プログラミングの視点でも非局所変数のコードをより明確になプログラミング言語など、ワニやpythonのような、人の使用をコードすることができてうれしいです。のため-ループまた、一般的に、最も効率的にできなだけ電源をオンにする"という複雑な操作ないビルをリストのようなリスト理解と地図の最適化した例総括的なツリーなど) --少なくとも効率的な面でのメモリは必ずしもの時間を、思最低でも一定の係数限りのものがあ病態ごみ収集hiccuping).

"Pythonism"

嫌いのpythonic"がないからとpythonic常に優雅なった。しかし、 mapfilter と同様の機能を有 itertools モジュール)と思われるunpythonicのです。

怠惰

の効率化のほうプログラミングの建設、 地図れ、怠けること, をとるものぐ。することができないこと( python3 やコンピューターがないの記憶喪失にすべての未保存のデータ:

>>> map(str, range(10**100))
<map object at 0x2201d50>

やってみることリストが学生の理解度

>>> [str(n) for n in range(10**100)]
# DO NOT TRY THIS AT HOME OR YOU WILL BE SAD #

なお一覧を理解しても本質的に怠惰な pythonにはを選択し、それらを実施するために非lazy.しかし、pythonは怠け者リストの理解の発電機を表現して

>>> (str(n) for n in range(10**100))
<generator object <genexpr> at 0xacbdef>

できる基本を考える [...] 書式と通電式のリストのコンストラクタのように、 list(x for x in range(5)).

簡単なり、逆例

from operator import neg
print({x:x**2 for x in map(neg,range(5))})

print({x:x**2 for x in [-y for y in range(5)]})

print({x:x**2 for x in (-y for y in range(5))})

リストの理解は非lazyなる場合がありメモリを使用しない限り発電機を理解).の角ブラケット [...] ることが多いものかき混乱のしるしをつけることになる。一方、あまりとなっている冗長などタイピング [x for x in....どのく反復子の変数、リストの理解は、通常、確かない場合にはインデントコード.だけど、常にインデントコード.

print(
    {x:x**2 for x in (-y for y in range(5))}
)

物を壊した:

rangeNeg5 = (-y for y in range(5))
print(
    {x:x**2 for x in rangeNeg5}
)

効率の比較python3

map はlazy:

% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=map(f,xs)'
1000000 loops, best of 3: 0.336 usec per loop            ^^^^^^^^^

その場合、使用する場合としない全てのデータ、またはわからない時などに必要なデータ, map にpython3(発電機を表現python2はpython3)を避ける算定値までの最後の瞬間が必要です。通常、これは通常、上回台を使用 map.下振れることは非常に限られたpythonに対しても機能言語:きのこの利益にアクセスする場合データは左から右の"序"ではpythonの発電機を表現できる評価の x[0], x[1], x[2], ....

しかしをしようするには、こちらをクリックして前の作機能 f したいと考えて map, いは無視さぼの map により直ちに強制力の評価 list(...).しかも興味深い結果:

% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=list(map(f,xs))'                                                                                                                                                
10000 loops, best of 3: 165/124/135 usec per loop        ^^^^^^^^^^^^^^^
                    for list(<map object>)

% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=[f(x) for x in xs]'                                                                                                                                      
10000 loops, best of 3: 181/118/123 usec per loop        ^^^^^^^^^^^^^^^^^^
                    for list(<generator>), probably optimized

% python3 -mtimeit -s 'xs=range(1000)' 'f=lambda x:x' 'z=list(f(x) for x in xs)'                                                                                                                                    
1000 loops, best of 3: 215/150/150 usec per loop         ^^^^^^^^^^^^^^^^^^^^^^
                    for list(<generator>)

結果に含まれている、またはそのAAA/BBB/CCC場として実施したものに頃-2010インテルワークステーションpython3.?.?, BおよびCにより行った頃-2013AMDワークステーションpython3.2.1でき、さらに、異なるハードウェア結果を見ると、地図リストの理解は同等の性能を最も強く影響を受けその他のランダム。このことが可能だき沈みえるものと考えていますリストの理解 [...] をどのように絡んでいるのかを調べ発表 (...), map も効率のよい発電機の表現ものと仮定すると全ての値で評価/使用されます。

現だけではないんだよるこれらの試験と非常に単純な機能の機能);しかしこれは微細でこの機能は複雑で、その性能架が無視できる他の要因についてプログラム。という名称になっていますのも面白い試験その他のうた f=lambda x:x+x)

だが、当時の読みpythonの組み立てに利用できます dis モジュールがそのこともう裏側

>>> listComp = compile('[f(x) for x in xs]', 'listComp', 'eval')
>>> dis.dis(listComp)
  1           0 LOAD_CONST               0 (<code object <listcomp> at 0x2511a48, file "listComp", line 1>) 
              3 MAKE_FUNCTION            0 
              6 LOAD_NAME                0 (xs) 
              9 GET_ITER             
             10 CALL_FUNCTION            1 
             13 RETURN_VALUE         
>>> listComp.co_consts
(<code object <listcomp> at 0x2511a48, file "listComp", line 1>,)
>>> dis.dis(listComp.co_consts[0])
  1           0 BUILD_LIST               0 
              3 LOAD_FAST                0 (.0) 
        >>    6 FOR_ITER                18 (to 27) 
              9 STORE_FAST               1 (x) 
             12 LOAD_GLOBAL              0 (f) 
             15 LOAD_FAST                1 (x) 
             18 CALL_FUNCTION            1 
             21 LIST_APPEND              2 
             24 JUMP_ABSOLUTE            6 
        >>   27 RETURN_VALUE

 

>>> listComp2 = compile('list(f(x) for x in xs)', 'listComp2', 'eval')
>>> dis.dis(listComp2)
  1           0 LOAD_NAME                0 (list) 
              3 LOAD_CONST               0 (<code object <genexpr> at 0x255bc68, file "listComp2", line 1>) 
              6 MAKE_FUNCTION            0 
              9 LOAD_NAME                1 (xs) 
             12 GET_ITER             
             13 CALL_FUNCTION            1 
             16 CALL_FUNCTION            1 
             19 RETURN_VALUE         
>>> listComp2.co_consts
(<code object <genexpr> at 0x255bc68, file "listComp2", line 1>,)
>>> dis.dis(listComp2.co_consts[0])
  1           0 LOAD_FAST                0 (.0) 
        >>    3 FOR_ITER                17 (to 23) 
              6 STORE_FAST               1 (x) 
              9 LOAD_GLOBAL              0 (f) 
             12 LOAD_FAST                1 (x) 
             15 CALL_FUNCTION            1 
             18 YIELD_VALUE          
             19 POP_TOP              
             20 JUMP_ABSOLUTE            3 
        >>   23 LOAD_CONST               0 (None) 
             26 RETURN_VALUE

 

>>> evalledMap = compile('list(map(f,xs))', 'evalledMap', 'eval')
>>> dis.dis(evalledMap)
  1           0 LOAD_NAME                0 (list) 
              3 LOAD_NAME                1 (map) 
              6 LOAD_NAME                2 (f) 
              9 LOAD_NAME                3 (xs) 
             12 CALL_FUNCTION            2 
             15 CALL_FUNCTION            1 
             18 RETURN_VALUE 

今年も、見に来て下さいねを用い [...] 書式によ list(...).残念なの map クラスは、少し不透明さに分解ができまによる当社速試験とします。

Python2:のものを使用できる mapfilter 代わりにリストの理解.

An 目的 理由は。うものではありません"Pythonic"です:
必要な機能/lambdas引数として、 新しい範囲.

んで頂いており噛んだこのた:

for x, y in somePoints:
    # (several lines of code here)
    squared = [x ** 2 for x in numbers]
    # Oops, x was silently overwritten!

がわかったと

for x, y in somePoints:
    # (several lines of code here)
    squared = map(lambda x: x ** 2, numbers)

そして思っています。

といえるのかもしれませんでしたがんのために同じ変数名が同じです。

ん.をコードしたもの xsんと同じです。
その後、 移転 内側のブロックを別のコードに問題が(読み:問題のメンテナンス中は開発)とは予想していなかったのです。

あり だことは一切ございませんこの間違い そしてリストの理解がより美しく。
だから個人の経験から見たその他の違いにも起こるのに十分な時代だと思うのプライベートビーチがあり、痛みとなっておりこれらのバグのクリープへのコードです。

結論:

使用 mapfilter.い微妙なく、診断の範囲に関連させてしまいます。

注:

も忘れずに使用を検討 imapifilteritertools った場合に、適切なご現できます。●

実際、 map リスト理解の行動のものとは大きく異なるPythonの3言語です。しくは以下のPython3プログラム:

def square(x):
    return x*x
squares = map(square, [1, 2, 3])
print(list(squares))
print(list(squares))

あなたが期待するかもしれない印刷をライン"[1,4,9]"が代わりに印"[1,4,9]"に続いて"[]".初めて見 squares そうして行動する列の三つの要素が多いのですが、二回目の時として空にします。

のPython2言語 map を返しまplain oldリストのように、リストの理解なの両方の言語である。世界の戻り値の map Python3( imap Python2)リストでないすべての反復子!

の要素を消費がきに対して繰り返し処理を実行する反復子とは異なり対して繰り返し処理を実行す。その squares う空前 print(list(squares)) ます。

をまとめ:

  • 処理時反復子は、まうひとつ忘れてはいけないな状態やその変異としてお送りします。
  • リストの予測からの変更のみがきを明示的に変異していその 容器.
  • やボーナス:数値、文字列、タプルはも予想から変更はできませんので、その 価値観.

私は、リストの内包表記が一般mapよりも私が何をしようとしているのより表現されている見つける - 。彼らは両方とも、それを成し遂げるが、前者は複雑lambda表現何ができるかを理解しようとしているの精神的な負担を節約できます。

グイドは、Pythonに受け入れることについて、彼最も後悔のものとしてlambdasと機能的な機能を示していますどこに、彼らは未だという主張を作ることができるように、

インタビューが、(私はそれがぶっきらぼう見つけることができません)どこかにそこにもありますそのおかげでニシキヘビ。

ここに1つの可能なケースがあります:

map(lambda op1,op2: op1*op2, list1, list2)

対ます:

[op1*op2 for op1,op2 in zip(list1,list2)]

私は)(郵便番号を推測していますあなたはリスト内包の代わりに、マップを使う、という場合でふけるする必要が不幸と不要なオーバーヘッドです。誰かが肯定的か否定的かどうか、これを明確にしている場合は素晴らしいことだ。

する予定がある場合を作る非同期並列、または分散型コードましょう。 map 渡りリスト内包していくことも非同期並列、または配布パッケージを提供 map 機能過負荷のpythonの map.その後に適切な map 機能はコードがない可能性がありますの変更オリジナルのシリアルコードで行(など)。

したがって、Python 3 以降、 map() はイテレータであるため、何が必要なのかに留意する必要があります。イテレータまたは list 物体。

すでに @AlexMartelli として 言及された, map() を使用しない場合に限り、リスト内包表記よりも高速です。 lambda 関数。

時間の比較をいくつか紹介します。

Python 3.5.2 と CPython
使ったことがある ジュピターノート そして特に %timeit 組み込みのマジックコマンド
測定:s == 1000 ミリ秒 == 1000 * 1000 μs = 1000 * 1000 * 1000 ナノ秒

設定:

x_list = [(i, i+1, i+2, i*2, i-9) for i in range(1000)]
i_list = list(range(1000))

組み込み関数:

%timeit map(sum, x_list)  # creating iterator object
# Output: The slowest run took 9.91 times longer than the fastest. 
# This could mean that an intermediate result is being cached.
# 1000000 loops, best of 3: 277 ns per loop

%timeit list(map(sum, x_list))  # creating list with map
# Output: 1000 loops, best of 3: 214 µs per loop

%timeit [sum(x) for x in x_list]  # creating list with list comprehension
# Output: 1000 loops, best of 3: 290 µs per loop

lambda 関数:

%timeit map(lambda i: i+1, i_list)
# Output: The slowest run took 8.64 times longer than the fastest. 
# This could mean that an intermediate result is being cached.
# 1000000 loops, best of 3: 325 ns per loop

%timeit list(map(lambda i: i+1, i_list))
# Output: 1000 loops, best of 3: 183 µs per loop

%timeit [i+1 for i in i_list]
# Output: 10000 loops, best of 3: 84.2 µs per loop

ジェネレーター式などもあります。参照してください。 PEP-0289. 。それで、比較に追加すると便利だと思いました

%timeit (sum(i) for i in x_list)
# Output: The slowest run took 6.66 times longer than the fastest. 
# This could mean that an intermediate result is being cached.
# 1000000 loops, best of 3: 495 ns per loop

%timeit list((sum(x) for x in x_list))
# Output: 1000 loops, best of 3: 319 µs per loop

%timeit (i+1 for i in i_list)
# Output: The slowest run took 6.83 times longer than the fastest. 
# This could mean that an intermediate result is being cached.
# 1000000 loops, best of 3: 506 ns per loop

%timeit list((i+1 for i in i_list))
# Output: 10000 loops, best of 3: 125 µs per loop

必要です list 物体:

カスタム関数の場合はリスト内包表記を使用し、使用します list(map()) 組み込み関数がある場合

必要ありません list オブジェクトの場合は、反復可能なオブジェクトだけが必要です。

常に使用する map()!

私はほとんどのPython的な方法ではなくmapfilterのリストの内包表記を使用することを検討してください。その理由は、リストの内包表記はmapfilterより明確であるということです。

In [1]: odd_cubes = [x ** 3 for x in range(10) if x % 2 == 1] # using a list comprehension

In [2]: odd_cubes_alt = list(map(lambda x: x ** 3, filter(lambda x: x % 2 == 1, range(10)))) # using map and filter

In [3]: odd_cubes == odd_cubes_alt
Out[3]: True

もし見ての通り、理解がlambdaのニーズなどの追加map表現を必要としません。 mapフィルタリングを可能にするfilterを必要とするまた、理解も容易にフィルタリングを可能にする。

私は、オブジェクトのメソッドを呼び出すための3つの方法を比較する簡単なテストを実行しました。時間差は、この場合には、ごくわずかであると、当該機能の問題である(@Alexマルテッリの応答を参照) 。ここで、私は次の方法を見ます:

# map_lambda
list(map(lambda x: x.add(), vals))

# map_operator
from operator import methodcaller
list(map(methodcaller("add"), vals))

# map_comprehension
[x.add() for x in vals]

Iは、リストのサイズを増大させるために、両方の整数(Pythonのvals)と浮動小数点数(Pythonのint)の(可変floatに格納されている)のリストを見ました。以下のダミークラスDummyNumが考慮されます:

class DummyNum(object):
    """Dummy class"""
    __slots__ = 'n',

    def __init__(self, n):
        self.n = n

    def add(self):
        self.n += 5

具体的には、add方法。 __slots__属性は、メモリサイズを縮小、クラス(属性)によって必要な合計メモリを定義するためのPythonでシンプルな最適化です。 ここでは結果のプロットはあります。

" マッピングのPythonオブジェクトのメソッドのパフォーマンス> 先に述べたように、

、使用される技術は、最小限の違いは、あなたが最もあなたに読みやすい、または特定の状況である方法でコーディングする必要があります。この場合、リスト内包(map_comprehension技術)は、特に短いリストで、オブジェクト内の追加の両方のタイプの最速です。

プロットとデータを生成するために使用されるソースのこのペーストビンを訪問します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top