Python function unexpectedly memorizes the length of list and adds it to every iteration

Question:

I’m trying to check number of “stopping times” of Collatz sequence. The script appends result of every function “step” in a list which length I use to figure out overall number of “steps”. the script is ok, but! Whenever I use several times it returns wrong length of a list. I don’t know wht but it keeps previous length of a list and adds it to the next function result.

def stopping_time(n, l=[]):
    if n == 1:
        return
    elif n % 2 == 0:
        n = n // 2
        l.append(n)
        stopping_time(n)
    else:
        n = n * 3 + 1
        l.append(n)
        stopping_time(n)

    return len(l)


a = stopping_time(4)
b = stopping_time(13)
c = stopping_time(19)
d = stopping_time(27)

print(a, b, c, d)

# 'a' shoulb be 2, 'b' should be 9, 'c' should be 20 and 'd' should be 111
# instead its 2, 11,  31,  142

Any thoughts?

Asked By: Arsen Suleymanov

||

Answers:

It’s not a bug, but a feature. Python indeed memorizes mutable values passed as default arguments between calls (cf. https://docs.quantifiedcode.com/python-anti-patterns/correctness/mutable_default_value_as_argument.html).

The solution may be passing the sentinel value as an argument, something like:

def foo(bar=None):
    if bar is None:
        bar=[]
     ...

In general, you set your list argument to None by default and then set it inside the function to [] if no other value was passed by the caller.

Answered By: lukeg
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.