0

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?

  • 1
    See the linked duplicates for a lot of discussion; tl;dr you want to use `l=None` in the function definition and add `if l is None: l = []` inside the body. – tzaman May 26 '20 at 10:33

1 Answers1

1

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.

lukeg
  • 4,189
  • 3
  • 19
  • 40