'Most pythonic way to take user input with a fucntion [closed]

I was wondering what the most pythonic way to take user input with a function is.

In the first example, I have what I see most often, which is to take input outside the function.

#Example1
def add(num1,num2):
    return num1+num2

num1=int(input('num1: '))
num2=int(input('num2: '))
add(num1,num2)

The second example takes user input directly inside the parenthesis when you call the function, which also works well.

#Example2
def add(num1,num2):
    return num1+num2
add(int(input('num1: ')),int(input('num2: ')))

However, if I try to take input from within the function I get an error. Is there a way to do this from within?

#Example3
def add(num1,num2):
    num1=int(input('num1: '))
    num2=int(input('num2: '))
    return num1+num2
add(num1,num2)

Which is the preferred way?



Solution 1:[1]

If you're assigning to num1 and num2 only within the function, you don't need to be passing them as arguments any more. Indeed, you can't pass them as arguments because the code outside of the function doesn't know what value has been entered for them. That's why you're getting an exception, the names num1 and num2 are unbound.

Just delete the arguments:

def add():                    # get rid of parameters here
    num1=int(input('num1: '))
    num2=int(input('num2: '))
    return num1+num2
add()                         # and don't try to pass any arguments

As for what is preferred, probably you want some variation on example 1. If you want the user input to be collected by a function, make it a separate function. The user-input collecting function can call the add function with the values, just like your global code did, without polluting the global namespace.

def add(num1,num2):            # this is unchanged from the early examples
    return num1+num2

def do_stuff():                # put the user input in another function
    num1=int(input('num1: '))
    num2=int(input('num2: '))
    print(add(num1,num2))      # or return here, or do whatever makes sense

Solution 2:[2]

All three examples may be used depend on situation. Here is no wrong example (except that num1 and num2 not need to be passed as function arguments for Example3)

My personal opinion is:

  1. Example3 is bad because it may be hard to test in future. Let's say that you want to test that 2 + 2 == 4:

    def add(n1, n2):
      return n1 + n2
    
    assert 2 + 2 == add(2, 2)
    

    In case of Example3 it is not possible to test add without user input

  2. Your function called add, so add must care only about adding. If you call your function get_input_sum then Example3 will be most correct

  3. add name is little bit wide so it is hard to guess is it should return sum or concat string? If you call it sum then function have to care about what you pass inside it:

    def sum(n1, n2):
      try:
        n1, n2 = int(n1), int(n2)
      except ValueError:
        print('Only numeric values accepted')
        raise
      return n1 + n2
    

    In this case you'll be sure that result of sum will be always correct and '2' + '2' will be 4 but not '22'

    If you cast str -> int and check types outside sum function you have to care about what you pass inside function number or string.

    However if meaning of add is wider and you don't expect to see a real sum (let's say that you want to do something like [1] + [2] => [1, 2]) then you should check types outside the function.

In summary: correct answer depend on context

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Blckknght
Solution 2