wishing for a 3-way loop construct - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Forum & Off Topic (https://python-forum.io/forum-23.html) +--- Forum: Bar (https://python-forum.io/forum-27.html) +--- Thread: wishing for a 3-way loop construct (/thread-2038.html) Pages:
1
2
|
wishing for a 3-way loop construct - Skaperen - Feb-13-2017 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. RE: wishing for a 3-way loop construct - Larz60+ - Feb-13-2017 It seems to me that's what dunders are for, in this case __iter__ For reference, if you don't have this one stored away, It's a good dunder reference: http://www.siafoo.net/article/57You can equate this to a C++ template. RE: wishing for a 3-way loop construct - micseydel - Feb-13-2017 Could you show some example? RE: wishing for a 3-way loop construct - nilamo - Feb-13-2017 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 RE: wishing for a 3-way loop construct - Larz60+ - Feb-13-2017 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 recThere'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 StopIterationThis 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 RE: wishing for a 3-way loop construct - Ofnuts - Feb-13-2017 (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. 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.
RE: wishing for a 3-way loop construct - Larz60+ - Feb-13-2017 Ofnuts - Clever and should be extremely efficient on dispatch side RE: wishing for a 3-way loop construct - micseydel - Feb-13-2017 You can use islice if items is large, as well https://docs.python.org/2/library/itertools.html#itertools.islice RE: wishing for a 3-way loop construct - Skaperen - Feb-15-2017 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. RE: wishing for a 3-way loop construct - nilamo - Feb-15-2017 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 |