読者です 読者をやめる 読者になる 読者になる

何かを書き留める何か

数学や読んだ本について書く何かです。最近は社会人として生き残りの術を学ぶ日々です。

『Effective Python』Item 20: 動的デフォルト引数ではNoneとドキュメンテーション文字列を使おう

Effective Python Python

『Effective Python』の続き。デフォルト引数の評価は作成時一度のみ。繰り返しませんのでどうか皆様Noneを使ってdocstringをお書きください。 www.effectivepython.com

前回『Effective Python』Item 19: キーワード引数でオプションを提供しよう - 何かを書き留める何かはデフォルト引数は便利である、という話題であったが、今回はリストや辞書といったミュータブルなデフォルト値に対する注意である。

import datetime

def log(message, when=datetime.now()):
    print('%s: %s' % (when, message))

log('Hi there!')
sleep(0.1)
log('Hi again!')

というコードを実行すると、datetime.nowが1回しか評価されていないことがわかる。 対策は、デフォルト引数をNoneにして引数が省略されたら内部で新しいオブジェクトを作るようにする、となる。

Python文法詳解』にもP194の「6.1.3 デフォルト引数」にて同等の内容が簡潔に説明されている。

Python文法詳解

Python文法詳解

そして、デフォルト引数がNoneだとデフォルトの振る舞いがわからないのでdocstringで説明しましょう、というのが筆者の主張である。 偶然にも、『Python文法詳解』のP195は「6.1.4 ドキュメンテーション文字列」である。

def log(message, when=None):
    """タイムスタンプつきのログメッセージを出力する。
    Args:
        message: 出力するメッセージ。
        when: メッセージを出力する時間。
            デフォルト値は現在の時刻
    """
    when = datetime.now() if when is None else when
    print('%s: %s' % (when, message))

log('Hi there!')
sleep(0.1)
log('Hi again!')