search
LoginSignup
30
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Pythonの内包表記(リストとジェネレータ式について)【追記あり】

はじめに

Pythonの内包表記は、Python独特の書き方として有名(?)だと思います。
今回は、そんな内包表記の基本的な部分についてまとめていきます。
具体的には、リスト内包表記、ジェネレータ式についてです。

リスト内包表記

リスト内包表記は特に有名かと思います。

print([i for i in range(0, 10)])

たったこれだけで0から9までの数字が格納されたリストが出力されます。

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

とても簡単に作れちゃいますね。
もちろん、もっと色々なことが可能です。

print('¥n'.join(['FizzBuzz' if i%15 == 0 else
                 'Fizz' if i%3 == 0 else
                 'Buzz' if i%5 == 0 else
                 str(i) for i in range(1, 101)]))

これはFizzBuzzですね。新しい言語を勉強し始めたら最初にやるやつ。
1から100までの数字を順に表示していき、3の倍数ならFizz、5の倍数ならBuzz、3の倍数かつ5の倍数ならFizzBuzzを数字の代わりに表示するものです。
ちなみに実行すると、1から100までを一つひとつ改行して表示します。
'¥n'.joinの部分がそれにあたりますね。

というか、自分で書いておいていうのも何ですが、かなり強引なコードですね……。
これはですね、次にもっと良い書き方を紹介するので、あえてこんな感じで書いています。
それでは次に行きましょう。

ジェネレータ式

ジェネレータ式……難しそうな言葉が登場しましたね……。
ジェネレータ式が何なのかを詳しく説明するには、ジェネレータとは何かを説明しなければならず、さらにジェネラータを説明するためにはイテレータについて説明しなければならなず、さらにイテレータを説明すqsうぇdrftgyふじこlp;@:(今度別の記事として投稿するかもです)

簡単に言うと、括弧内でさっと関数をつくってさっと使えちゃう便利なやつです。

print(i for i in range(0,10))

さっきのリスト内包表記とほぼ同じように感じますね。
違いは[ ]がないことですね。
この時、一体どのようにして出力されるのでしょうか?

<generator object <genexpr> at 0x10d747b48>

出力はこちら。
さっきのリストとは全然違いますね!
これでは意味が全くわかりませんので、内包表記で書くときは[ ]を忘れないようにしてくださいね。

しかしながら、このジェネレータ式が便利な時も結構多いのです。

print('¥n'.join((i%3 == 0)*'Fizz' + (i%5 == 0)*'Buzz' or str(i) for i in range(1, 101)))

はい。一行の情報量がかなり多い気がしますが、一行で何かのコードが書かれましたね。
お察しの通り、これはFizzBuzzです。
出力も、先ほどと全く同じ形式で出力されます。

こんな書き方、リスト内包表記ではできませんね!(ですよね?)
リスト内包表記の上のコードでも無理やり1行にできますが……見にくいのは嫌ですよね。
(リスト内包表記もジェネレータ式も80文字超えちゃうので実際には改行が必要です)

感想

今回は2種類のみの紹介になりましたが、これだけもかなり色々できそうですよね!
何より内包表記を使うとPythonicなコードっぽくて好きです。
あとは、ジェネレータ式が使えそうなところは積極的に使ったほうがいいと思います。リスト内包表記だといちいちリスト作っちゃうので。

以上です。

追記(2015/12/2)

print('¥n'.join((i%3 == 0)*'Fizz' + (i%5 == 0)*'Buzz' or str(i) for i in range(1, 101)))

こんな書き方、リスト内包表記ではできませんね!(ですよね?)

申し訳ありません、できます。

print('¥n'.join([(i%3 == 0)*'Fizz' + (i%5 == 0)*'Buzz' or str(i) for i in range(1, 101)]))

これでも全く同じ出力が得られます。

ここ間違えちゃいけないだろってところを盛大に間違えてしまい、この記事の目的が完全に失われたような気さえしますね……。
以後気をつけます。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
30
Help us understand the problem. What are the problem?