我正在尝试编写一个python函数,在第一次调用时返回1.在第二次调用时,返回2.在第三次调用时,返回3.等等。
目前,我使用全局变量实现了这一目标:
index = 0
def foo():
global index
index += 1
return index
三次调用该函数时:
print(foo())
print(foo())
print(foo())
返回预期的值:
1
2
3
但是,我已经读过使用全局变量是不好的做法。所以,我想知道如果不使用全局变量就可以实现相同的结果。
有什么建议吗?
感谢您的帮助。
答案 0 :(得分:11)
使用闭包:
def make_inc():
val = [0]
def inc():
val[0] += 1
return val[0]
return inc
inc = make_inc()
print inc()
print inc()
print inc()
使用类(OOPL中最明显的解决方案):
class Inc(object):
def __init__(self):
self._val = 0
def __call__(self):
self._val += 1
return self._val
inc = Inc()
print inc()
print inc()
print inc()
使用生成器(不能直接调用,您必须使用.next()
方法):
def incgen():
val = 0
while True:
val += 1
yield val
inc = incgen()
print inc.next()
print inc.next()
print inc.next()
答案 1 :(得分:6)
您可以使用功能属性:
def f():
f.counter = getattr(f, 'counter', 0) + 1
return f.counter
或关闭:
def w():
counter = 0
def f():
nonlocal counter
counter += 1
return counter
return f
答案 2 :(得分:4)
我将为谢尔盖的答案提供另一种解决方案:利用mutable default arguments!
def f(_=[0]):
_[0] += 1
return _[0]
这样做的缺点是用户可能错误地使用一个参数调用该函数,并且它不会收到错误消息。
答案 3 :(得分:2)
你能用一个物体吗?
class Incrementer:
def __init__(self):
self.value = 0
def __call__(self):
print(self.value)
self.value += 1
然后你可以在实例化之后将其称为函数:
>>> a = Incrementer()
>>> a()
0
>>>a()
1
答案 4 :(得分:1)
您也可以使用发电机。
def yrange(n):
i = 0
while i < n:
yield i
i += 1
输出:
>>> y = yrange(3)
>>> y
<generator object yrange at 0x401f30>
>>> y.next()
0
>>> y.next()
1
>>> y.next()
2
>>> y.next()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
答案 5 :(得分:0)
您还可以改进生成器,使其更灵活:
def counter_gen():
count = 0
while True:
res = yield count
count += res
>>> counter = counter_gen()
>>> counter.send(None) #initialize generator
>>> 0
>>> counter.send(1)
>>> 1
>>> counter.send(3)
>>> 4