Python Forum
wishing for a 3-way loop construct
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
wishing for a 3-way loop construct
#1
when i make a loop, i often need for the body of the loop to do something different or a little bit different in the first pass or the last pass.  sometimes i need for the body of the loop to do something different in both, and in most of those cases the first and last passes are different from each other.  i wish the evolution of programming languages had included this in its syntactical design.  short of iterating on input from a dynamic source (pipe, socket, generator) it's not really hard to do this.  iterating on a list, for example, is still done with some kind of indexing or queuing that can do this.  even queuing can make it possible for most dynamic sources.

i'm recoding my pipeline stuff today.   it involves a need where the first and last commands in the pipeline need special handling, but i'd like to have all the like handling be done by the same lines of code.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#2
It seems to me that's what dunders are for,
in this case __iter__
Output:
__iter__(self) x.__iter__() <==> iter(x) Also called when iteration over the instance is requested, such as in a for loop. Should return an iterator suitable for iterating over all the items contained in the instance. Mapping objects, again, should consider only keys. If not present, Python attempts to call __getitem__ with integer keys starting at zero and ending when IndexError is raised. If __getitem__ is also not defined, a TypeError ('iteration over non-sequence') is raised.
For reference, if you don't have this one stored away, It's a good dunder reference: http://www.siafoo.net/article/57


You can equate this to a C++ template.
Reply
#3
Could you show some example?
Reply
#4
Couldn't you do this with a with block?  The context manager you define can handle the "first" and "last", while the block is what gets executed in between?

>>> class Pipe:
...   def __init__(self, start, end):
...     self.start = start
...     self.end = end
...   def __enter__(self):
...     self.start(self)
...     return self
...   def __exit__(self, *args):
...     self.end(self)
...
>>> def setup(pipe):
...   pipe.counter = 0
...
>>> def teardown(pipe):
...   print("final count: {0}".format(pipe.counter))
...
>>> with Pipe(setup, teardown) as p:
...   for i in range(4):
...     p.counter += i
...
final count: 6
Reply
#5
When you first enter a loop, python calls __iter__ here's where you can do four first iteration initialization
after that, it calls __next__ or __next__() in python 3
    def __iter__(self):
        print('1st iteration stuff here')
        # set maxitem here
        return(self)
For last iteration :
    def __next__(self):
        if self.itemnum > self.maxitem:
            # do last iteration stuff
            raise StopIteration
        self.itemnum += 1
        return rec
There's probably a better way to raise StopIteration

I just found this class that does it well:
class MyListIter(object):
    """ A sample implementation of a list iterator. NOTE: This is just a 
    demonstration of concept!!! YOU SHOULD NEVER IMPLEMENT SOMETHING LIKE THIS!
    Even if you have to (for any reason), there are many better ways to 
    implement this."""
    def __init__(self, lst):
        self.lst = lst
        self.i = -1
    def __iter__(self):
        return self
    def next(self):
        if self.i<len(self.lst)-1:
            self.i += 1         
            return self.lst[self.i]
        else:
            raise StopIteration
This is for a list, but something very similar could be done for loop
Here's where the source is loctated: Understanding Python Iterables and Iterators
Reply
#6
(Feb-13-2017, 03:07 AM)Skaperen Wrote: when i make a loop, i often need for the body of the loop to do something different or a little bit different in the first pass or the last pass.  sometimes i need for the body of the loop to do something different in both, and in most of those cases the first and last passes are different from each other.  i wish the evolution of programming languages had included this in its syntactical design.  short of iterating on input from a dynamic source (pipe, socket, generator) it's not really hard to do this.  iterating on a list, for example, is still done with some kind of indexing or queuing that can do this.  even queuing can make it possible for most dynamic sources.

i'm recoding my pipeline stuff today.   it involves a need where the first and last commands in the pipeline need special handling, but i'd like to have all the like handling be done by the same lines of code.

 
doFirst(items[0])
for items in items[1:-1]:
     doMiddle(item)
doLast(items[-1])
Also, maybe you can use the for/else construct, where the else part is done once the loop has run to the end.
Unless noted otherwise, code in my posts should be understood as "coding suggestions", and its use may require more neurones than the two necessary for Ctrl-C/Ctrl-V.
Your one-stop place for all your GIMP needs: gimp-forum.net
Reply
#7
Ofnuts - Clever and should be extremely efficient on dispatch side
Reply
#8
You can use islice if items is large, as well https://docs.python.org/2/library/iterto...ols.islice
Reply
#9
what ofnuts showed is a good way to go.  i have done something similar, without the functions, and with parts of the 3 blocks in common to avoid duplicated code.  i was wishing to see it in the languages.  maybe some obscure language did it in its syntax design.  i'd be curious about design decisions.

oooh, the else: clause on loops.   learned something new today. else clause on try/except ... also another new thing.
Tradition is peer pressure from dead people

What do you call someone who speaks three languages? Trilingual. Two languages? Bilingual. One language? American.
Reply
#10
I'm still a little confused as to why you think this is so common that it should be baked into the language. Are C-style for loops one of your favorite things ever (you know, since they have initialization statements)? :p
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020