Python 一个简单的函数,每次调用时返回一个递增1的数字,不带全局变量?

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

我试图编写一个python函数,在第一次调用时返回1。在第二次调用时,返回一个2。在第三个,一个3。等等

目前,我使用一个全局变量实现了这一点:

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