ぬらくら日記

ぬらりくらりと過ごすプログラマが書く徒然日記。

python3はリスト内包表記とmapどっちがいいか?

おはようございます、ぬらくらです。

昨日、友達とこんな話をしていました。

僕「リスト内包表記って結局写像じゃん? mapと同じだよね」

友「じゃあ何が違うん?」

ということで試してみました!

文法

まず、文法ではどのような差があるでしょうか?

とりあえず、0~999を2乗するプログラムを書いてみます!

リスト内包表記
[i**2 for i in range(100)]
map
map(lambda i:i**2,range(100))

書き方は全然違いますね。

特に、map型は第一引数が関数であるため、lambda式を用いている点が違います。

速度比較

次に、上記の2コードの速度比較をしてみましょう。

リスト内包表記
In [16]: %timeit [i**2 for i in range(100)]
19.9 µs ± 311 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
map
In [17]: %timeit map(lambda i: i**2, range(1000))
295 ns ± 2.46 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

この場合、mapのほうが早いですね。

ではmapのほうがいいのでしょうか?

いえ、根本的に大きな違いがあります!

mapはmapオブジェクト、リスト内包表記はリストオブジェクト

これはいったいどういうことでしょうか?

実は,map型は宣言された時点では実行されていない、mapオブジェクトとなっています。

ipythonで確認すると、

In [14]: map(lambda i: i**2, range(1000000))
Out[14]: <map at 0x7fe661fa9518>

となっており実行されていません。

これの最大のメリットは、メモリを確保しないことです。

逐次実行するため、一括で大規模なメモリを確保しないのがメリットです。

ということで、 - リストを表現したい場合はリスト内包表記 - イテレータを作りたい場合はmap

といったような使い分けが適切なのではと思います!

おまけ

mapをリストにキャストした場合の時間を図ってみました

In [19]: %timeit list(map(lambda i: i**2, range(100)))
24.6 µs ± 169 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

リスト内包表記よりも時間がかかりますね。 逆にリストにpushする形だと

In [30]: %%timeit
    ...: a = []
    ...: for i in range(100):
    ...:     a.append(i)
    ...:
4.62 µs ± 28.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

え、最速?!

途中から最適化がかかって、繰り返しの場合は爆速になってる…??

理由がわかる方がいたら教えてください…

自己紹介

はじめまして、ぬらくらと申します。

今日からこのブログを始めようと思います。

  1. 自己紹介
  2. ブログを始めたきっかけ
  3. 終わりに

といった順番で話したいと思うので、ぜひ最後まで読んでいってください!

自己紹介

経歴

  • 1998年1月26日生まれ(現在20歳)
  • 神戸生まれ神戸育ち(と言っても辺境ですが…)
  • 高専出身
  • 大阪のITベンチャーに就職, 現在はプログラマを務める

    趣味

  • プログラミング(好きじゃなきゃプログラマやってない)
  • 読書
  • 将棋
  • 雑談
  • etc…

プログラミングに関して

ブログを始めたきっかけ

端的に言うと、自分がどんな人間か周りに知ってもらって、自分がちょっとでも周りの役に立てることがあるか探すためです。

半年前、プロのブロガーさんとお話をする機会がありました。
その時に、「どんなことでも興味を持つ人間はいる」といったようなことを聞きました。

例えば、僕は将棋が好きですが、段位を獲得できるほどは強くありません。
しかし、初学者に教えるくらいならば十分にできます。
また、プログラミングも就職したばかりですが、高校生や大学生に教えることならできます。
このように、時分の力量に合わせてターゲットを考えれば、いいんだよという話でした。

なので、僕のできることややりたいことをどんどん投稿していこうと思います。
そして、そこに価値を感じていただけたらなと思います。

終わりに(はじめに?)

僕はこの記事からどんどん投稿を増やしていこうと思っています。
この記事を読んでくださった皆さん、ありがとうございました。

投稿の内容は毎回バラバラになると思いますが、よければ読んでください!

以上です。
またのご来店をお待ちしております。