python question about iterative functions/ general functions

Question:

I have the following code, which i know to be wrong and also know what exactly is wrong, lack of ‘return’ before both iterative calls:

alpha = 546
beta = 66

def Euclid(a, b):
    while not (a == 0 or b == 0):
        if a >= b:
            Euclid(a % b, b)
        else:
            Euclid(a, b % a)

    return max(a, b)

print(Euclid(alpha, beta))

My question is why does the code above not still work? I viewed it in code visualiser, and it shows that the last value it returns is indeed max(a,b), so GCD, but then after the function keeps executing the code forever, going from arguments of (6,12) to (6,0), and then starting all over again with (6,12), after returning (6,0). Would just like to know what exactly is happening, since i thought function always quits after the last return.

Asked By: John Doe

||

Answers:

Let’s take a look at your Euclid function and try to understand what happens line by line (and also pay close attention to the values of the variables):

def Euclid(a, b):
    while not (a == 0 or b == 0):
        if a >= b:
            Euclid(a % b, b)
        else:
            Euclid(a, b % a)

    return max(a, b)
  • You call it with a = 546 and b = 66. (a=546 and b=66)
  • You enter the while loop because a!=0 and b!=0 (a=546 and b=66)
  • Since a>=b you call the Euclid function with a%b and b (a=546 and b=66)
  • You ignore the return value (a=546 and b=66) (actually this call never returns either, but let’s assume for now it does)
  • You go back to the start of your while loop and start again (a=546 and b=66)

The problem is that you never modify the values of a and b, so your while condition will always be true, and your first call of the function never reaches the return.

Ps.: B Remmelzwaal is right about how to fix your code, I only explained what is happening, which makes you get stuck in an infinite loop. Based on his answer the correct code would be:

def Euclid(a, b):
    while not (a == 0 or b == 0):
        if a >= b:
            return Euclid(a % b, b)
        else:
            return Euclid(a, b % a)

    return max(a, b)

Ps2.: To clarify some misunderstanding, the while loop is un necessary in the code, since you would enter only once and return from it. The commands inside the while are never repeated.

The code which reflects better what is happening would be:

def Euclid(a, b):
    if a!=0 and b!=0:
        if a >= b:
            return Euclid(a % b, b)
        else:
            return Euclid(a, b % a)

    return max(a, b)

So in this case when you call the function with a = 546 and b = 66, the following is going to happen:

  • Euclid(546,66)
    • Euclid(18,66)
      • Euclid(18,12)
        • Euclid(6,12)
          • Euclid(6,0) –> This is not calling any more Euclids and returns 6
          • return 6
        • return 6
      • return 6
    • return 6
  • return 6

So the Euclid(6,0) gives you 6, the Euclid(6,12) returns the return value of Euclid(6,0), which was 6. And so on while you reach back to the Euclid(546,66).

You can imagine it as a matryoshka doll, every outer doll tells you the number which the inner doll told it. In this analogy the smallest inner doll is the Euclid(6,0) and every other doll just repeats it as it proceeds through the layers.

Answered By: Phoenixdust
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.