Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any reason to use "while 1, do something, break" in Python?

In the Python library SymPy I try to understand the function partitions() in sympy.utilities.iterables:

It starts like this:

def partitions(n, m=None, k=None, size=False):
    """Generate all partitions of integer n (>= 0).

I am confused about the following while loop, because it looks pointless. If I remove the while 1: and the break it should make no difference. However, I expect that the people who develop SymPy know what they are doing, and don't make very simple mistakes. So does this make some sense that I fail to see?

while 1:
    # Let i be the smallest key larger than 1.  Reuse one instance of i.
    i = keys[-1]
    newcount = ms[i] = ms[i] - 1
    reuse += i
    if newcount == 0:
        del keys[-1], ms[i]
    room += 1

    # Break the remainder into pieces of size i-1.
    i -= 1
    q, r = divmod(reuse, i)
    need = q + bool(r)
    if need > room:
        if not keys:
            return
        continue

    ms[i] = q
    keys.append(i)
    if r:
        ms[r] = 1
        keys.append(r)
    break

For learning purposes I have simplified the whole function, and my_partitions(n) gives the same results as partitions(n).

def my_partitions(n):
    ms = {n: 1}
    keys = [n]
    yield ms

    while keys != [1]:
        # Reuse any 1's.
        if keys[-1] == 1:
            del keys[-1]
            reuse = ms.pop(1)
        else:
            reuse = 0

        # Let i be the smallest key larger than 1.  Reuse one instance of i.
        i = keys[-1]
        ms[i] -= 1
        reuse += i
        if ms[i] == 0:
            del keys[-1], ms[i]

        # Break the remainder into pieces of size i-1.
        i -= 1
        q, r = divmod(reuse, i)
        ms[i] = q
        keys.append(i)
        if r:
            ms[r] = 1
            keys.append(r)

        yield ms
like image 639
Watchduck Avatar asked Feb 09 '23 01:02

Watchduck


1 Answers

This is a dirty hack to bring goto to Python. The while 1: line is the label and the continue statement is the goto.

Please do not write code like that if you can avoid it. If you must do this, at least make it while True: since the argument to while is ordinarily a boolean value.

like image 81
Kevin Avatar answered Feb 12 '23 10:02

Kevin