Pause in a loop

Jp Calderone exarkun at intarweb.us
Tue Jul 22 06:57:35 EDT 2003


On Tue, Jul 22, 2003 at 10:00:27AM +0000, manuel wrote:
> 
> I've two modules: main.py and eval.py
> 
> Eval.py is imported in main.py, but I've a loop
> in eval.py that must call a function in main.py...
> 
> I can't import main.py in eval.py too, because
> that would create an import loop.
> 
> But I'm thinking a different solution:
> a pause in a loop to return periodically an
> output. It's possible?
> 

  Generators, or "resumable functions" may be one possible solution for
this:

    from __future__ import generators  # Necessary until Python 2.3

    class MoreWorkToDo:
        pass

    class NearlyDone:
        pass

    def f1():
	for i in xrange(100):
            do_something_expensive_and_slow()
            yield MoreWorkToDo
        for i in xrange(10):
            cleanup_a_little()
            yield NearlyDone

    def f2():
        for x in f1():
            print str(x),

  Another possibility is to use a callback:

    class MoreWorkToDo:
        pass

    class NearlyDone:
        pass

    def f1(perLoop):
        for i in xrange(100):
            do_something_expensive_and_slow()
            perLoop(MoreWorkToDo)
        for i in xrange(10):
            cleanup_a_little()
            perLoop(NearlyDone)

    def cbFunc(v):
        print str(v),

    def f2():
        f1(cbFunc)

  Still another approach might create an iterator out of an explicit state
machine:

    class MoreWorkToDo:
        pass

    class NearlyDone:
        pass

    class Worker:
        def __iter__(self):
            return _WorkerIter()

    class _WorkerIter:
        def __init__(self):
            self.state = 'working'
            self.workCount = 100
            self.cleanCount = 10

        def next(self):
            return getattr(self, 'state_' + self.state)()

        def state_working(self):
            do_something_expensive_and_slow()
            self.workCount -= 1
            if self.workCount <= 0:
                self.state = 'cleanup'
            return MoreWorkToDo

        def state_cleanup(self):
            cleanup_a_little()
            self.cleanCount -= 1
            if self.cleanCount <= 0:
                raise StopIteration()
            return NearlyDone

    def f2():
        for x in Worker():
            print str(x),

  The iterator solution is very similar to the generator solution (in fact,
the generator also creates an iterator, just a different kind) but as you
can see is a bit more code.  The advantage is the iterator version may be
able to continue if an unexpected exception is raised in one of the calls to
`next', whereas the generator form will never be able to do so.  The
iterator version is also pickleable.

  Hope this helps,

  Jp
> 
> thanks,
> 
>           Manuel
> 
> 
> -- 
> http://mail.python.org/mailman/listinfo/python-list

-- 
"If you find a neighbor in need, you're responsible for serving that
neighbor in need, you're responsible for loving a neighbor just like you'd
like to love yourself." -- George W. Bush, Sept. 16, 2002





More information about the Python-list mailing list