Home > Back-end >  Why does input() activate when not being called in dictionary?
Why does input() activate when not being called in dictionary?

Time:10-16

In my code, I have a dictionary of values along with a key called 'custom' which allows me to input an arbitrary value. When I print key values that are NOT 'custom' it still hits the input() field:

Ip = {'argon':15.76,
      'neon':21.56,
      'krypton':14.00,
      'xenon':12.13,
      'helium':24.59,
      'hydrogen':15.42,
      'custom': float(input('Enter ionization potential (eV): '))}

print(Ip['argon'], Ip['helium'])

output:

Enter ionization potential (eV): 1
15.76 24.59

I was under the impression that keys and their associated values are kept suppressed until called, but clearly I misunderstand how dictionaries work.

A quick and dirty way of ameliorating this was to make a conditional statement, but there could be (for some reason) multiple input() dictionary definitions such that I'd have to hard-code a conditional statement for each one. Is there a more Pythonic way of doing this?

def func(key):
    
    if key == 'custom':
        Ip = {key:float(input('Enter ionization potential (eV): '))}

# Is there a way to remove the need for a conditional statement?
    else:
        Ip = {'argon':15.76,
              'neon':21.56,
              'krypton':14.00,
              'xenon':12.13,
              'helium':24.59,
              'hydrogen':15.42}
        
    return print(Ip[key])

func('argon')

output:

15.76

CodePudding user response:

It is being called, as you've realized. When you define the dict, the call is evaluated and its result is inserted into the dict under 'custom', so in that example, 'custom': 1.0. To avoid the call, make it a function instead.

Now that raises the question of how to have mixed types in a dict (floats and functions) and special-casing the functions. One way to get around that is to have two separate dicts: one with floats and a fallback one with functions. For example:

def func(key):
    ionization_potential = {
        'argon': 15.76,
        'neon': 21.56,
        'krypton': 14.00,
        'xenon': 12.13,
        'helium': 24.59,
        'hydrogen': 15.42}
    functions = {
        'custom': lambda: float(input('Enter ionization potential (eV): '))}
    try:
        v = ionization_potential[key]
    except KeyError:
        f = functions[key]
        v = f()
    return v

Demo:

>>> func('argon')
15.76
>>> func('custom')
Enter ionization potential (eV): 1
1.0

Lastly, if a key is not found in either dict, this will raise a KeyError from KeyError, so if I were you, I'd raise a ValueError from None in that case, since the problem is with the value of the argument:

try:
    f = functions[key]
except KeyError:
    raise ValueError(f'key not found: {key!r}') from None
v = f()

Demo:

>>> func('foobar')
Traceback (most recent call last):
  ...
ValueError: key not found: 'foobar'
  • Related