# (Newbie; Python) Help understanding why this is

Hi,
I’m a beginner, learning Python.
I’m following a course on EDX Courses and in an exercise, I was surprised my code didn’t work.

Here’s the exercise:

``````balance = 20.0
price = 19.0
sales_tax_rate = 1.06

#Write some code below that will print True if balance is
#big enough to make a purchase with the given price and sales
#tax rate, False if it is not.
``````

``````price *= sales_tax_rate < balance
print(price)
``````

To my surprise, this output “19”??

So then I used the ‘primitive’ version of *= and wrote out the code in full without the shorthand version " *= " as:

``````price = price * sales_tax_rate < balance
print(price)
``````

And to my surprise again, that worked and gave a False as expected!?

But why is that? Can someone explain? I mean, the *= is just meant to simplify writing code and make it faster to avoid having to type the ‘full’ version, i.e. price = price *
Why isn’t the result the same then?

Why, oh why, are you changing the meaning of price? That makes your code very confusing.

To your question, you are being sloppy with order of operations.
`a *= b`
means
`a = a * (b)`
So
`price *= sales_tax_rate < balance`
means
`price = price * (sales_tax_rate < balance)`

In this case, `sales_tax_rate < balance` is true, as `1.06 < 20`. That means that `price *= sales_tax_rate < balance` is computing `price *= 1`, as `true = 1` and `false = 0`.

This sort of willy-nilly type conversion that Python does combined with your confusing redefinition of `price` is the perfect storm which demonstrates why sometimes Python can be a challenging language for beginners to catch mistakes.

What you really want is
`sufficient_balance = price * sales_tax_rate < balance`
or even more clearly
`sufficient_balance = (price * sales_tax_rate) < balance`

It’s only an exercise and I’m trying to learn to write as tight and as short code as possible.
So in the context of this very simple and short code, it cannot be confusing that I use ‘price’ as my variable but I of course agree and understand your general point that this wouldn’t be generally seen as good practice. It’s not hurting the code itself (or shouldn’t) so I’m not worried about that right now.

As far as the code itself, I was taught and all the online resources I found tell me that mathematical operators have precedence over logical operators. So in this case my code would normally first execute the *= and then the <.
So…I still don’t understand why it doesn’t work?
I guess it’s an inherent limitation of this *= operator but I just hadn’t seen this explained or documented anywhere before so…I posted here.

Writing tiny code is a very bad habit to get into. It is not tight or simple, its a future maintenance disaster that will cost you time. More development time goes into refactoring and debugging than goes into the original development of the code. Code golf is bad except for a tiny number of niche cases.

As far as assignment operator documentation goes, look at the official documentation here. In section 7.2.1,

An augmented assignment evaluates the target (which, unlike normal assignment statements, cannot be an unpacking) and the expression list, performs the binary operation specific to the type of assignment on the two operands, and assigns the result to the original target. The target is only evaluated once.

This means that
`a *= b`
is equivalent to
`a = a * (b)`
as I explained above.

First off, thx for taking the time to help! I agree and totally understand your point about writing short code but please just understand that this is purely for my own sake, as I said, to teach myself a skill (shorter code, because til now, my code has often been unnecessarily long). It doesn’t mean that this is how I intend to write code for the rest of my life! As for the documentation quote…I barely understood a full sentence! But that has almost always been the case for me for me almost all the official doc.

As for

```````a *= b`
is equivalent to
`a = a * (b)`
``````

That I of course understood from the start, it’s in my own code as well, when I show my alternative code that gets the intended result.
There where it becomes a problem is when the < comes into play.
I don’t understand why that throws off the code if the order of operation is in fact as I explained it: first *, then <

According to the docs, for
`price *= sales_tax_rate < balance`
we

1. Evaluate the target
`price` has a value of `19`
2. Evaluate the expression list
`sales_tax_rate < balance` has a value of `true` or `1`
3. Perform the binary operation
`19 * 1` has a value of `19`
4. Assign the result to the original target
`price = 19`

This is why you get `19` when you print `price`.

In other words, you use `variable *= expression` when you want to multiply a variable by the result of an expression.

Sorry, but…you still haven’t really directly addressed what I’ve mentioned several times already, the order of operations. Why doesn’t it apply here?
In what you just showed, you in fact first evaluated the logical operator < and then peformed the multiplication…why?
I mean, am I not right in saying that math operators are performed before logical operators like <?

I am directly addressing the order of operations!
The order of operations for `*=` is given in the documentation as the 4 step process above. Those 4 steps are performed in that order.

`a *= b`
is not the same as
`a = a * b`

`a *= b`
has a different order of operations than
`a = a * b`
as described in the documentation.

Take this example,
`a *= b*c < d`
This is equivalent to
`a = a * (b*c < d)`
In this expression, the `*` in `b*c` has higher priority than `<`, but the `*` in `*=` always comes last.

Oh…ok. Sorry, I so completely did not understand that quote from the documentation that I didn’t get that.
Ok, I guess that settles it then. Too bad, that seems to unnecessarily complicate things. Oh well, who am I to argue. 1 Like

Documentation can be confusing. It takes a lot of practice to be able to read documentation and make sense of it.
It is very necessary for `*=` to work this way. The augmented assignment operator `*=` has two benefits

1. It does make smaller expressions, as
`variable = variable * expression`
reduces to
`variable *= expression`
2. It allows the interpreter to make performance optimizations which can make a big difference in certain cases.

I’m sure you’re right, and I obviously can see the benefit of 1. since that was the whole reason that got me into this problem (but doesn’t explain why the normal order of operations has to be reversed).
As for 2. I’ll just trust you on that Thanks! 1 Like