Does a simple assignment in Python evaluate twice?

  Kiến thức lập trình

In this page of Python official reference, there’s the following sentence:

An augmented assignment statement like x += 1 can be rewritten as x = x + 1 to achieve a similar, but not exactly equal effect. In the
augmented version, x is only evaluated once.

It seems to suggest that a simple assignment would evaluate x twice. I wanted to test this, so created the following example code:

X = [print("ttHello X"), 0 ]
X = X + [1]

This actually prints “Hello X” only once, at the first assignment. I’ve tried making X[0] a function that prints something instead, and it doesn’t work.

Here’s a small example with setters and getters:

class X:
    def __init__(self, value:int = 0):
        self._value = value

    @property 
    def value(self):
        print("HEllo X!")
        return self._value

    @value.setter
    def value(self, value):
        self._value = value

Now, I experiment with the code below:

x = X(1)
x.value = x.value +1 
x.value

This prints “HEllo X!” twice. I was expecting it to be thrice.

x = X(1)
x.value +=1 
x.value

This prints “HEllo X!” twice, the same number of times as with the simple assignment.

Is there a way to check whether Python really evaluates x twice with a simple assignment?

2

An example where you can see the difference:

d = {None: 0}
d[print('hello')] += 1

d = {None: 0}
d[print('world')] = d[print('world')] + 1

Output (Attempt This Online!):

hello
world
world

Or with your question’s attempt, but using value [1] instead of 1 and accessing its element:

x = X([1])
x.value[0] = x.value[0] +1 
x.value[0]

print()

x = X([1])
x.value[0] +=1 
x.value[0]

Now it does print thrice and twice, as the first half does use the getter three times instead of using it two times and using the setter once.

Attempt This Online!

3

You seem to have misunderstood what they mean by

x is only evaluated once

in that sentence, x is assumed to be an expression (which can be evaluated)

In the example you wrote, the expression that gets evaluated twice is simply X, so the only thing that “happens twice” is the name resolution.


Note that this is still not equivalent, as the X = X + [1] calls the list.__add__ function, which creates an entirely new list and then sets X to that new list,

whereas X += [1] calls the list.__iadd__ method which modifies X inplace (and should therefore be vastly faster in a lot of cases)

1

Maybe during parsing?

Looks like they are the same bytecode:

>>> import dis
>>> def foo():
...     x = 0
...     x += 1
...
>>> def bar():
...     x = 0
...     x = x + 1
...
>>> dis.dis(foo)
  1           0 RESUME                   0

  2           2 LOAD_CONST               1 (0)
              4 STORE_FAST               0 (x)

  3           6 LOAD_FAST                0 (x)
              8 LOAD_CONST               2 (1)
             10 BINARY_OP               13 (+=)
             14 STORE_FAST               0 (x)
             16 RETURN_CONST             0 (None)
>>> dis.dis(bar)
  1           0 RESUME                   0

  2           2 LOAD_CONST               1 (0)
              4 STORE_FAST               0 (x)

  3           6 LOAD_FAST                0 (x)
              8 LOAD_CONST               2 (1)
             10 BINARY_OP                0 (+)
             14 STORE_FAST               0 (x)
             16 RETURN_CONST             0 (None)

The only difference is

10 BINARY_OP 13 (+=)

and

10 BINARY_OP 0 (+)

I guess you need to have a look at how they’re implemented

The documentation further gives a good explanation:

An augmented assignment statement like x += 1 can be rewritten as x = x + 1 to achieve a similar, but not exactly equal effect. In the augmented version, x is only evaluated once. Also, when possible, the actual operation is performed in-place, meaning that rather than creating a new object and assigning that to the target, the old object is modified instead.

Unlike normal assignments, augmented assignments evaluate the left-hand side before evaluating the right-hand side. For example, a[i] += f(x) first looks-up a[i], then it evaluates f(x) and performs the addition, and lastly, it writes the result back to a[i].

1

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website Kho Theme wordpress Kho Theme WP Theme WP

LEAVE A COMMENT