はじめに
Pythonでコードを書いていてハマったのでメモ
Python使いの人たちには常識かもしれないが多言語使いだと落とし穴になりそう。
関数のデフォルト引数挙動
Pythonではデフォルト引数は関数定義時に一度だけ評価されるという挙動らしいです。
関数定義時であって初めに呼び出された時じゃないという点もポイントです。
下記のコードでは
現在時刻を表示
↓
print_now関数定義
↓
5秒スリープ
↓
print_now関数呼び出し(現在時刻を表示・・・のつもり)
↓
3秒スリープ
↓
print_now関数呼び出し(現在時刻を表示・・・のつもり)
↓
3秒スリープ
↓
現在時刻を表示
を行っています。
import datetime
import time
print(f'0:{datetime.datetime.now():%Y-%m-%d %H:%M:%S}')
def print_now(msg, now = datetime.datetime.now()):
print(f'{msg}:{now:%Y-%m-%d %H:%M:%S}')
time.sleep(5)
print_now('1')
time.sleep(3)
print_now('2')
time.sleep(3)
print(f'3:{datetime.datetime.now():%Y-%m-%d %H:%M:%S}')
出力結果
0:2021-04-11 23:17:28
1:2021-04-11 23:17:28
2:2021-04-11 23:17:28
3:2021-04-11 23:17:39
初めて呼び出された時でも呼び出した時でもなく関数定義時に計算された値になっている。
これは知らないとハマるって・・・。
公式によると
デフォルト引数の式は関数が定義されるときにただ一度だけ評価され、同じ "計算済みの" 値が呼び出しのたびに使用されることを意味します。
とのこと。
以上