#修正
最初「pythonのbool型は遅い」とのタイトルで公開しておりましたが、記事の内容が当てはまるのはpypyを使う場合のみであり、誤りでした。
誤った情報を流してしまい、申し訳ありません。
#言いたいこと
競技プログラミングでpypyを利用する時、True/Falseをbool型で扱うのは遅いです。
int型を使いましょう。
#概要
何かフラグを用意して、それによって処理を分岐させることはよくあると思います。
f = 1
とする人も
f = True
とする人もいるかと思いますが、どちらも同じ事が起きると期待しますよね。
しかし、実際は実行速度に差がでます。
正確に言うと、真偽値の判定に差がは無く、書き換えで差が出ます。これは後ほど語ります。
#実験
以下のコードで比較してみます。
実行環境はatcoderのコードテストでPyPy3(3.7.0)です。
f = 1
for i in range(10**9):
if f:
f = 0
else:
f = 1
f = True
for i in range(10**9):
if f:
f = False
else:
f = True
結果はこのようになりました。(複数回やってもだいたいこんな感じです)
コード | 実行時間 | メモリ |
---|---|---|
int.py | 2423 ms | 25640 KB |
bool.py | 7439 ms | 25612 KB |
思ったより差がデカくないですか!? | ||
実行速度が厳しい問題だと、これだけでもTLEの危険が高まります。 | ||
(実際、これでABC182 Eでハマりました) |
#考察
ということで、あくまで競技プログラミングでpypyを使う場合の話ですが、フラグを使いたい場合にはbool型ではなくint型を使うようにしましょう。
いろいろ実験してみましたが、速度の差に影響があるのは真偽値判定ではなく値の書き換えのようでした。
フラグとして使うからには書き換えが前提になるかと思いますので注意が必要です。
例えば途中でフラグを立てたらそれ以降立てっぱなしという場合であれば、速度に差は出ないはずです。
コロコロと立てたり折ったりする場合にはこんなつまらない理由でTLEしてしまうかもしれません。
とくにこだわりがなければint型を使うことをおすすめします。
#おまけ
strでもやってみました。
a = "True"
for i in range(10**9):
if a == "True":
a = "False"
else:
a = "True"
結果は以下の通りです。さすがに一番遅いですね。
実行時間 | メモリ |
---|---|
8183 ms | 25612 KB |
#追記
python3で実行した場合は誤差の範囲内でした。
@shiracums さん、ご指摘ありがとうございました。