Python 一个简单的函数,每次调用时返回一个递增1的数字,不带全局变量?
我试图编写一个python函数,在第一次调用时返回1。在第二次调用时,返回一个2。在第三个,一个3。等等 目前,我使用一个全局变量实现了这一点:Python 一个简单的函数,每次调用时返回一个递增1的数字,不带全局变量?,python,increment,Python,Increment,我试图编写一个python函数,在第一次调用时返回1。在第二次调用时,返回一个2。在第三个,一个3。等等 目前,我使用一个全局变量实现了这一点: index = 0 def foo(): global index index += 1 return index 调用函数三次时: print(foo()) print(foo()) print(foo()) 它返回预期的值: 1 2 3 但是,我已经读到使用全局变量是一种不好的做法。所以,我想知道,如果不使用glob
index = 0
def foo():
global index
index += 1
return index
调用函数三次时:
print(foo())
print(foo())
print(foo())
它返回预期的值:
1
2
3
但是,我已经读到使用全局变量是一种不好的做法。所以,我想知道,如果不使用globals,是否可以获得相同的结果
有什么建议吗
谢谢您的帮助。您可以使用函数属性:
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
使用闭包:
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中最明显的解决方案):
使用生成器(不可直接调用,必须使用.next()
方法):
我将为Sergey的答案提供另一种解决方案:利用漏洞
这样做的缺点是,用户可能会使用一个参数错误地调用函数,并且不会收到错误消息。您可以使用对象吗
class Incrementer:
def __init__(self):
self.value = 0
def __call__(self):
print(self.value)
self.value += 1
然后,您可以在实例化后像调用函数一样调用它:
>>> a = Incrementer()
>>> a()
0
>>>a()
1
你也可以使用发电机
def yrange(n):
i = 0
while i < n:
yield i
i += 1
def yrange(n):
i=0
而i
输出:
>>> 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
y=y范围(3)
>>>y
>>>y.下一步()
0
>>>y.下一步()
1.
>>>y.下一步()
2.
>>>y.下一步()
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
停止迭代
您还可以改进生成器,使其更灵活:
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
非本地
仅是Python3 IIRC。警告/对于“函数属性”技巧,我绝对不推荐它,因为它非常脆弱(在f
定义之后添加g=f;f=lambda:None
,您会发现原因)。您的生成器代码可能应该使用next(inc);next(inc)
而不是inc.next()
,因为前者适用于python2.6+和python3,而后者仅适用于python2。x@Bakuriu是的,对不起,我还得换成py3K
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
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