kick the base

Houdiniと、CG技術と、日々のこと。

Python: ランダムなファイル名を持つテキストファイルを複数作成する03 -内包表記

本連載も山場です。今回は内包表記についてお話します。内包表記は実際のPythonコードを読み書きする上で必須となりますので、複数のケースを見ながら丁寧に説明していこうと思います。

環境

  • OS X 10.11.6
  • Python 3.4.4

最終的なコード

リスト内包

内包表記にはリスト内包・ジェネレータ式・セット内包・辞書内包がありますが、本記事ではリスト内包についてご説明します。

まずはじめにリスト内包の説明を簡単にすると、ループ処理を使って複雑なリストを簡単に作る方法といえます。

はじめてのリスト内包

リスト内包の書き方

はじめにリスト内包のフォーマットを書いておきます。覚えておきましょう。

[式 for 変数 in イテレート可能オブジェクト]

カタチとしてはこのようになります。

これから実際にリスト内包を使っていきますが、

  1. 先にforループの構成を考え
  2. の部分で 添字を加工する

と2段階で考えると分かりやすいと思います。

最も簡単なリスト内包

[0, 1, 2, 3, 4]

上記リストを内包表記で書き直してみます。

[i for i in range(5)]

こんな感じになりました。

なんだか逆にややこしく感じますね。しかし慣れると非常にパワフルなのでぜひこの機会に学んで行きましょう。

後半for i in range(5)の部分と前半iの部分に分けて考えます。今回はrangeオブジェクトから取り出された0〜4までの数値が変数iに入り、その要素iがそのままリストのメンバーに入っています。

f:id:kickbase:20161010001823j:plain

次の例と合わせると分かりやすいと思います。

rangeオブジェクトの要素を二乗したメンバーを持つリスト

[0, 1, 4, 9, 16]

これはリスト内包でこのように書けます。

[i ** 2 for i in range(5)]

少しメリットが出てきました!for文以下は変更ないので0〜4までの数値がiに入り、i ** 2*1が新しく作られるリストのメンバーになるわけです。

f:id:kickbase:20161010001822j:plain

添字を利用せず、単純なループとして扱う

今まで添え字を利用するケースを見てきましたが、全く同じ要素を10個持つリストなども簡単に作れます。

[13, 13, 13, 13, 13, 13, 13, 13, 13, 13]

こんなリストを作りたければ、下記のようにすればよいでしょう。

[13 for _ in range(10)]

添字は利用しないため_とし、要素の部分には直値で13を入れています。

ここでは例のため13としましたが、勿論文字列だろうがなんだろうが大丈夫です。13の替わりに'Hello'を入れれば下記のようになるでしょう。

['Hello' for _ in range(10)]

もちろん出力結果は下記のとおりです。

['Hello', 'Hello', 'Hello', 'Hello', 'Hello', 'Hello', 'Hello', 'Hello', 'Hello', 'Hello']

イテレート可能オブジェクトに文字列を使用する

今まではイテレート可能オブジェクトにrangeオブジェクトを指定してきましたが、実はPythonでは文字列もイテレート可能オブジェクトとして扱えます。

文字列を頭からひとつづつ取り出せるということです。便利ですね。やってみましょう!

['月', '火', '水', '木', '金', '土', '日']

上記リストを内包表記で作成しましょう。

[s for s in '月火水木金土日']

添字はiからsに変わりましたが同様に動作します。今回はstringの頭文字であるsとした訳です。

イテレート可能オブジェクトには'月下水木金土日'を与えています。文字列が要素のリストは手で書くとシングル・ダブルクォーテーションとカンマが多く登場するので面倒ですが、内包表記だと楽ですね。

最後に応用として下記リストを作ってみましょう。答えを見ずにまずはトライしてみてください。

['月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日', '日曜日']

応用

答えは以下のとおりです。

['{}曜日'.format(s) for s in '月火水木金土日']

前回学んだformatメソッドを利用しています。

このように内包表記を使えばかなり複雑なリストを作成することができます。今回は説明しませんが後置ifなど使うとより自由な分岐も行えます。内包表記は実際のコードを読んでいても頻出するので、覚えておくと良いでしょう。

まとめ

リスト内包のみでひとつの記事になってしまいましたが、まだまだ内包表記の世界は奥深いので、研究してみると面白いかと思います。

*1:i*2だと2倍、i**2だと二乗になります