I've just started learning programming some time ago and been playing with Python a bit. I wrote a small program that rolls dice based on user input (number of sides on the die and number of dice). Here's the code:
from random import randrange
def number_of_sides():
n = input("How many sides? ") # Get input from the user
if n.isdigit(): # Check if the input is a digit
n = int(n) # If it is, turn it into an integer
return n # And return the value of n
else:
print("Invalid input. ") # If test returns false, rerun function
number_of_sides()
def number_of_dice():
m = input("How many dice? ") # Get input from the user
if m.isdigit(): # Check if the input is a digit
m = int(m) # If it is, turn it into an integer
return m # And return the value of m
else:
print("Invalid input. ") # If test returns false, rerun function
number_of_dice()
def play_again() -> object: # Checks if user answered yes or no, then reruns everything or exits with exit code 0
answ = input("Do you want to play again?(yes/no) ")
if answ == "yes":
dice_roll()
elif answ == "no":
print("Ok then")
return True
else:
print("Input invalid, trying again")
play_again()
def dice_roll(): # sides - for number of sides, dice - for number of dice.
sides = number_of_sides() # Whatever number the function returns
dice = number_of_dice() # Whatever number the function returns
results = [] # empty list, here is where results will be appended
for i in range(1, dice + 1): # That returns values for each dice specified in the dice variable
throw = randrange(1, sides + 1)
results.append(throw)
results_str = " | ".join(str(i) for i in results) # Turn the list into string, separate results with a pipe
print(results_str) # Print the results of throws
play_again() # Ask the user to play again
dice_roll()
Everything works ok when I provide valid input (so digits like 6 and 6 for sides and dice), it crashes, however, when I try providing invalid input first. For some reason the number_of_sides() and number_of_dice() functions return None when they're first fed invalid input and then crash the code in the for loop in the dice_roll() function:
How many sides? a
Invalid input.
How many sides? 6
How many dice? 6
Traceback (most recent call last):
File "<directory>/dice_roll.py", line 48, in <module>
dice_roll()
File "<directory>/dice_roll.py", line 41, in dice_roll
throw = randrange(1, sides + 1)
TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
Process finished with exit code 1
I tested these functions separately and they seem to be working fine. This snippet:
def number_of_sides():
n = input("How many sides? ")
if n.isdigit():
n = int(n)
print(n, ", ", type(n))
return n
else:
print(n, ", ", type(n))
number_of_sides()
Returns str if you provide a string and int if you provide it with digits. I would like to know what may be causing this weird behaviour.
returnsomething from yourelseblocks innumber_of_sidesandnumber_of_dice. If there is no explicitreturnstatement, Python functions implicitlyreturn None. I would advise against using recursion/mutual recursion here. It is only going to make it hard to reason about.