Python Forum
iincomplete terators - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: iincomplete terators (/thread-9192.html)



iincomplete terators - Skaperen - Mar-26-2018

i would like to iterate over an iterator and then deal with it (the iterator itself), such as return it, in its incomplete (not iterated all the way) state. what i have been doing is making it into a list (using comprehension as i have found that some iterator classes "leak" through a list() call), popping elements as they are used, and using the incomplete list:
    ...
    mylist = [x for x in myiter]
    while mylist:
       thing = mylist.pop(0)
       result = testit(thing)
       if result:
           return mylist, result, thing
       ...
i am looking for how i might do:
    ...
    for thing in mylist:
       result = testit(thing)
       if result:
           return ...
so the big question is: is there a way to get (and pass along like return) the iterated state of any iterator? anything that can be iterated has to be storing that iteration state somewhere. is that accessible?

can i duplicate/replicate a generator part way through it doing its generating thing?


RE: iincomplete terators - Gribouillis - Mar-26-2018

Calling iter() should work
def func(seq):
    seq = iter(seq)
    for thing in seq:
        if thing == 'w':
            return seq, thing
        
s, t = func('hello world')
print(list(s))
Output:
['o', 'r', 'l', 'd']



RE: iincomplete terators - Skaperen - Mar-26-2018

def beyond(a,b):
    for c in a:
        if c == b:
            return iterstate(a)
...
y = [x for x in beyond([1,2,3,4,5,6],3)]
print(repr(y))
with that example i should get [4, 5, 6] for output. but in this case, it is a list. i'd want something that works with any iterator, to duplicate it, including its current iteration state.

the iteration state, alone, should be considered meaningless, to any other iterator. this should be especially obvious for generators.


RE: iincomplete terators - Gribouillis - Mar-27-2018

Why don't you call iter() as in the above code
def beyond(a,b):
    a = iter(a)
    for c in a:
        if c == b:
            return a

y = [x for x in beyond([1,2,3,4,5,6],3)]
print(repr(y))
Output:
[4, 5, 6]
There is also
import itertools as it

def beyond(a, b):
    return it.islice(it.dropwhile(lambda x: x != b, a), 1, None)
or even
import functools as fu
import itertools as it
import operator as op

def beyond(a, b):
    return it.islice(it.dropwhile(fu.partial(op.ne, b), a), 1, None)



RE: iincomplete terators - Skaperen - Mar-27-2018

i tried iter() like this:

def funny(x):
    for v in x:
        i = iter(x)
        for u in i:
            print(v,u)

funny([1,2,3,4,5])
print('done')
but iter(x) just duplicated x at its initial state. i guess i do not understand how this is used.


RE: iincomplete terators - Gribouillis - Mar-27-2018

(Mar-27-2018, 05:51 AM)Skaperen Wrote: i guess i do not understand how this is used.
If x is a list, iter(x) returns an iterator pointing to x that also stores an "iteration state" (probably an integer index). When you call for v in x, what python actualy does is for v in iter(x), that is to say it creates an iterator. This is the "iterator protocol". Use your favorite search engine with these words.


RE: iincomplete terators - Skaperen - Mar-28-2018

what if x is not a list?


RE: iincomplete terators - Gribouillis - Mar-28-2018

(Mar-28-2018, 12:19 AM)Skaperen Wrote: what if x is not a list?
Then iter(x) returns the appropriate iterator object for this type, which encapsulate the state of the iteration. You can use this protocol by implementing __iter__() and __next__() method for your classes and your iterator classes.