Python itertools计数器的当前值是什么

时间:2016-06-29 13:45:25

标签: python itertools

Python(2.7.9)中的itertools.count计数器对于线程安全计数非常方便。我怎样才能获得计数器的当前值?

每次拨打next()时,计数器都会递增并返回最后一个值:

import itertools
x = itertools.count()
print x.next()  # 0
print x.next()  # 1
print x.next()  # 2

到目前为止,非常好。

我找不到一种方法来获取计数器的当前值而不调用next(),这会产生增加计数器或使用repr()函数的不良副作用。< / p>

继上述之后:

print repr(x)  # "count(3)"

所以你可以解析repr()的输出。像

这样的东西
current_value = int(repr(x)[6:-1])

可以做到这一点,但真的很难看。

有没有办法更直接地获得计数器的当前值?

5 个答案:

答案 0 :(得分:4)

使用来源,卢克!

根据module implementation,这是不可能的。

typedef struct {
    PyObject_HEAD
    Py_ssize_t cnt;
    PyObject *long_cnt;
    PyObject *long_step;
} countobject;

当前状态存储在cntlong_cnt成员中,并且它们都没有在对象API中公开。正如您所建议的那样,只有可以检索它的位置是对象__repr__

请注意,在解析字符串时,您必须考虑非奇异增量情况。 repr(itertools.count(123, 4))等于'count(123, 4)' - 您提出的逻辑在这种情况下会失败。

答案 1 :(得分:2)

根据documentation,无法访问函数的当前值。 itertools.count()是来自itertools模块的生成器方法。因此,通常只需生成器当前值的值分配给变量。

只需存储下一个电话的结果:

current_value = x.next()

或( Python版本≥2.6的内置python方法

current_value = next(x)

如果你想要添加一些语法糖,你可以创建一个包装函数或一个实用程序装饰器类,但是赋值是标准的。

答案 2 :(得分:1)

在不推进迭代器的情况下获得下一个价值的另一种方法是滥用复制协议:

>>> c = itertools.count()
>>> c.__reduce__()[1][0]
0
>>> next(c)
0
>>> c.__reduce__()[1][0]
1

或者只是从对象副本中获取它:

>>> from copy import copy
>>> next(copy(c))
1

答案 3 :(得分:0)

It是一个生成器,做你想做的事情并不容易。

如果您想在多个地方使用它的值,我建议您通过.next()获取值并将其存储在变量中。如果您担心计数器可能会在这两种用途之间递增,那么您无论如何都需要将它们放在critical section中。

如果您不想使用这些支票生成的额外&#39; + 1来污染该计数器,您可以再使用一个计数器来计算支票(也将其放在关键部分)。从前者中减去后者会给你所需要的东西。

另外,你真的对线程安全有把握吗?文档页面没有关于线程的内容。

答案 4 :(得分:0)

今天遇到同样的事情。这就是我最终得到的:

class alt_count:

    def __init__(self, start=0, step=1):
        self.current = start - step
        self.step = step

    def __next__(self):
        self.current = self.current + self.step
        return self.current

应该为您提供几乎所有的itertools.count功能以及current属性。

i = alt_count()
print(next(i))  # 0
print(next(i))  # 1
print(i.current)  # 1

如果不需要当前值,我发现使用此简单的closure也可以。请注意,nonlocal仅适用于Python版本> 3。

def alt_next_maker(start=0, step=1):
    res = start - step

    def alt_next():
        nonlocal res, step
        res = res + step
        return res

    return alt_next

如果不想使用itertools模块,可以将其用作简单的选择。

alt_next = alt_next_maker()
print(alt_next())  # 0
print(alt_next())  # 1

文档还提及以下内容:

def count(start=0, step=1):
    # count(10) --> 10 11 12 13 14 ...
    # count(2.5, 0.5) -> 2.5 3.0 3.5 ...
    n = start
    while True:
        yield n
        n += step