1

I created an iterator to increment the figure number in various plotting function calls:

figndx=itertools.count()

I then proceed to call these throughout my code, passing next(figndx) as an argument to increment the value I use for the figure number: - for ex:

an.plotimg(ref_frame,next(figndx),'Ref Frame')
an.plotimg(new_frame,next(figndx),'New Frame')

etc...

After some particular function call, I want to read back the figndx value and store it in a variable for later use. However, when I look at figndx , it returns count(7), for example. How do I extract the '7' from this?

I've tried :

figndx

figndx.__iter__()

and I can't find anything else in the 'suggested' methods (when I type the dot (.)) that will get the actual iterator value. Can this be done?

`

jrive
  • 218
  • 2
  • 3
  • 14
  • 1
    What you want to do is like peek the value, I mean get the value without moving the iterator? – Dani Mesejo Oct 28 '21 at 14:44
  • I don't think an `itertools.count` objects expose anyway to retrieve that value. I suppose, you could parse the string representation with a retro or something, but that would be relying on an implementation detail. – juanpa.arrivillaga Oct 28 '21 at 14:49
  • right @ Dani Mesejo.... I found this answer as I kept searching for alternatives, and it seems to work: https://stackoverflow.com/questions/38101507/what-is-the-current-value-of-a-python-itertools-counter. figndx.__reduce__()[1][0] seems to work. – jrive Oct 28 '21 at 14:49
  • What do you mean by "the actual iterator"? `figndx` *is the actual iterator*. – juanpa.arrivillaga Oct 28 '21 at 14:50
  • 1
    @jrive yeah definitely don't do that – juanpa.arrivillaga Oct 28 '21 at 14:51
  • @juanpa -- I want the value of figndx, – jrive Oct 28 '21 at 14:51
  • @jrive i understand what you want from your description but just understand that you are using terminology incorrectly. – juanpa.arrivillaga Oct 28 '21 at 14:52
  • @juanpa ---you commented, "don't do that..." what, and why not? I'm not an experienced python user (or programmer for that matter), so I would appreciate any details – jrive Oct 28 '21 at 14:53
  • Because it totally relies on an implementation detail, you should only the public API – juanpa.arrivillaga Oct 28 '21 at 14:54
  • @juanpa.arrivillaga--- what terminology? I said, "actual iterator value", is that not right? – jrive Oct 28 '21 at 14:54
  • No that isn't right. That object *is the actual iterator* – juanpa.arrivillaga Oct 28 '21 at 15:03
  • @juanpa.arrivillaga How much of an implementation detail would you say is `next(copy.copy(figndx))`? [Demo](https://tio.run/##RczBCoMwEATQe75ijwmIFxGk0G8RiVEX2t1l3UL8@hgtpXMYGB6MHLYxdYNoKfgWVgO0pMb82huILIdzC640Z3j@pY38IfOhGiuMgAQ60Zp8Hx4OakSxOqVs/vpor/LfnxAauOE3SzkB). – no comment Nov 01 '21 at 18:29

2 Answers2

3

Just wrap a count object

class MyCount:
    def __init__(self, *args, **kwargs):
        self._c = itertools.count(*args, **kwargs)
        self._current = next(self._c)
    def __next__(self):
        current = self._current
        self._current = next(self._c)
        return current
    def __iter__(self):
        return self
    def peek(self):
        return self._current
         
juanpa.arrivillaga
  • 88,713
  • 10
  • 131
  • 172
  • wow...cool, but beyond my current mastery of Python. Will have to digest it. Thank you. How is that class then used? – jrive Oct 28 '21 at 15:48
  • @jrive the same way, just use `figndx = MyCount()` then use `figndx` the same as you have been. If you want to peek at the next value that will come from the iterator, use `figndx.peek()` – juanpa.arrivillaga Oct 28 '21 at 16:28
  • You can actually subclass `itertools.count` and save some lines there. But this custom iterator approach is definitely cleaner than (repeated) teeing! – user2390182 Oct 28 '21 at 18:15
2

You can create yourself a peeker, using itertools.tee, and encapsulate the peek:

from itertools import count, tee

def peek(iterator):
    iterator, peeker = tee(iterator)
    return iterator, next(peeker)

Then you can call it like

figndx = count(1)    
next(figndx)
next(figndx)

figndx, next_value = peek(figndx)
next_value
# 3
user2390182
  • 72,016
  • 6
  • 67
  • 89
  • But what happens if you do next(peeker) 3 times and next(figndx) two times? – Dani Mesejo Oct 28 '21 at 14:53
  • Of course, you have to make yourself a new peeker for every peek. – user2390182 Oct 28 '21 at 14:59
  • Thank you!...I don't understand it, though. Within the function, when you do x,y =tee(iterator), the value is returned in peeker. But, why doesn't tee(figndx) work the same way? – jrive Oct 28 '21 at 15:45
  • 1
    `tee` just splits into independent iterators. That way you can call `next` on one of them without affecting the other. The value is returned by `next(peeker)` – user2390182 Oct 28 '21 at 15:49