2

This piece of code generates the permutation, I'm interested to how the else: return at the end works.

all_str = []
def permu(iterable,r=None):
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    if r > n:
        return
    indices = list(range(n))
    cycles = list(range(n, n - r, -1))
    all_str.append( tuple(pool[i] for i in indices[:r]))
    while True:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i + 1:] + indices[i:i + 1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                all_str.append( tuple(pool[i] for i in indices[:r]))
                break
        else: # here
            return
permu("abcde",4)

what is the else at the bottom referring to? I know that you can have an if in the loop and else outside the loop, but this doesn't seem to be the case as the if is already taken care of by an else.

When I remove the else: return, the function generates permutation endlessly in a repeating fashion.

I want to know this because I need to replicate this code in C++.

Any help or suggestion will be greatly appreciated :)

Kenivia
  • 384
  • 1
  • 13
  • 1
    It's more clear to read the "for else" as "for finally". The else is executed if the for loop finishes correctly. [read more](https://stackoverflow.com/questions/9979970/why-does-python-use-else-after-for-and-while-loops). In your example, it will return (exit the while) after for finishes. – Raphael Nov 08 '19 at 23:41
  • @Raphael yes! thanks! – Kenivia Nov 08 '19 at 23:48

3 Answers3

2

the else clause of a for loop runs under a special circumstance: if the loop finishes without any disruption (in this case: break) the else clause will run, otherwise, it will be skipped. Namely, if the else related to the if is executed, the else of the for won't run.

Reza Keshavarz
  • 688
  • 2
  • 9
  • 17
1

The else statement of a for loop is executed if nobody explicitely executed a break from within the for loop ( Full explanation in the python documentation https://docs.python.org/3.6/reference/compound_stmts.html#the-for-statement )

so if you want to replicate this in C++ you had to set a variable that keeps track whether you quit the for loop via a break or just because the for loop finished.

I didn't write C for ages, so there might be tiny errors in my pseudo C code.

while(bla){
  int encountered_break = 0;
  for(bla;bla;bla){
      if (bla){
      } else {
          encountered_break = 1;
          break;
      }
  }
  if(!encountered_break){
      return;
  }
}
gelonida
  • 5,327
  • 2
  • 23
  • 41
  • 1
    fixed some errors in previous comment (now deleted as wrong and redundant): @Raphael Do you have an example of a code without `break`, that would __not__ call the `else` section of a for loop? An example causing an exception within the for loop will just raise a normal exception so neither `else:` nor any code after the exception is executed. Also after reading the documentation of the `for` loop ( https://docs.python.org/3.6/reference/compound_stmts.html#the-for-statement ) I don't see how I could __not__ enter the else section, except with a `break`. – gelonida Nov 09 '19 at 00:04
  • 1
    strange: Whenever I get down votes I never get an explanation (which would help me to improve the quality of my answer) Added a link to the full documentation of the for loop in case this was the reason. – gelonida Nov 09 '19 at 00:07
1

It's more clear to read the for else as for finally. The else is executed if the for loop finishes correctly. In your example, it will return (exit the while) after the for loop finishes.

In your example, if you remove the else: return, than the execution will always be inside the while True.

Read more about it here.

Raphael
  • 959
  • 7
  • 21