Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the current value of a Python itertools counter

The itertools.count counter in Python (2.7.9) is very handy for thread-safe counting. How can I get the current value of the counter though?

The counter increments and returns the last value every time you call next():

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

So far, so good.

I can't find a way to get the current value of the counter without calling next(), which would have the undesirable side-effect of increasing the counter, or using the repr() function.

Following on from the above:

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

So you could parse the output of repr(). Something like

current_value = int(repr(x)[6:-1])

would do the trick, but is really ugly.

Is there a way to get the current value of the counter more directly?

like image 367
Carl Avatar asked Jun 29 '16 13:06

Carl


People also ask

What is count in Itertools?

itertools. count() makes an iterator that returns values that counts up or down infinitely. itertools.count() — Functions creating iterators for efficient looping — Python 3.9.7 documentation.

What is a counter variable in Python?

To count objects, you typically use a counter, which is an integer variable with an initial value of zero. Then you increment the counter to reflect the number of times a given object appears in the input data source. When you're counting the occurrences of a single object, you can use a single counter.

How do you get the length of a counter in Python?

In Python, you can count the total number of elements in a list or tuple with the built-in function len() and the number of occurrences of an element with the count() method.

What does cycle () do in Python?

The cycle() function accepts an iterable and generates an iterator, which contains all of the iterable's elements. In addition to these elements, it contains a copy of each element.


3 Answers

Another hack to get next value without advancing iterator is to abuse copy protocol:

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

Or just take it from object copy:

>>> from copy import copy
>>> next(copy(c))
1
like image 110
Denis Otkidach Avatar answered Sep 29 '22 08:09

Denis Otkidach


Use the source, Luke!

According to module implementation, it's not possible.

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

Current state is stored in cnt and long_cnt members, and neither of them is exposed in object API. Only place where it may be retrieved is object __repr__, as you suggested.

Note that while parsing string you have to consider a non-singular increment case. repr(itertools.count(123, 4)) is equal to 'count(123, 4)' - logic suggested by you in question would fail in that case.

like image 22
Łukasz Rogalski Avatar answered Sep 29 '22 10:09

Łukasz Rogalski


According to the documentation there is no way to access the current value of the function. itertools.count() is a generator method from the itertools module. As such, it is common practice to just simply assign the value of a generator's current value to a variable.

Simply store the the result of the next call:

current_value = x.next()

or ( Built-in python method for Python version ≥ 2.6 )

current_value = next(x)

You could make a wrapper function, or a utility decorator class if you would like some added syntactic sugar, but assignment is standard.

like image 39
ospahiu Avatar answered Sep 29 '22 10:09

ospahiu