質問するログイン新規登録

回答編集履歴

1

デコレータによる実装例を追記

2025/08/30 19:45

投稿

melian
melian

スコア21449

answer CHANGED
@@ -32,3 +32,51 @@
32
32
  2回目: ['test2']
33
33
  3回目: list2 = ['test2'], list3 = ['test2', 'test3']
34
34
  ```
35
+ **追記**
36
+
37
+ デコレータ([PEP 318 – Decorators for Functions and Methods](https://peps.python.org/pep-0318/))を利用して実装してみました。
38
+ 関数の属性(attribute) `__default_parameters__` にデフォルトパラメータを記録しておいて、関数が実行される度に必要に応じて関数定義時のデフォルト値に戻します。
39
+
40
+ ```python
41
+ import inspect
42
+ from functools import wraps
43
+ from copy import deepcopy
44
+
45
+ def reset_default_parameter(f):
46
+ @wraps(f)
47
+ def wrapper(*args, **kwds):
48
+ if not hasattr(f, '__default_parameters__'):
49
+ # 属性 __default_parameters__ にデフォルトパラメータを記録
50
+ f.__default_parameters__ = {
51
+ k: (i, v.default) for i, (k, v) in enumerate(inspect.signature(f).parameters.items())
52
+ if v.default is not inspect.Parameter.empty
53
+ }
54
+ for k, (i, v) in f.__default_parameters__.items():
55
+ # キーワードパラメータとして指定されていない、かつ、位置パラメータでも
56
+ # 指定されていない場合に関数定義時のデフォルト値に戻す
57
+ if k not in kwds and i >= len(args):
58
+ kwds.update({k: deepcopy(v)})
59
+ return f(*args, **kwds)
60
+ return wrapper
61
+
62
+ @reset_default_parameter
63
+ def add_item(item, items=[]):
64
+ items.append(item)
65
+ return items
66
+
67
+ if __name__ == '__main__':
68
+ # 使用例
69
+ list1 = add_item("test1")
70
+ print("1回目:", list1)
71
+
72
+ list2 = add_item("test2")
73
+ print("2回目:", list2)
74
+
75
+ list3 = [1, 2, 3]
76
+ add_item('test3', list3)
77
+ print(f'{list3 = }')
78
+
79
+ # 1回目: ['test1']
80
+ # 2回目: ['test2']
81
+ # list3 = [1, 2, 3, 'test3']
82
+ ```