例えば以下のように、デフォルト引数で初期化を行い、文字列を追加する関数があるとする。
1
2
3
| def append_to(values=[]):
values.append("Hoge")
return values
|
期待する振る舞いとしては。
1
2
3
4
5
6
7
8
9
10
| 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
は空のリストに初期化されるので上記のように返ってきてほしい
だが、実際に表示されるのは
1
2
3
4
5
6
7
8
9
10
| 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']
|
である。
実際に内部で何が起きているかというと
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| 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
対処方法#
関数が呼び出されるごとに新しいオブジェクトを作成する。
何も設定されていないときは、デフォルト引数を使うことで検知する
1
2
3
4
5
| def append_to(values=None):
if values is None:
values = []
values.append("Hoge")
return values
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| 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#
See Also
Support
記事をお読みくださりありがとうございます。このウェブサイトの運営を支援していただける方を募集しています。
もしよろしければ、下のボタンからサポート(投げ銭)していただけると、ブログ執筆、情報発信のモチベーションに繋がります✨
