简单函数返回每次调用时递增1的数字,没有全局变量?

时间:2016-07-19 10:03:33

标签: 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

但是,我已经读过使用全局变量是不好的做法。所以,我想知道如果不使用全局变量就可以实现相同的结果。

有什么建议吗?

感谢您的帮助。

6 个答案:

答案 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