# Ask user to enter an expression and display output
def main():
    expression = input("Expression: ")

    print(calculate(splitter(expression)))


# Split expression into components and assign to variables as float values
def splitter(expression):
    x, y, z = expression.split()

    return x, y, z

# Calculate expression result
def calculate(x, y, z):
    x, z = float(x), float(z)

    if y == "+":
        return str(round((x + z), 1))
    elif y == "-":
        return str(round((x - z), 1))
    elif y == "*":
        return str(round((x * z), 1))
    else:
        return str(round((x / z), 1))



main()

I am getting traceback errors for any expression (1 + 1) I enter.

  • FizzyOrange
    link
    fedilink
    arrow-up
    2
    ·
    5 hours ago

    Yeah others have pointer out the error, but I want to really recommend using VSCode with the Python extension and static types. It will make finding these errors super easy because it adds a red underline exactly where the problem is.

    Static types means:

    def splitter(expression: str) -> tuple[str, str, str]:
    ...
    def calculate(x: str, y: str, z: str) -> str:
    
  • rtxn@lemmy.world
    link
    fedilink
    arrow-up
    20
    arrow-down
    1
    ·
    edit-2
    13 hours ago

    Change this:

        print(calculate(splitter(expression)))
    

    to this:

        print(calculate(* splitter(expression)))
    

    The error is that calculate expects three float values (x, and y, and z), but splitter returns a tuple object ((x, y, z) as one object, similar to arrays in other languages):

    >>> type(splitter("1 + 2"))
    <class 'tuple'>
    

    Prepending a tuple or a list with a * operator (unpacking or splatting) unpacks the object into its individual items that are then passed to the function as separate arguments.

    In fact, str.split() already returns a tuple. By assigning multiple values at once in x, y, z = expression.split(), you actually unpack the returned tuple into individual values, then in return x, y, z, you pack those values into a tuple.

  • Troy@lemmy.ca
    link
    fedilink
    arrow-up
    5
    ·
    10 hours ago

    print(eval(input(“Expression:”)))

    Unsafe coding is best coding ;)

  • cherrykraken@lemmy.ca
    link
    fedilink
    arrow-up
    7
    arrow-down
    1
    ·
    edit-2
    11 hours ago

    Functions in Python can only return a single value. While you are allowed to comma-separate additional values, as you have done, they are combined into a single tuple object that wraps the intended values.

    As such, your splitter function is returning a single tuple containing three strings. Your calculate function is expecting three individual arguments (I’m guessing that the error trace mentions this).

    To get around this, you can use the splat/asterisk operator to “unpack” the items from the tuple:

    a, b, c = splitter(expression)
    # or, inline
    calculate(*splitter(expression))
    

    Edit: removed bad asterisk

    • Eager Eagle@lemmy.world
      link
      fedilink
      English
      arrow-up
      7
      ·
      edit-2
      13 hours ago

      Functions in Python can only return a single value

      that’s not true accurate, this is valid code in this context:

      x, y, z = splitter(expression)
      

      Where x, y, and z are strings. But when you do this, akin to what OP did:

      value  = splitter(expression)
      

      then value is a tuple of 3 strings.

      In fact, unpacking with asterisk at assignment, like below, is not allowed:

      x, y, z = *splitter(expression)
      
          x, y, z = *splitter(expression)
                    ^^^^^^^^^^^^^^^^^^^^^
      SyntaxError: can't use starred expression here
      
  • palmtrees2309@lemm.ee
    link
    fedilink
    English
    arrow-up
    3
    arrow-down
    1
    ·
    edit-2
    13 hours ago

    After the split x becomes (1 and z becomes 1). They can’t be converted to float. I think that’s why. Let me run the code. Edit - Also as you are returning a, b, c from splitter but Python functions return a single object. The a, b, c turns to a tuple. But you are using js syntax I think. So we have to unwrap inside the calculate function.

    Now my original comment is not useful but you can try to introduce a conditional to check of the numbers x and z are actually numbers before converting to floats

    # Ask user to enter an expression and display output
    
    def main():
        expression = input("Expression: ")
        print(calculate (splitter (expression)))
    
    # Split expression into components and assign to variables as float values
    
    def splitter (expression):
        print(expression)
        x, y, z = expression.split()
        print(expression.split())
        return x, y, z
    
    # Calculate expression result
    
    # Changes Beginning
    def calculate(numbers):
        x,y,z = numbers
    # Changes End
    
        x, z = float(x), float(z)
        if y == "+":
            return str(round((x + z), 1))
        elif y == "-":
            return str(round((xz), 1))
        elif y == "*":
            return str(round((x*z), 1))
        else:
            return str(round((x / z), 1))
    
    main()
    
    
  • Eager Eagle@lemmy.world
    link
    fedilink
    English
    arrow-up
    2
    arrow-down
    1
    ·
    edit-2
    13 hours ago

    you’re missing the asterisk to expand the tuple returned by splitter:

    print(calculate(*splitter(expression)))
    

    if you’re using VS Code, check out the error lens extension