Home > OS >  Why do these recursive functions behave this way in Python and no so when rewritten in other languag
Why do these recursive functions behave this way in Python and no so when rewritten in other languag

Time:08-30

The following script prompts the user for a positive integer and is meant to make sure that the given value is in the range 1-99.

#!/usr/bin/env python3


def get_positive_int():
    while True:
        l = int(input("Level: "))
        if 0 < l < 100:
            return l
        else:
            get_positive_int()
l = get_positive_int()        
print(l)

Submitting a positive integer yields no unexpected behaviour:

Level: 5
5

Yet when I give a negative integer than my interaction with the script looks like this:

Level: -300
Level: 5
Level: 5
5

I also noticed that when I remove the while loop from get_positive_int:

def get_positive_int():
    l = int(input("Level: "))
    if 0 < l < 100:
        return l
    else:
        get_positive_int() 

then my interaction with the script looks like this:

Level: -300
Level: 5
None

Why doesn't my code print 5 right away when it is submitted after submitting -300? Why does get_positive_int seem to return None despite having been given 5? I have not noticed such behaviour in other languages as in Bash

get_positive_int() {
  echo "Level: "  
  read l
  if [[ "${l}" -gt 0 ]] && [[ "${l}" -lt 100 ]]; then 
    :
  else
    get_positive_int 
  fi 
}

get_positive_int
echo "${l}"

or in Racket

(define (take-positive-int) (displayln "Level: ")(let ((l (string->number (read-line))))
  (if (and (> l 0) (< l 100))  l
     (take-positive-int))))

(define l (take-positive-int))

(displayln l)

where the interaction looks like this:

Level: 
-300
Level: 
5
5

CodePudding user response:

Python requires explicit use of the return to output a value. You probably want this:

def get_positive_int():
    while True:
        l = int(input("Level: "))
        if 0 < l < 100:
            return l
        else:
            return get_positive_int()


l = get_positive_int()        
print(l)

This will output like:

Level: 101
Level: 100
Level: 99
99

You also don't need to mix recursion and a while loop. You could do this purely in a while loop

def get_positive_int():
    while True:
        l = int(input("Level: "))
        if 0 < l < 100:
            return l

or purely with recursion:

def get_positive_int():
    l = int(input("Level: "))
    if 0 < l < 100:
        return l
    else:
        return get_positive_int()

CodePudding user response:

You need to return the recursive call:

def get_positive_int():
    while True:
        l = int(input("Level: "))
        if 0 < l < 100:
            return l
        else:
            return get_positive_int()

However, you don't need a recursive call:

def get_positive_int():
    while not(0 < (l:= int(input("Level: "))) < 100):
        print("value not between 0 and 100")
    return l

l = get_positive_int()
print(l)

CodePudding user response:

Because you not use return statement, you need to explicitly specify return value, if you don't do this, python will return None value. Also I suggest you to that don't use recursive function until you really need it because it can damage your code, let's say user give negative numbers all the time like below ;

def get_positive_int():
    while True:
        l = -4
        if 0 < l < 100:
            return l
        else:
            get_positive_int()

l = get_positive_int()        
print(l)

Output:

Traceback (most recent call last):
  File "b.py", line 12, in <module>
    l = get_positive_int()        
  File "b.py", line 10, in get_positive_int
    get_positive_int()
  File "b.py", line 10, in get_positive_int
    get_positive_int()
  File "b.py", line 10, in get_positive_int
    get_positive_int()
  [Previous line repeated 995 more times]
  File "b.py", line 7, in get_positive_int
    if 0 < l < 100:
RecursionError: maximum recursion depth exceeded in comparison

You can simply modify your code like this ;

def get_positive_int():
    while True:
        l = int(input("Level: "))
        if 0 < l < 100:
            return l

l = get_positive_int()        
print(l)

Output:

Level: 300
Level: 300
Level: -5
Level: 6
6
  • Related