こんにちは、かずやです。
先日、AWSアカウントにある全てのCloudFormationスタックの削除保護を有効化するスクリプトを書きました。
実際のスクリプトは会社のブログに書いてあります
【Pythonスクリプト】アカウント内のCloudFormationスタックを全部一気に削除保護する
この記事の中で、filterやmapを使ってjsonから目的の値を取得しているのですが、Pythonを書くならリスト内包表記というもっと便利なものがあるよーと先輩に教えていただきました。
ということで今回は、Pythonのリスト内包表記のご紹介。
リスト内包表記とは
Pythonが独自に持っている記法で、特定条件のリストを簡単に生成できるものになります。
例えば、0から特定の値までのリストを生成する場合、
1 2 3 |
array = [] for i in range(10): array.append(i) |
という書き方が考えられます。(当然、list()を使う方法もありますが)
これをリスト内包表記で書き直すと以下のようになります。
1 |
array = [i for i in range(10)] |
for文を用いた場合、初期化処理+値の追加処理という書き方になりますが、リスト内包表記では、値の追加処理をリスト内に書きます。
処理を一行にまとめて記述することができるのはなかなか嬉しいですね。
filter, map処理の置き換え
先ほど紹介した会社のブログでは、削除保護を有効化したいスタックの名前の一覧を取得するために、
- describe-stacksによりstackに関する情報を一括取得
- filterにより条件に合致するリストを取得
- mapにより名前のみのリストを取得
という処理を行なっています。該当箇所を抜粋すると、以下。
1 2 3 |
stacks = client.list_stacks(**params)['StackSummaries'] # stack情報取得 root_stacks = list(filter(lambda stack: 'ParentId' not in stack, stacks)) # ParentIdをもつStackのみを取得 stack_names = list(map(lambda stack: stack['StackName'], root_stacks)) # 名前のみのリストを取得 |
特にfilterとmap処理では、lambda式を使った書き方となっており若干の分かりにくさは否めません。
これをfor文で普通に書くとこんな感じ。
1 2 3 4 5 6 |
stack_names = [] for stack in stacks: if 'ParentId' not in stack: continue stack_names.append(stack['name']) |
…改めて書いてみて思ったのですが、行数大して変わらないし、こっちの方が処理内容分かりやすい気がしますね…。おかしいな…。
き、気をとり直して最後にリスト内包表記を。
1 |
stack_names = [stack['name'] for stack in stacks if 'ParentId' not in stack] |
はい、ザクっとワンライナーで書けました。気持ちいい!
またfilterとmapを書いたときに比べるとかなり見やすいのではないでしょうか。普段使っているforやif文が用いられるので比較的とっつきやすくなる気がします。
見た目の違いもありながら、どうやらappendを繰り返すよりもリスト内包表記の方が処理速度が上という話もあるらしく。
処理をまとめられて速度も上がるなら、いいことづくしですね。
終わりに
Pythonにはあまり触れてきていなかったのですが、結構便利な記法もあるもんやなーという感じがしましたね。
AWS触っているとしょっちゅうJSONの処理を行うので、リスト内包表記は割と活用場面があるんじゃないかな。
ちょこちょここういうTipsも上げていきますね。
ではではっ!