Thursday 28 June 2007

Going Back

Reversing the digits of a number is a time-honoured exercise for student programmers. It gets the student to think about integer division and modulo operations, and about iterative processes.

An exercise I've often give to my students is to write a recursive procedure for reversing an integer's digits, even though I know that it can be done more simply as a loop. This is a good way to have the students think about parameter passing and variable scope. But up till now, I've only had students doing this in Pascal.

So when I went to do it in Python, I found myself momentarily stopped by the fact that Python does not have an exact equivalent to Pascal's variable parameters. So how do I get a recursive procedure for integer reversal in Python?

I came up with two solutions.

Solution 1:
revers(n):
global q #tell Python to use the global variable, not a local one
if n > 0:
q=q*10+n%10
revers(n/10)
return q

q = 0
x=int(raw_input("Enter a number: "))
print revers(x)

Here, I simply made the function calculate the reversed integer in a global variable. Now, when I was learning Pascal programming, all my reference works said the same thing: don't change a global variable inside a function/procedure. Since old habits die hard, I found myself looking for a different solution to the one above, one that didn't require the global variable inside the function.

Solution 2:

revers(n,q=[0]):
if n > 0:
q[0]=q[0]*10+n%10
revers(n/10)
return q[0]

x=int(raw_input("Enter a number: "))
print revers(x)

This solution uses the fact that arguments to Python functions are object references, so passing a mutable object (a list being an obvious example) allows you to progressively alter the value in that object with each subsequent recursive call to the function.

Python also allows you to declare a default value for an argument and thereby omit it from the function call. The default value is evaluated only once, so setting using q=[0] as an argument only affects the first call to the function, and subsequent recursive calls do not reset the list.

As a solution, I prefer this (since it doesn't violate the rules about variable scope I learned so long ago), but I wonder how well my students will understand how the mutability of an object relates to the scope of a recursive function.

No comments: