I'm new to python and I'm looking to code a small calculator for divisions, that includes while loops and if conditionals
My code looks like this:
a = input('first number')
while type(a)!=int:
try:
a=int(a)
print('imput number is correct ',a)
except:
print('Imput data is not correct ')
a=input('first number')
b = input('second number')
while type(b)!=int and b!=0:
try:
b=int(b)
print('Imput data is correct',b)
except:
print(' imput data is not a number, please only imput numbers ')
b=input('second number')
while b==0:
try:
c=1/b
print('imput number is correct ',b)
except ZeroDivisionError:
print('Cant divide by 0')
b=input('second number again')
if type(a)==int and type(b)==int and b!=0:
c=a/b
print('the result is: ',c)
The program suddenly ends after you imput 0 a second time in the second number space, but the proccess should keep asking for a value that is a number and different from 0
After b=input('second number again') is executed, b is a string, so b == 0 is False(a string is never equal to an integer).
You'll find this easier if you write a common function to get the user input. Something like this:
def get_input(prompt, nonZero=False):
while True:
try:
if (n := int(input(prompt))) == 0 and nonZero:
raise ValueError('Value must be non-zero')
return n
except ValueError as e:
print(e)
a = get_input('Input first number: ')
b = get_input('Input second number: ', True)
print(a/b)
Related
as part of the Chapter 3 exercise for Automate the Boring Stuff, I need to write a short program that mimics the Collatz sequence, where:
If number inputted is even number, divide it by 2, repeat until it equals 1;
If number inputted is odd number, multiply it by 3 then plus 1, repeat until it equals 1;
Create a clean exit for Ctrl+C.
Detect whether the user typed in a noninteger string.
Below is my code so far, which seems to work but I would appreciate any advice/best practice for improving it.
My main question is, after the program prints 'Enter integers only', is there any short and simple way to loop back to the 'Enter any number: ' line? I can't think of anything atm besides complicated if loops. Thanks.
def collatz(number):
if number % 2 == 0 :
results = number // 2
print(results)
if results != 1:
collatz(results)
elif number % 2 == 1 :
results = 3 * number + 1
print(results)
if results != 1:
collatz(results)
try:
entry = input('Enter any number : ')
number = int(entry)
print(number)
collatz(number)
except ValueError:
print('Enter integers only.')
except KeyboardInterrupt:
sys.end()
You can try using a while loop. The below code will be helpful for you.
def collatz(number):
if number % 2 == 0 :
results = number // 2
print(results)
if results != 1:
collatz(results)
elif number % 2 == 1 :
results = 3 * number + 1
print(results)
if results != 1:
collatz(results)
while True:
try:
entry = input('Enter any number : ')
number = int(entry)
print(number)
collatz(number)
except ValueError:
print('Enter integers only.')
except KeyboardInterrupt:
break # Stop the while loop.
sys.end()
As you want to keep prompting the same, until the program exits. I'd suggest just encapsulating the program code in a while(true) loop:
while True:
try:
entry = input('Enter any number : ')
number = int(entry)
print(number)
collatz(number)
except ValueError:
print('Enter integers only.')
except KeyboardInterrupt:
sys.end()
You can define an iteration to make sure the input is integer type.
while True: # executes the loop body indefinitely
try:
entry = input('Enter any number : ')
number = int(entry)
print(number)
collatz(number)
break # immediately terminates the loop entirely
except ValueError:
print('Enter integers only.')
except KeyboardInterrupt:
sys.end()
Put it in a "while" loop.
while True:
try:
...
except:
...
the inputs are 7,2,bob,10, and 4. The output is supposed to be:Invalid input,Maximum is 10,Minimum is 2.
I initially had issues with 'None' not being able to be used with '<' until I used 'or'. Should you be kind enough to address this query, please talk to me like you would to a small pet or golden retriever. Thank you.
largest = None or 0
smallest = None or 0
while True:
num = input("Enter a number: ")
fval=float(num)
if fval is'bob':
print('invalid')
if largest is None:
fval>largest
largest=fval
if smallest is None:
smallest=fval
elif smallest<fval:
smallest=fval
if num == "done":
break
print(fval)
print("Maximum", largest, "Minimum",smallest)
You would get error if you convert string which is not float to float type.
Here you can use try except to try to convert and in case of error print invalid.
This code would solve your problem:
largest = None
smallest = None
while True:
num = input("Enter a number: ")
if num=="done":
break
try:
fval=float(num)
largest=fval if largest is None else max(largest,fval)
smallest=fval if smallest is None else min(smallest,fval)
except:
print('invalid')
print("Maximum", largest, "Minimum",smallest)
Error is very explanatory. In the second line inside the while loop, you are trying to turn the string "bob" to a floating point number.
fval = float("bob")
Python is unable to do this so it raises a ValueError.
One way to get around this is with try and except. This approach makes Python do something, and if that "something" raises an error, it jumps to the except part.
try:
float("bob")
except ValueError:
print("invalid")
You can then continue your code below this piece as intended.
This is a better way to handle this. Use a try to catch EVERY invalid input, not just "bob".
largest = 0
smallest = 9999999
while True:
num = input("Enter a number: ")
if num == "done":
break
try:
fval = float(num)
largest = max(fval, largest)
smallest = min(fval, smallest)
except ValueError:
print('invalid')
print("Maximum", largest, "Minimum",smallest)
You have 2 problems. Firstly, you need to ensure that the input can be converted to a float. This can be done using a try catch block.
try:
fval=float(num)
except:
print("Cannot convert to float")
Secondly, it is easier to just set the first value as smallest/largest then do your checks. You can monitor the first value using a boolean flag (e.g. True/False variable named 'firstNumber')
firstNumber = True
while True:
num = input("Enter a number: ")
try:
fval=float(num)
if firstNumber:
firstNumber = False
smallest = largest = fval
elif fval<smallest:
smallest=fval
elif fval>largest:
largest=fval
print(fval)
except:
if num == "done":
break
else:
print('invalid')
print("Maximum", largest, "Minimum",smallest)
Note: There were a few bugs in your code as well.
Also, do you really need a float if your inputs are all integers?
question:
Write a program that repeatedly prompts a user for integer numbers until the user enters 'done'. Once 'done' is entered, print out the largest and smallest of the numbers. If the user enters anything other than a valid number catch it with a try/except and put out an appropriate message and ignore it.
Input:
7 ,2 , bob, 10, 4, done.
Desired output:
Invalid input
Maximum is 10
Minimum is 2
Actual output:
Invalid input
Invalid input
Maximum is 10
Minimum is 2
Code:
largest=-1
smallest=None
while True:
num =input("Enter a number: ")
try:
if num == "done" :
break
elif smallest is None:
smallest=int(num)
elif int(num)<smallest:
smallest=int(num)
elif int(num)>largest:
largest=int(num)
else:
raise ValueError()
except ValueError:
print("Invalid input")
print("Maximum is",largest)
print("Minimum is",smallest)
I think there's a more Pythonic way of doing this. Try this:
inputList = []
while True:
num = input("Enter a number:")
try:
num = int(num)
inputList.append(num)
except:
if num == "done":
break
else:
print ("Invalid input. Ignoring...")
print ("Maximum is:",max(inputList))
print ("Minimum is:",min(inputList))
Edit: This code works with Python3. For Python2, you might want to use raw_input() instead of input()
You are already capturing the ValueError in Exception,
So inside, try, you are raising ValueError there you leave the scope for this error.
When you accept input, and it accepts 4 as input, which is neither larger than largest (i.e. 10) nor smaller than the smallest (i.e. 2). So it lands in else part and raises ValueError (as per your code). Hence prints Invalid input twice in your case. So this part is unnecessary as well as makes your solution bogus.
Again, from efficiency point of view -
1 - You are checking smallest == None for every input, which takes O(1) time and is unnecessary if you take it any integer
Here is the solution you are looking for :-
largest=None
smallest=None
while True:
try:
num = input("Enter a number: ")
num = int(num)
if smallest is None:
smallest = num
if largest is None:
largest = num
if num < smallest:
smallest = num
elif num > largest:
largest = num
except ValueError:
if num == 'done':
break
else:
print("Invalid input")
continue
print("Maximum is",largest)
print("Minimum is",smallest)
I have 2 inputs to type and I want to loop through them if the user would enter incorrect input. What I did is I set while True and then try and except and then continue. However in case of second input if the input is wrong then whole loop is repeated from the start - that is from the first input. I would like it to be repeated from the second input. The only thing that I can think of is to put break in the code after first correct input and then set another while True for the second input. What are better ways to do this?
while True:
try:
a = int(input("Type positive integer: "))
except ValueError:
print(" Enter a positive NUMBER!")
continue
if a <= 0:
print("Input can't be 0 or negative!")
continue
else:
try:
b = int(input("Type second positive integer: "))
except ValueError:
print(" Enter a positive NUMBER!")
continue
if b <= 0:
print("Input can't be 0 or negative!")
continue
else:
break
Since your condition is the same for each loop, you could try storing the try-except part as a function which returns the value (or a bool indicating success or failure with a parameter for the value), running the lambda in a for loop for each input you require, storing the result in a list and then getting what you need out as a tuple.
E.g.
def try_get_number_input():
try:
value = int(input("Type positive integer: "))
except ValueError:
print(" Enter a positive NUMBER!")
return False, 0
if value <= 0:
print("Input can't be 0 or negative!")
return False, 0
return True, value
# We require 2 inputs from the user
required_inputs = 2
received_inputs = []
for num in range(0, required_inputs):
values = try_get_number_input()
while not values[0]:
values = try_get_number_input()
received_inputs.append(values[1])
This ensures that the code is DRY (doesn't repeat itself) and is easily changeable (if you require 3 inputs instead, you can easily change it rather than having to add another branch of your while loop)
def getNumber(second=False):
while True:
try:
if second:
number = int(input("Type second positive integer: "))
else:
number = int(input("Type positive integer: "))
except ValueError:
print(" Enter a positive NUMBER!")
continue
if number <= 0:
print("Input can't be 0 or negative!")
continue
return number
a, b = getNumber(second=False), getNumber(second=True)
print(a,b)
You asked what a for loop would look like, here's one example:
vals = []
for msg in ['', 'second ']:
while True:
try:
n = int(input(f"Type {msg}positive integer: ")) # PY3.6
# n = int(input("Type {}positive integer: ").format(msg))) # <=PY3.5
except ValueError:
print(" Enter a positive NUMBER!")
continue
if n <= 0:
print("Input can't be 0 or negative!")
continue
vals.append(n)
break
a, b = vals
you can use decorator for retry logic and single function to read int value
def retry(func):
def wrapper(msg):
while True:
try:
return func(msg)
except Exception as e:
print(e)
return wrapper
#retry
def read_int(msg):
try:
a = int(input(msg))
except:
raise ValueError('Invalid Number')
else:
if a < 0:
raise ValueError('Number should be positive')
return a
a = read_int('type valid positive number: ')
b = read_int('type other valid positive number: ')
print(a, b)
I have a question concerning int(). Part of my Python codes looks like this
string = input('Enter your number:')
n = int(string)
print n
So if the input string of int() is not a number, Python will report ValueError and stop running the remaining codes.
I wonder if there is a way to make the program re-ask for a valid string? So that the program won't just stop there.
Thanks!
You can use try except
while True:
try:
string = input('Enter your number:')
n = int(string)
print n
break
except ValueError:
pass
Put the whole thing in an infinite loop. You should catch and ignore ValueErrors but break out of the loop when you get a valid integer.
What you're looking for isTry / Except
How it works:
try:
# Code to "try".
except:
# If there's an error, trap the exception and continue.
continue
For your scenario:
def GetInput():
try:
string = input('Enter your number:')
n = int(string)
print n
except:
# Try to get input again.
GetInput()
n = None
while not isinstance(n, int):
try:
n = int(input('Enter your number:'))
except:
print('NAN')
While the others have mentioned that you can use the following method,
try :
except :
This is another way to do the same thing.
while True :
string = input('Enter your number:')
if string.isdigit() :
n = int(string)
print n
break
else :
print("You have not entered a valid number. Re-enter the number")
You can learn more about
Built-in String Functions from here.