Home > front end >  Count of uninterrupted loop iterations
Count of uninterrupted loop iterations

Time:11-05

In Python, I often find myself implementing the same pattern: count the number of "valid" iterations while processing within a loop, where an "invalid" iteration is skipped over with a continue statement. I use the continue statement instead of if-else blocks to improve readability. Essentially, I do the following:

count = 0
for item in collection:
    do_something_1(item)
    if not evaluate_some_condition(item):
        continue
    count  = 1
    do_something_2(item)
return count

There are several nifty tricks one can use to implement similar patterns in a Pythonic manner. For example, enumerate, continue, break, for-else, and while-else come to mind. I am looking for a Pythonic construct to implement the scenario described above.

This works (below) but would require the evaluate_some_condition function be executed twice for every element, which can sometimes be unacceptable (it is also less readable in my opinion):

count = sum(1 for item in collection if not evaluate_some_condition(item))
for item in collection:
    do_something_1(item)
    if not evaluate_some_condition(item):
        continue
    do_something_2(item)
return count

Some construct like the below would be ideal:

for count, item in uninterrupted_enumerate(collection):
    do_something_1(item)
    if not evaluate_some_condition(item):
        continue
    do_something_2(item)
return count

Any ideas of a built-in Python feature, third-party feature, or future plans to include such a feature?

CodePudding user response:

No, I think the very first version:

count = 0
for item in collection:
    do_something_1(item)
    if not evaluate_some_condition(item):
        continue
    count  = 1
    do_something_2(item)
return count

is pretty much how it is done and it very obvious (i.e. readable) what is happening. If you compare it with your last version, where it would be very unclear that any counting is happening. If you really want to solve it that way, you could always increase some global variable within the evaluate_some_condition function, depending whether the internal check was successful or not. But again, this is probably less readable than your first version.

CodePudding user response:

I think the most interesting alternative is to use decorators. Because this was described in a different post, I will simply provide the link: https://stackoverflow.com/a/44969343/8033585

Another alternative is to use classes. For example:

class Doer2:
    def __init__(self):
        self.count = 0
    def __call__(self, item):
        self.count  = 1
        # put here the code from 'do_something_2()'
        ....

Then:

doer2 = Doer2()
for item in collection:
    do_something_1(item)
    if not evaluate_some_condition(item):
        continue
    doer2(item)

return doer2.count
  • Related