473,372 Members | 1,357 Online

# recursive function stuck in a loop

Expand|Select|Wrap|Line Numbers
1. def fact(n):
2.     if n<0:
3.         print 'error'
4.     if n==0:
5.         return 1
6.     else:
7.         return n * fact(n-1)
8.
9. # I tried
10. >>fact(-2)
11. error
12. error
13. error
14. error
15. error
16. error
17. ....
18.
I would like to know why did the error occur and how to fix it?
Oct 29 '07 #1
4 1214
bartonc
6,596 Expert 4TB
That's because, the way it is written, both if statements are executed. This slight mod will fix it:
Expand|Select|Wrap|Line Numbers
1. def fact(n):
2.     if n<0:
3.         print 'error'
4.     elif n==0: # need elif so the rest are not evaluated if n < 0
5.         return 1
6.     else:
7.         return n * fact(n-1)
Oct 29 '07 #2
bartonc
6,596 Expert 4TB
That's because, the way it is written, both if statements are executed. This slight mod will fix it:
Expand|Select|Wrap|Line Numbers
1. def fact(n):
2.     if n<0:
3.         print 'error'
4.     elif n==0: # need elif so the rest are not evaluated if n < 0
5.         return 1
6.     else:
7.         return n * fact(n-1)
It would, however, be much more readable like this:
Expand|Select|Wrap|Line Numbers
1. def fact(n):
2.     if n > 0:
3.         return n * fact(n - 1)
4.     elif n == 0: # take care of exceptions after the business
5.         return 1
6.     else:
7.         print 'error'
Oct 29 '07 #3
bvdet
2,851 Expert Mod 2GB
Expand|Select|Wrap|Line Numbers
1. def fact(n):
2.     if n<0:
3.         print 'error'
4.     if n==0:
5.         return 1
6.     else:
7.         return n * fact(n-1)
8.
9. # I tried
10. >>fact(-2)
11. error
12. error
13. error
14. error
15. error
16. error
17. ....
18.
I would like to know why did the error occur and how to fix it?
Your code can also be modified to work like this:
Expand|Select|Wrap|Line Numbers
1. def fact(n):
2.     if n < 0:
3.         print 'error'
4.         return None
5.
6.     if n == 0:
7.         return 1
8.     return n * fact(n-1)
When Python encounters a return statement, it immediately returns control to the calling script. Note that the else statement is not required for the same reason.
Oct 29 '07 #4
bartonc
6,596 Expert 4TB
Your code can also be modified to work like this:
Expand|Select|Wrap|Line Numbers
1. def fact(n):
2.     if n < 0:
3.         print 'error'
4.         return None
5.
6.     if n == 0:
7.         return 1
8.     return n * fact(n-1)
When Python encounters a return statement, it immediately returns control to the calling script. Note that the else statement is not required for the same reason.
Great point, BV. And just to add to the mix, I'll point that:
Expand|Select|Wrap|Line Numbers
1. def somefunc(someargs):
2.     if someargs == blablabla:
3.         return None
4. # is equivalent todef somefunc(someargs):
5.     if someargs == blablabla:
6.         return  # functions and methods with no return value automatically return None
Oct 29 '07 #5