4

Is it possible to know if generator was used? i.e.

def code_reader(code):
   for c in code:
        yield c

code_rdr = code_reader(my_code)

a = code_rdr.next()

foo(code_rdr)

After foo call I would like to know if .next() was called on code_rdr by foo or not. Of course I could wrap it by some class with a counter for next() calls. Is there any easy way to do so?

Chris_Rands
  • 38,994
  • 14
  • 83
  • 119
www
  • 4,365
  • 1
  • 23
  • 24
  • how about getting the index of the item the `foo` would return like `code.index(foo(code_rdr))`? I know, it is not perfect in case of duplicates but its something – Ma0 Mar 10 '17 at 10:09
  • @Ev.Kounis: but `foo` is likely a blackbox... – Willem Van Onsem Mar 10 '17 at 10:14
  • 2
    Possible duplicate of [Is there a Python function that checks if a generator is started?](http://stackoverflow.com/questions/17684908/is-there-a-python-function-that-checks-if-a-generator-is-started) – Szabolcs Mar 10 '17 at 10:14
  • Another relevant dupe: http://stackoverflow.com/questions/41307038/how-can-i-tell-whether-a-generator-was-just-started – Chris_Rands Mar 10 '17 at 10:49
  • @WillemVanOnsem meaning?... ☺ – Ma0 Mar 10 '17 at 10:55

2 Answers2

10

Python 3.2+ has inspect.getgeneratorstate(). So you can simply use inspect.getgeneratorstate(gen) == 'GEN_CREATED':

>>> import inspect
>>> gen = (i for i in range(3))
>>> inspect.getgeneratorstate(gen)
'GEN_CREATED'
>>> next(gen)
0
>>> inspect.getgeneratorstate(gen)
'GEN_SUSPENDED'
Chris_Rands
  • 38,994
  • 14
  • 83
  • 119
  • it solves it in some special case when generator was not used pre foo. In my use case code_rdr will be already started. – www Mar 10 '17 at 12:39
  • Sorry I don't understand, it sounds like a different question though, if you're saying `next()` has already been called? – Chris_Rands Mar 10 '17 at 13:12
  • 1
    @www Ok, well you could compare the `return` value of `inspect.getgeneratorlocals()` before and after calling `foo` but it won't work in all cases (like if your generator is `(c for c in 'aaa')`). Anyway, I suggest you ask this as a new question with a different title etc, it's a rather different question and you'll get more attention that way – Chris_Rands Mar 10 '17 at 17:01
0

I have used idea from attached possible answers, bellow is redefined code_reader function:

def code_reader(code):
length = len(code)
i = 0
while i < length:
    val = (yield i)
    if val != 'position':
        yield code[i]
        i += 1

by using .send('position') on I would have know position of next item to be generated, i.e.

a = code_reader("foobar")

print a.next()
print a.send('position')
print a.next()
print a.send('position')
print a.send('position')
print a.next()
print a.send('position')

output:

0
0
f
1
1
o
2
www
  • 4,365
  • 1
  • 23
  • 24