-2

For context, this code is written on a video within the channel Numberphile by Matt Parker talking about multiplication persistence. The code is written in Python 2, and my question is about the line return "DONE".

Evidently, this prevents an infinite loop from being generated, as it is clear running an example (below) with and without that line:

def per(n, steps = 0):
    if len(str(n)) == 1:
        print "TOTAL STEPS " + str(steps)
        return "DONE"

    steps += 1
    digits = [int(i) for i in str(n)]

    result = 1
    for j in digits:
        result *= j
    print result
    per (result, steps)    

per(27)

# 14
# 4
# TOTAL STEPS 2

Now, the same code without the line return "DONE" would not end the loop, and yield:

14
4
TOTAL STEPS 2
4
TOTAL STEPS 3
4
TOTAL STEPS 4
4
TOTAL STEPS 5
4
TOTAL STEPS 6
4
TOTAL STEPS 7
4
TOTAL STEPS 8
4
TOTAL STEPS 9
4
TOTAL STEPS 10
4
TOTAL STEPS 11
4
TOTAL STEPS 12
4
TOTAL STEPS 13
4
TOTAL STEPS 14
4
...

My question is about the meaning of 'return "HOME"'. Does it simply mean STOP. Is there any meaning of "HOME" in there?

Antoni Parellada
  • 4,253
  • 6
  • 49
  • 114
  • I think you are correct, not sure though – Arnav Poddar May 29 '19 at 00:21
  • I don't think there is any significance of the word "DONE" itself. It is just a standard break condition for the recursion. Without the condition on the length of `n`, it would lead to an infinite loop – razdi May 29 '19 at 00:26

2 Answers2

2

If you were to run the function in a variable assignment you would literally get "DONE". I'm assuming you mean "DONE" instead of "HOME" since there is no return "HOME" in your example.

For instance:

x = per(7)
print(x)

Would print the usual output and also print DONE when you called print(x). Because 7 is a single digit the condition if len(str(n)) == 1 is met on the first run..

TOTAL STEPS 0
DONE

This function calls itself though, which makes it a confusing choice to learn about this stuff since that's fairly unusual. If we run the script with a number with more than one digit, we'll get None instead.. because it never runs the return statement, it's return value is the python default, which is a NoneType:

x = per(27)
print(x)

Result:

14
4
TOTAL STEPS 2
None

Because 27 doesn't meet the condition of having a single digit.. the script calls itself with the results it's printing out.. until it finally uses 4.. which meets the condition and prints out the TOTAL STEPS line.

To see this value we have to modify the function:

def per(n, steps = 0):
    if len(str(n)) == 1:
        print("TOTAL STEPS " + str(steps))
        return "DONE"

    steps += 1
    digits = [int(i) for i in str(n)]

    result = 1
    for j in digits:
        result *= j
    print(result)
    x = per(result, steps)
    print("Inner return", x)


x = per(27)
print("Outer return", x)

Result:

14
4
TOTAL STEPS 2
Inner return DONE
Inner return None
Outer return None

Thankfully you don't have to worry too much about return values.. since you aren't capturing the return value in a variable in your example.. just using return by itself would have the same result. Which is to stop running the function at that point, and to move on to the line after per(27) if there was one.. it can be a useful way to see what's happening in this function though.

Using variable assignment with = is not the only way to use a return value.. just the easiest way to demonstrate what's happening. for instance just running print(per(27)) would have the same result as my example.

Zhenhir
  • 1,157
  • 8
  • 13
0

The return inside the if statement is just a termination for your recursive function - have you noticed that you are calling per(x) inside itself?

If we take out the return, the function will not terminate, and Python will raise a max recursive exception.

Now your function does this: if length of n is 1, terminate; otherwise, call another per function until somewhere it meets your termination condition.

But your per is not actually returning anything when len(str(n)) != 1. By default, a function implicitly returns None. So even though per(1) returns "Done", the returned value will not be propagated to the function which calls it.

To make it clearer, what you might need is (which guarantees the return value will be consistent with different input):

def per(n, steps=0):
    if len(str(n)) == 1:
        return "Done"
    # some other code
    return per(result, steps)

And another definition is also consistent:

def per(n, steps=0):
    if len(str(n)) == 1:
        return # None
    # some other code
    per(result, steps)
    # implicitly return None
knh190
  • 2,744
  • 1
  • 16
  • 30