回答編集履歴
2
追記
answer
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
すでにそのものズバリの回答がついているのと、個人的にあまり関数閉包が好きではないので、「似たやり方」をいくつか。
|
2
2
|
|
3
|
-
|
3
|
+
### 普通にクラスにする
|
4
4
|
けっきょく、欲しいものは閉じた名前空間のあるオブジェクト。普通に考えたらインスタンスです。
|
5
5
|
|
6
6
|
```python
|
@@ -32,7 +32,7 @@
|
|
32
32
|
この規模だと見栄えがしませんが、ある程度大きいものを作るならいい方法です。
|
33
33
|
|
34
34
|
|
35
|
-
|
35
|
+
### 引数のデフォルト値を活用する
|
36
36
|
デフォルト値が実行時(関数定義時)評価なのがキモ。
|
37
37
|
|
38
38
|
```python
|
@@ -54,7 +54,7 @@
|
|
54
54
|
|
55
55
|
```
|
56
56
|
|
57
|
-
|
57
|
+
### 単に外のスコープに置く
|
58
58
|
|
59
59
|
```python
|
60
60
|
a = increment(1)
|
@@ -66,7 +66,7 @@
|
|
66
66
|
|
67
67
|
これで済むなら別にこれでも良いのでは? と思います。
|
68
68
|
|
69
|
-
|
69
|
+
### 関数オブジェクトの属性に押し込む
|
70
70
|
この方法は汚いので非推奨ですが・・・
|
71
71
|
|
72
72
|
```python
|
@@ -89,4 +89,45 @@
|
|
89
89
|
"""
|
90
90
|
```
|
91
91
|
|
92
|
-
記述量だけならクロージャより少なくて済むのが強みです。
|
92
|
+
記述量だけならクロージャより少なくて済むのが強みです。引数のデフォルト値を使う方法には負けますが。
|
93
|
+
|
94
|
+
関数に呼び出しをまたいで変化する状態を持たせるような用途だと、この方法は輝きます。デフォルト値では(たぶん)できないからです。
|
95
|
+
|
96
|
+
これとクロージャでカウンタを書いた例。
|
97
|
+
|
98
|
+
```python
|
99
|
+
# クロージャ版
|
100
|
+
def make_f(init):
|
101
|
+
def f():
|
102
|
+
nonlocal init # 必須
|
103
|
+
init += 1
|
104
|
+
return init
|
105
|
+
return f
|
106
|
+
|
107
|
+
f = make_f(0)
|
108
|
+
for i in range(5):
|
109
|
+
print(f())
|
110
|
+
""" =>
|
111
|
+
1
|
112
|
+
2
|
113
|
+
3
|
114
|
+
4
|
115
|
+
5
|
116
|
+
"""
|
117
|
+
|
118
|
+
# 属性版
|
119
|
+
def f():
|
120
|
+
f.init += 1
|
121
|
+
return f.init
|
122
|
+
f.init = 0
|
123
|
+
|
124
|
+
for i in range(5):
|
125
|
+
print(f())
|
126
|
+
""" =>
|
127
|
+
1
|
128
|
+
2
|
129
|
+
3
|
130
|
+
4
|
131
|
+
5
|
132
|
+
"""
|
133
|
+
```
|
1
修正
answer
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
すでにそのものズバリの回答がついているのと、個人的にあまり関数閉包が好きではないので、「似たやり方」をいくつか。
|
2
2
|
|
3
3
|
- 普通にクラスにする
|
4
|
-
けっきょく、欲しいものは閉じた名前空間。普通に考えたらインスタンスです。
|
4
|
+
けっきょく、欲しいものは閉じた名前空間のあるオブジェクト。普通に考えたらインスタンスです。
|
5
5
|
|
6
6
|
```python
|
7
7
|
class Hoge:
|