1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Python】関数のデフォルト引数の落とし穴

Posted at

はじめに

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

初めて呼び出された時でも呼び出した時でもなく関数定義時に計算された値になっている。
これは知らないとハマるって・・・。

公式によると

デフォルト引数の式は関数が定義されるときにただ一度だけ評価され、同じ "計算済みの" 値が呼び出しのたびに使用されることを意味します。

とのこと。

以上

1
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?