Pythonの関数のデフォルト引数はmutable(上書きされる)
例えば以下のように、デフォルト引数で初期化を行い、文字列を追加する関数があるとする。
def append_to(values=[]):
values.append("Hoge")
return values
期待する振る舞いとしては。
In [14]: def append_to(values=[]):
...: values.append("Hoge")
...: return values
...:
In [17]: append_to()
Out[17]: ['Hoge']
In [18]: append_to()
Out[18]: ['Hoge']
と関数呼び出しごとに、values
は空のリストに初期化されるので上記のように返ってきてほしい
だが、実際に表示されるのは
In [14]: def append_to(values=[]):
...: values.append("Hoge")
...: return values
...:
In [17]: append_to()
Out[17]: ['Hoge']
In [18]: append_to()
Out[18]: ['Hoge', 'Hoge']
である。
実際に内部で何が起きているかというと
In [23]: def append_to(values=[]):
...: values.append("Hoge")
...: return values
...:
In [24]: pinfo append_to
Signature: append_to(values=[])
Docstring: <no docstring>
File: ~/<ipython-input-23-4530a91351ab>
Type: function
In [25]: append_to()
Out[25]: ['Hoge']
In [26]: pinfo append_to
Signature: append_to(values=['Hoge'])
Docstring: <no docstring>
File: ~/<ipython-input-23-4530a91351ab>
Type: function
In [27]: append_to()
Out[27]: ['Hoge', 'Hoge']
In [28]: pinfo append_to
Signature: append_to(values=['Hoge', 'Hoge'])
Docstring: <no docstring>
File: ~/<ipython-input-23-4530a91351ab>
Type: function
が起きている。
pinfo
は ipython 上で、オブジェクトの情報が確認できる便利コマンドです。
関数呼び出しごとに、デフォルト引数の values が上書きされていっていることがわかります。
これは、Python のデフォルト引数が、関数が定義されたときのみ評価され、毎回毎回評価されるわけではない。(Ruby は評価される)
ここでわかるのは、mutable
対処方法
関数が呼び出されるごとに新しいオブジェクトを作成する。 何も設定されていないときは、デフォルト引数を使うことで検知する
def append_to(values=None):
if values is None:
values = []
values.append("Hoge")
return values
In [34]: def append_to(values=None):
...: if values is None:
...: values = []
...: values.append("Hoge")
...: return values
...:
In [35]: append_to()
Out[35]: ['Hoge']
In [36]: pinfo append_to
Signature: append_to(values=None)
Docstring: <no docstring>
File: ~/<ipython-input-34-8e047f793784>
Type: function
In [37]: append_to()
Out[37]: ['Hoge']
In [38]: pinfo append_to
Signature: append_to(values=None)
Docstring: <no docstring>
File: ~/<ipython-input-34-8e047f793784>
Type: function
想定通りの動きになった
Ref
関連しているかもしれない記事
- 遅すぎる `pandas.read_gbq` を使わずに、Google BigQueryから高速にデータを読み込む
- Jupyter Notebook上にTensorboard を わずか2行で表示させる
- How to concat image using skimage
- Google Colaboratory で Mecab-ipadic-Neologd を使用可能にする
- Jupyter Notebookの差分を明瞭に確認する事ができるpackage : nbdime
📮 📧 🐏: 記事への感想のおたよりをおまちしてます。 お気軽にお送りください。 メールアドレス入力があればメールで返信させていただきます。 もちろんお返事を希望せずに単なる感想だけでも大歓迎です。
このサイトの更新情報をRSSで配信しています。 お好きなフィードリーダーで購読してみてください。
このウェブサイトの運営や著者の活動を支援していただける方を募集しています。 もしよろしければ、Buy Me a Coffee からサポート(投げ銭)していただけると、著者の活動のモチベーションに繋がります✨
Amazonでほしいものリストも公開しているので、こちらからもサポートしていただけると励みになります。