functions
Separate your program into functions
- getting the input number
- calculate the result
- present the result (print)
get the number
When you do int(input("<message>"))
, and the user types in text that is not convertable to an integer, your program will fail with a strange error message. Better is to validate the user input
def get_number() -> int:
"""
Asks the user for a number
Asks again if the user input is no valid integer
Returns None when the user returns 'q'
"""
while True:
input_str = input("Enter your number")
try:
return int(input_str)
except ValueError:
if input_str.lower() == "q":
return None
print(
f"{input_str} is not a valid integer. "
"Try again or enter `q` to quit"
)
If you want, you can add more tests to this function, like testing that the result is larger than 1,...
calculate
Your algorithm works like this:
- iterate from the number itself down
- store the remainder of the division in a dict
- make a list of the values
- check whether any of the values of the dict is 0
This can be simplified in a number of steps:
- why the list. You can immediately iterate over the values
- why the dict? You only use the values, so you can use another container like a list
or set
to only store the values
- why iterate over all the values, if you use a set
, you can check if 0 in remainders
- why iterate over all the values. You can stop once a remainder is 0
- why start at the number with the iteration. You will not find any divisors between number
and number//2
. You can even stop at the square root of the number, because either the divisor or the quotient will be smaller if there is any.
- why iterate descending. Odds are, you'll find a remainder in the lower numbers sooner
- why iterate over all numbers. If 2 is no divisor, 4, 6, 8, ... will not be a divisor either
So this would be a lot more efficient:
def is_prime(number: int) -> bool:
"""Checks whether `number` is prime"""
if number < 2:
return False
if number == 2:
return True
i = 3
while i**2 <= number:
if number % i == 0: # or of `not number % i:`
return False
i += 2
return True
There are more efficient prime checkers out there, but this will already be a lot more performant than your version
present the result
Now you have nice, clear functions to get a number from the user, and calculate whether the number is prime, you can make a function to present this to the user:
def main() -> None:
number = get_number()
if number is None:
return
result = is_prime(number)
if result:
message = f"{number} is prime"
else:
message = f"{number} is not prime"
print(message)
print("Press Enter to close the program")
input()
if __name__ == "__main__"
The code you really want executed when you call this as a script, but not when you import it in a different program should go behind an if __name__ == "__main__":
guard. Here you can do the presentation:
if __name__ == "__main__":
main()
type hints
I've added type hints, so users of the function (other programmers, not the end users) know what kind of type the function expects and returns
x < pr and x > 1
? Under what circumstances can the left side of theand
be false? If it can, demonstrate such a test case. If it cannot, then why say it? \$\endgroup\$