Python と C++ の違いについて語ってみる【リスト内包表記】~副作用のないリストの初期化~
リスト内包表記とはなんぞや
Python には「リスト内包表記」という書き方があります。
百聞は一見に如かず。
ご覧あれ。
リスト1(Python リスト内包表記)
def test_a():
a = [i for i in range(0, 4)]
print(a)
このマーカーの部分ですね。
これは、次のコードと同等です。
リスト2 (Python リスト設定)
def test_b():
a = []
for i in range(0, 4):
a += [i]
print(a)
リスト3 (Python リスト初期化)
def test_c():
a = [0, 1, 2, 3]
print(a)
結果はどれも同じ。
「a」にはリスト [0, 1, 2, 3] が設定されます。
リスト内包表記は、通常なら初期化リストを書く [ ] の中に式を書いちゃいました。
すごい発想ですよね。
リスト2、リスト3 ならC言語でも書けます。
リスト4 (C言語 配列設定)
void test_a()
{
int i;
int a[4];
for (i = 0; i < 4; i++)
{
a[i] = i;
}
printf("[%d, %d, %d, %d]\n", a[0], a[1], a[2], a[3]);
}
リスト5 (C言語 配列初期化)
void test_b()
{
int a[4] = {0, 1, 2, 3};
printf("[%d, %d, %d, %d]\n", a[0], a[1], a[2], a[3]);
}
でも、C言語ではリスト1のような内包表記は書けません。
Python は、わざわざこの技を追加したわけです。
リスト内包表記のメリットとはなんぞや
さて。
この「リスト内包表記」。
どのようなメリットがあるのでしょうか。
いくつか考察してみます。
コード量が減る
うん。
確かにそうですよね。
リスト2の通常の for 文による設定では3行。
対し、リスト1のリスト内包表記は1行に収まってます。
リスト3も1行ですが、データ量が多くなるとどんどんコード量は膨らんでいきます。
内包表記は、リストの初期化パターンに当てはまるコードをコンパクトに表現していると言えるかもしれません。
処理速度が速い
リスト内包表記でネットを検索するとよく出現する評価です。
本当に速いのでしょうか。
試してみるに限ります。
3000万の初期化です。
import time
def test_a():
a = [i for i in range(0, 30000000)]
def test_b():
a = []
for i in range(0, 30000000):
a += [i]
print(time.localtime())
print('test_a')
test_a()
print(time.localtime())
print('test_b')
test_b()
print(time.localtime())
そして、実行結果。
time.struct_time(tm_year=2022, tm_mon=12, tm_mday=2, tm_hour=15, tm_min=4, tm_sec=30, tm_wday=4, tm_yday=336, tm_isdst=0)
test_a
time.struct_time(tm_year=2022, tm_mon=12, tm_mday=2, tm_hour=15, tm_min=4, tm_sec=33, tm_wday=4, tm_yday=336, tm_isdst=0)
test_b
time.struct_time(tm_year=2022, tm_mon=12, tm_mday=2, tm_hour=15, tm_min=4, tm_sec=40, tm_wday=4, tm_yday=336, tm_isdst=0)
リスト内包表記は約3秒。
リストの設定は約6秒。
リスト内包表記の方が倍くらい速いですね。
とは言え、3000万というリストの初期化であり、それより小さいと差異もどんどん小さくなって、とりたてて速いという感じもなくなります。
副作用がない
「いかなる副作用もなく計算することができます」
コード量や処理速度もさることながら、リスト内包表記のメリットはこれにつきると思われます。
この「副作用」。
プログラミングにおいてはしばしば話題になるのですけど、感覚的にとらえにくい。
副作用がないという、内包表記の効能についてはこちら。
Pythonドキュメントのリスト内包表記の説明についてはこちらから。
ご指摘等々、いつでもコメントください。