-1

I have the following code (probably self-explanatory):

def main():
    print("Please input 2 numbers to operate on: ")
    value1 = int(input())
    value2 = int(input())
    print("Please input an operator: ")
    operator = str(input())
    result ={
        '+': lambda x, y: x+y,
        '-': lambda x, y: x-y,
        '*': lambda x, y: x*y,
        '/': lambda x, y: x/y
        }.get(operator(value1, value2), "Error")
    print(result)

if __name__ == "__main__":
    main()

But I get the error:

Please input 2 numbers to operate on:
4
4
Please input an operator:
*
Traceback (most recent call last):
  File "C:\Users\Megapoort\source\repos\Python switch function\Python_switch_function.py", line 17, in <module>
    main()
  File "C:\Users\Megapoort\source\repos\Python switch function\Python_switch_function.py", line 13, in main
    }.get(operator(value1, value2), "Error")
TypeError: 'str' object is not callable

I dont really understand what I did wrong here.

Tom Gebel
  • 744
  • 1
  • 4
  • 13

5 Answers5

2

You're putting the parenthesis in the wrong place- .get(operator(value1, value2), "Error") calls operator with value1 and value2.

What you probably meant was .get(operator, "Error")(value1, value2) which correctly calls the results of the .get with the specified arguments.

Kevin Sheng
  • 411
  • 1
  • 5
  • 8
  • 3
    And you'll *still* get the error if `get` can return `"Error"`. – chepner Oct 13 '20 at 19:23
  • 1
    I don't know if that's supposed to be a bad thing- if you give it a bad operator, it *does* return an error. – Kevin Sheng Oct 13 '20 at 19:30
  • 1
    If you don't care about that error, they you probably wouldn't care enough to use `get` over simply risking a `KeyError` with `{...}[operator]`. – chepner Oct 13 '20 at 19:33
1

This isn't a case where you should use get, as there isn't really a default function to use. If the user inputs an undefined operator, you should raise an exception (just not necessarily a KeyError) or exit.

def main():
    print("Please input 2 numbers to operate on: ")
    value1 = int(input())
    value2 = int(input())
    print("Please input an operator: ")
    operator = str(input())
    try:
        op = {
        '+': lambda x, y: x+y,
        '-': lambda x, y: x-y,
        '*': lambda x, y: x*y,
        '/': lambda x, y: x/y
        }[operator]
    except KeyError:
        sys.exit(f"Invalid operator {operator}")

    result = op(value1, value2)
    print(result)

If you were to use get, it should also return a function. For example,

result = {...}.get(operator, lambda x, y: None)(value1, value2)
chepner
  • 497,756
  • 71
  • 530
  • 681
1

You are close to want you want to achieve. It might help if you split the result assignment statement in separate steps:

First, make a mapping between the operator symbol (a str) and the lambda, fully equal to your example:

    operator_map = {
        '+': lambda x, y: x+y,
        '-': lambda x, y: x-y,
        '*': lambda x, y: x*y,
        '/': lambda x, y: x/y,
    }

Next, get the lambda (a function object) your operator symbol maps to, and let the interpreter generate an exception if an unknown operator was entered:

    func = operator_map[operator]

Next, call the function with the two operands you have read earlier:

    result = func(value1, value2)

If you would really like to combine it all in one statement:

    result = {
        '+': lambda x, y: x+y,
        '-': lambda x, y: x-y,
        '*': lambda x, y: x*y,
        '/': lambda x, y: x/y,
    }[operator](value1, value2)

Tip: The lambda expressions you provided are already provided in the standard library operator module. lambda x, y: x+y is equivalent to operator.add, x-y --> operator.sub, x*y --> operator.mul, and the x/y lambda is equivalent to operator.truediv.

Jan-Hein
  • 68
  • 6
0

Your operator = str(input()) is one value a string. But later you want 2 values from it: operator(value1, value2) also operator is at that moment a string not a function so there is no way operator() will yield any results beside an error.

Fix it like this:

print("Please input 2 numbers to operate on: ")
value1 = 1
value2 = 2
print("Please input an operator: ")
operator = str("+")
result ={
    '+': lambda x, y: x+y,
    '-': lambda x, y: x-y,
    '*': lambda x, y: x*y,
    '/': lambda x, y: x/y
    }.get(operator, "Error")
print(result(value1, value2))
Andreas
  • 8,694
  • 3
  • 14
  • 38
0
result ={
    '+': lambda x, y: x+y,
    '-': lambda x, y: x-y,
    '*': lambda x, y: x*y,
    '/': lambda x, y: x/y
    }.get(operator(value1, value2), "Error")

You are doing too many things in a single statement. Break it into smaller pieces:

operations = {
    '+': lambda x, y: x+y,
    '-': lambda x, y: x-y,
    '*': lambda x, y: x*y,
    '/': lambda x, y: x/y
}
foo = operator(value1, value2)
result = operations.get(foo, "Error")

Now we can see that operator(value1, value2) is causing the error because the value of operator is a string and we can't use parentheses after a string. Instead, we need parentheses after a function. And the function is in the dictionary that you can look up with a string:

operation = operations.get(operator)
result = operation(value1, value2)

The moral of the story is to break up a complex statement into smaller pieces so that you can reason about each little step rather than getting mixed up about one large step.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268