-3

I'm trying to use this loop to condense existing code, but storing the operators in a list and then drawing from it doesn't work, it throws this error: TypeError: unsupported operand type(s) for +: 'float' and 'str'

I understand that it's not interpreting the operator variable as an actual math operation, it's reading it as a str, but I'm not sure how to fix that. Here's the complete loop I've built.

operators = ["+", "-", "*", "/", "^"]

for operator in operators:
    math_expression = input("Enter your math expression, or (q)uit: ")
    print("Operator found " + operator)
    operator_position = math_expression.find(operator) # find operator
    print("Found " + operator + "operator at index " + str(operator_position))
    first_number = math_expression[:operator_position] # find first number
    second_number = math_expression[operator_position + 1:] # find second number
    answer = float(first_number) + operator + float(second_number)
  • What you're trying is equivalent to something like `1.5 + "*" + 0.5`, which would just result in that error, since you're trying to concatenate floating point numbers with strings. You could be using something like [`eval`](https://docs.python.org/3/library/functions.html#eval) or `exec`, have you tried those? They should only be used if you're not trying to create something secure though. – Random Davis Nov 23 '20 at 16:50
  • 2
    Don't use `eval` or `exec` though! They can be used to execute any arbitrary code. – AKX Nov 23 '20 at 16:51
  • @RandomDavis I have not tried that, I'll look into it, thanks! – aidenmitchell Nov 23 '20 at 16:51
  • 1
    Create a *mapping* (i.e. a dict) from the string to a function which executes whatever operation you want. e.g. `{"+": lambda x,y: return x+y, "-": lambda x,y: x - y, ...}`, or using `import operator`, you can use `{"+": operator.add, "-": operator.sub, ...}` – juanpa.arrivillaga Nov 23 '20 at 16:51
  • @Iguananaut That seems a little complicated, but, yes, I'm trying to create a calculator. – aidenmitchell Nov 23 '20 at 16:52
  • @juanpa.arrivillaga Yeah I'd love to start with a different format, but I can't store them otherwise, at least I don't think. – aidenmitchell Nov 23 '20 at 16:53
  • @aidenmitchell **of course you can**. See my edit to my previous comment – juanpa.arrivillaga Nov 23 '20 at 16:53
  • 1
    @aidenmitchell well, because creating a calculator, "correctly" *is complicated*. It would involve writing a parser, at least, for the input strings you want to process. You can, of course, use `eval` or `exec` which uses the Python parser, but as noted, generally you want to avoid `eval`ing strings from user input, that is very unsafe – juanpa.arrivillaga Nov 23 '20 at 16:54
  • I picked one existing question about this at random (there are many). But implementing a simple calculator program is a fairly typical exercise and something you can search around about. You can get sophisticated with it but for starters if you just want to handle expressions with a single infix operator, create a mapping from the operator (eg the string '+' to a function that computes it (eg. operator.add) – Iguananaut Nov 23 '20 at 16:55
  • Can I mark a comment as an answer? – aidenmitchell Nov 23 '20 at 16:56
  • @Iguananaut it's such a terrible beginners exercise. – juanpa.arrivillaga Nov 23 '20 at 16:56

1 Answers1

1

The operator module has functions that represent basic operations, such as the ones you're looking for.

Here, we

  • stuff those operators into a dict
  • loop over the symbol and function for each operator
  • if the symbol is found in the user input, the str.partition() function splits the string into segments before and after the symbol...
  • and then we just call the function.
import operator

operators = {
    "+": operator.add,
    "-": operator.sub,
    "*": operator.mul,
    "/": operator.truediv,
    "^": operator.pow,
}

expression = "5 + 3"  # elided input to make debugging faster

for symbol, func in operators.items():
    if symbol in expression:
        a, _, b = expression.partition(symbol)
        answer = func(float(a), float(b))
        print(answer)
        break
AKX
  • 152,115
  • 15
  • 115
  • 172