Why is my output not formatted as a string?

 # 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.

20 points · 13 comments · view on lemmy.world

13 Comments

rtxn@lemmy.world · 23 pts · 1y

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.

Kissaki@programming.dev · 7 pts · 1y

There's a !python@programming.dev community more appropriate to python specific questions

cherrykraken@lemmy.ca · 6 pts · 1y (2 replies)

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 · 7 pts · 1y (1 reply)

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
cherrykraken@lemmy.ca · 2 pts · 1y

Gahh, serves me right for blindly writing code on my phone!

troyunrau@lemmy.ca · 5 pts · 1y

print(eval(input("Expression:")))

Unsafe coding is best coding ;)

FizzyOrange@programming.dev · 3 pts · 1y (4 replies)

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:
bestboyfriendintheworld@sh.itjust.works · 4 pts · 1y (3 replies)

PyCharm is the way to go to write Python.

FizzyOrange@programming.dev · 1 pts · 1y (2 replies)

Yeah that's a great option too. Not free though (although the pricing is very reasonable IMO). I think if you're this much of a beginner it doesn't make sense to pay for Pycharm.

crmsnbleyd@sopuli.xyz · 4 pts · 1y (1 reply)

The community version is free right

FizzyOrange@programming.dev · 1 pts · 1y

Ah yeah I don't think that existed last time I used it.

palmtrees2309@lemm.ee · 2 pts · 1y

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 · 1 pts · 1y

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