回答編集履歴
3
追記
answer
CHANGED
|
@@ -30,4 +30,62 @@
|
|
|
30
30
|
>>> func.__defaults__ = 'spam',
|
|
31
31
|
>>> func()
|
|
32
32
|
spam
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
質問追記を受けて
|
|
36
|
+
---
|
|
37
|
+
関数オブジェクトは呼び出された際、不足する引数にデフォルト値が定められていないか調査します。
|
|
38
|
+
そのときにチェックされる帳簿が`__defaults__`及び`__kwdefaults__`です。
|
|
39
|
+
|
|
40
|
+
> 自分が悩んだのは[0].append(42)の[0]でした。
|
|
41
|
+
|
|
42
|
+
`__defaults__`がデフォルト値のタプルだからです。
|
|
43
|
+
```Python
|
|
44
|
+
>>> def func(arg1=[], arg2=[]):
|
|
45
|
+
... print(arg1, arg2)
|
|
46
|
+
...
|
|
47
|
+
>>> func.__defaults__
|
|
48
|
+
([], [])
|
|
49
|
+
>>> type(func.__defaults__)
|
|
50
|
+
<class 'tuple'>
|
|
51
|
+
>>>
|
|
52
|
+
>>> func.__defaults__[0]
|
|
53
|
+
[]
|
|
54
|
+
>>> type(func.__defaults__[0])
|
|
55
|
+
<class 'list'>
|
|
56
|
+
>>>
|
|
57
|
+
>>> func.__defaults__[0].append(42)
|
|
58
|
+
>>> func()
|
|
59
|
+
[42] []
|
|
60
|
+
>>>
|
|
61
|
+
>>> func.__defaults__[1].append(6)
|
|
62
|
+
>>> func()
|
|
63
|
+
[42] [6]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
> func.defaults = 'spam',について考えました。おそらくargs=[]の=以降を変更するのではと考え、args='slim'として行ったところ、spamに変更されていたので、=とするとデフォルト値を変更できるのではという結論に自分の中で至りました。
|
|
67
|
+
|
|
68
|
+
その考えで問題無いように思います。
|
|
69
|
+
ただし関数オブジェクトの属性を書き換えているだけなので、決して特殊な文法ではありませんが。
|
|
70
|
+
|
|
71
|
+
> タプルでは('aaa',)というように,が必要だったのを思い出すと=でデフォルト値を変更する時はタプルとしての操作をする(先例のリストの追加をするときの[0]とは別)のかな
|
|
72
|
+
|
|
73
|
+
単一要素のタプルのリテラルを記述するときは、
|
|
74
|
+
文法の都合上最後にカンマ(俗称ケツカンマ)を付けなければなりません。
|
|
75
|
+
|
|
76
|
+
カンマを付けないと、計算の順序を操作する括弧と見分けが付かないからです。
|
|
77
|
+
|
|
78
|
+
> func.defaults[0].append(42)のような形式で、辞書を値のない辞書として、0のかわりにNoneを使用してみましたが、エラーでした。
|
|
79
|
+
|
|
80
|
+
やるならこんな感じでしょうか。
|
|
81
|
+
```Python
|
|
82
|
+
>>> def moji(a, *, b='ow'):
|
|
83
|
+
... print(a, b, sep='')
|
|
84
|
+
...
|
|
85
|
+
>>> moji.__kwdefaults__
|
|
86
|
+
{'b': 'ow'}
|
|
87
|
+
>>> moji.__kwdefaults__['b'] = 'ing'
|
|
88
|
+
>>>
|
|
89
|
+
>>> moji('r')
|
|
90
|
+
ring
|
|
33
91
|
```
|
2
追記
answer
CHANGED
|
@@ -5,11 +5,13 @@
|
|
|
5
5
|
---
|
|
6
6
|
なお、デフォルト値は次のように確認できます。
|
|
7
7
|
```Python
|
|
8
|
-
>>> def func(arg=
|
|
8
|
+
>>> def func(arg='spam', *, kwarg='ham'):
|
|
9
9
|
... pass
|
|
10
10
|
...
|
|
11
11
|
>>> func.__defaults__
|
|
12
|
-
(
|
|
12
|
+
('spam',)
|
|
13
|
+
>>> func.__kwdefaults__
|
|
14
|
+
{'kwarg': 'ham'}
|
|
13
15
|
```
|
|
14
16
|
|
|
15
17
|
このことからも、**デフォルト値が関数オブジェクトに所有されている**ことが分かります。
|
1
追記
answer
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
1
|
> 関数の呼び出しによって、デフォルトの値に対する新しいオブジェクトが作られるのだと予想しがちです。実はそうなりません。デフォルト値は、関数が定義されたときに一度だけ生成されます。この例の辞書のように、そのオブジェクトが変更されたとき、その後の関数の呼び出しは変更後のオブジェクトを参照します。
|
|
2
2
|
|
|
3
|
-
引用元: [Python よくある質問 » なぜオブジェクト間でデフォルト値が共有されるのですか?](https://docs.python.jp/3/faq/programming.html#why-are-default-values-shared-between-objects)
|
|
3
|
+
引用元: [Python よくある質問 » なぜオブジェクト間でデフォルト値が共有されるのですか?](https://docs.python.jp/3/faq/programming.html#why-are-default-values-shared-between-objects)
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
なお、デフォルト値は次のように確認できます。
|
|
7
|
+
```Python
|
|
8
|
+
>>> def func(arg=[]):
|
|
9
|
+
... pass
|
|
10
|
+
...
|
|
11
|
+
>>> func.__defaults__
|
|
12
|
+
([],)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
このことからも、**デフォルト値が関数オブジェクトに所有されている**ことが分かります。
|
|
16
|
+
なお、次のような不可解な操作も可能です。
|
|
17
|
+
```Python
|
|
18
|
+
>>> def func(args=[]):
|
|
19
|
+
... print(args)
|
|
20
|
+
...
|
|
21
|
+
>>> func()
|
|
22
|
+
[]
|
|
23
|
+
>>>
|
|
24
|
+
>>> func.__defaults__[0].append(42)
|
|
25
|
+
>>> func()
|
|
26
|
+
[42]
|
|
27
|
+
>>>
|
|
28
|
+
>>> func.__defaults__ = 'spam',
|
|
29
|
+
>>> func()
|
|
30
|
+
spam
|
|
31
|
+
```
|