Search code examples
python-3.xvariablestype-conversionuser-input

Unable to accept user-input and use it without errors


Ok, I've been on this for a few days and not able to fix it myself.

Python 3 and working on this snippet of code below. My problem is with variable types and the user-input. This code is part of a larger code I'm wanting a user (me mostly) to be able to use meaningful variable names ("m_earth" for earth mass, and similar quantities) as input for the calculation for "F1", and for others I'd like to use....IF...I can get this part working first.

I have tried using "float" and "int" and it really just creates other errors that I can't fix.

Below the code included is what happens when this code is used.

Anyone have some suggestions...please?

Thanks

G = float(6.674E-11)

# All masses are in Kg
m_earth = 5.972E24
m_moon = 7.345E22

m1 = input('Enter the first mass  ')
print(m1, 'Kg')

m2 = input('Enter the second mass  ')
print(m2, 'Kg')

r = input('Enter the center-to-center distance from mass m1 to mass m2  ')

F1 = G * m1 * m2 / r ** 2
print('The gravitational force is  ', F1, "N")

Enter the first mass  m_earth
m_earth Kg
Enter the second mass  m_moon
m_moon Kg
Enter the center-to-center distance from mass m1 to mass m2  3E12
Traceback (most recent call last):
  File "C:/Users/xyz/PycharmProjects/My Python Programs/try it.py", line 15, in <module>
    F1 = G * m_earth * m_moon / r ** 2
TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

Process finished with exit code 1


Solution

  • You are getting this error because input() always returns a string. The reason you cannot add arbitrary strings to ints or floats is because in most cases it does not make sense.

    Consider 3 + 'Hello'. What would you expect the outcome to be?

    So how do we take care of this? We convert it to something python understands as being allowed to perform arithmetic functions on. In python those types are int(whole numbers) and float fractional numbers. For arguments sake, there are many others but you don't need them for your example.

    Since we cannot guarantee that the user has entered a number, we need some type of check to make sure they did.

    That is where we can use a try/except block.

    G = float(6.674E-11)
    
    # All masses are in Kg
    m_earth = 5.972E24
    m_moon = 7.345E22
    
    m1 = input('Enter the first mass  ')
    print(m1, 'Kg')
    
    m2 = input('Enter the second mass  ')
    print(m2, 'Kg')
    
    r = input('Enter the center-to-center distance from mass m1 to mass m2  ')
    
    # any Error that occurs in the try block
    # will hand control to the except block
    # if the type of Exception in except is 
    # the type of error that occurred
    try:
        # here we try to convert the variable m1 of type str
        # to a variable of type float
        # since float() "returns" a float and does not convert in place
        # we need to catch the output it gives into the same variable
        m1 = float(m1)
        m2 = float(m2)
        r = float(r)
        F1 = G * m1 * m2 / r ** 2
        print('The gravitational force is  ', F1, "N")
    # any conversion error here will result in a ValueError
    # We can catch that specific error and alert the user they 
    # mis-entered some data
    except ValueError as v:
        print('Some of your input is not valid.')
    

    But you wanted be able to specify the name of the variable. For that you can use a python dict. A dict maps a key to some value. Keys can be a number of types, but most importantly, they can be a str, the type that input() returns. In this case it could be m_earth.

    # we need sys to do an early exit in the program
    # if the data entered is not a key in the dict
    import sys
    
    G = float(6.674E-11)
    
    # All masses are in Kg
    my_dict = {'m_earth': 5.972E24,
               'm_moon': 7.345E22}
    
    m1 = input('Enter the first mass  ')
    # this will raise a KeyError
    # if the key is not in your dict
    try:
        m1 = my_dict[m1]
    except KeyError as k:
        sys.exit('That name is invalid.')
    print(m1, 'Kg')
    
    m2 = input('Enter the second mass  ')
    try:
        m2 = my_dict[m2]
    except KeyError as k:
        sys.exit('That name is invalid.')
    
    r = input('Enter the center-to-center distance from mass m1 to mass m2  ')
    
    try:
        r = float(r)
        F1 = G * m1 * m2 / r ** 2
        print('The gravitational force is  ', F1, "N")
    except ValueError as v:
        print('Some of your input is not valid.')