What does it mean to say that x is evaluated only once in an accumulated substitution sentence such as x+=1?

Asked 2 years ago, Updated 2 years ago, 37 views

I understand the meaning of the in-place operation in the second half, but I don't understand the meaning that x is evaluated only once.
As for the value, I think we can evaluate the initial value of x and x+1 in either way.

7.2.1. Aggregated assignment statement

A cumulative assignment expression, such as x+=1, can be rewritten to make it look much the same as x=x+1, but is not strictly equivalent.For cumulative substitutions, x is evaluated only once.In addition, the actual operation is to perform an in-place operation if possible.This means changing the contents of the previous object instead of creating a new object and substituting it for the target at the time of substitution.

An augmented assignment expression 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.

This is additional information that takes your opinions into account.

Either way, the calculation time was not changed, so it was omitted

Next is the version to add elements to the list.

augmentassign.py

Calculation time: 0.0144632940292358398 [sec]

import time
firstTime = time.time()
i = 0
list1 = [1,1,1]
while i<100_000:
    i+=1
    list1+=[1]

usedTime=time.time() - firstTime
print("Time spent calculating: {0}".format(usedTime)+"[sec]")

normalassign.py

Calculated time: 25.47399997711816 [sec]

import time
firstTime = time.time()
i = 0
list1 = [1,1,1]
while i<100_000:
    i+=1
    list1 = list1 + [1]

usedTime=time.time() - firstTime
print("Time spent calculating: {0}".format(usedTime)+"[sec]")

There seems to be an overwhelming difference between simply in-place and in-place.

I didn't change the calculation time for either of the additional elements, so I omitted it
Maybe it's because both of them are out-place.

Then, I will try to increase the calculation of the original operand itself.
Just to be sure, I have confirmed that the id on the list has not changed.

evalOnLeft_normal.py

Pre-calculation id:140108440645824
list1: [1000001,1000001,1000001,1000001,1000001,1000001,1000001,1000001,1000001]
Calculated id: 140108440645824 Calculated time: 3.2987570762634277 [sec]

import time

firstTime = time.time()
i = 0
list1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
print("Pre-calculated id: {0}".format(id(list1))))

defaultOnLeft():
    global i
    whichIndex=i%10
    return whichIndex


while i<10_000_000:
  
    list1 [evalOnLeft()] = list1 [evalOnLeft()]+1
    i+=1

usedTime=time.time() - firstTime
print("list1:{0}".format(list1))
print("After Calculation id: {0}".format(id(list1))))
print("Time spent calculating: {0}".format(usedTime)+"[sec]")

evalOnLeft_augment.py

Pre-calculated id:140579620745408
list1: [1000001,1000001,1000001,1000001,1000001,1000001,1000001,1000001,1000001]
Calculated id:140579620745408
Calculated time: 2.5201609134674072 [sec]

import time

firstTime = time.time()
i = 0
list1 = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1 ]
print("Pre-calculated id: {0}".format(id(list1))))

defaultOnLeft():
    global i
    whichIndex=i%10
    return whichIndex


while i<10_000_000:
  
    list1 [evalOnLeft()] + = 1
    i+=1

usedTime=time.time() - firstTime
print("list1:{0}".format(list1))
print("After Calculation id: {0}".format(id(list1))))
print("Time spent calculating: {0}".format(usedTime)+"[sec]")

So there was a plausible time difference.
If the operands themselves are calculated more, it may be worth worrying about.

The rest may be the definition of a word that defines whether the number of evaluations is different between the cumulative and normal types, or the actual intention of the doc creator.

python python3

2022-09-30 19:38

5 Answers

Wouldn't it be easier to interpret x as representing anything that can come to the left of the cumulative assignment rather than literally understanding x as a single identifier?

i=0
definc():
    global i
    i+=1
    returni
list = [1,2,3]
list [inc()] + = 1
print(list)//-> [1,3,3]

In such an example, you can clearly see the difference between list[inc()]+=1 and list[inc()]=list[inc()]+1.


2022-09-30 19:38

I think it's a comparison with a substitute.
"If x=x+1, evaluate x on the right and x on the left, but x+=1 only once, so it is not strictly equivalent (internal processing)."
I think it means the degree.


2022-09-30 19:38

What does it mean to say that x is evaluated only once in an accumulated substitution sentence such as x+=1?

"I interpreted ""subsidiary"" as being counted in the evaluation."

  • If x=x+1

    Calculating x+1 -- > x (first assessment)
    Assessment of -->x (second assessment) replacing results with x

  • If x+=1

    Add 1 to x -->x Assessment

If x=x+1

Calculating x+1 -- > x (first assessment)
Assessment of -->x (second assessment) replacing results with x

If x + = 1

Add 1 to x -->x Assessment

However,

A cumulative assignment expression, such as x+=1, can be rewritten as x=x+1, but is not strictly equivalent.For the cumulative assignment, x is evaluated only once.

"I think ""x is evaluated only once for the accumulated substitution"" in is an unnecessary explanation (*)."
"Strictly unequivalent" does not occur in the ""difference in the number of evaluations"", but rather the difference in whether x is being rewritten (subscribed) or not (subscribed) in the new object you generated.

そう I thought so because I couldn't think of an example where behavior changes depending on the number of evaluations.

Add

"For those who add up, x is evaluated only once" is suspicious.

I looked into Python Documentation and found out

x+=1 is equivalent to x=operator.iadd(x,1)
x=x+1 is equivalent to x=operator.add(x,1)

said he.
This allows you to read x's ratings in the same way, whether it's in-place or not.

Also, when I put a print statement into the properties of the class, both of them had the same number of evaluations.

Below is the source and verification results.

operator--- Standard operator in functional form
describes the following:

The operator module provides an efficient set of functions corresponding to Python's built-in operators. For example, operator.add(x,y) is equivalent to the expression x+y

According to this, x=x+1 is equivalent to x=operator.add(x,y).

In-place operator
describes the following:

Many operations have "in-place" versions. The following functions provide a simpler way to call such operators than the usual grammar.For example, the statement x+=y is equivalent to x=operator.iadd(x,y).In other words, z=operator.iadd(x,y) is equivalent to the compound statement z=x;z+=y.

According to this, x+=1 is equivalent to x=operator.iad(x,1).

[Code used for verification]

class Sample():
    def__init__(self, x):
        self.xx = x
    @property
    defx(self):
        print('get x==>',self.xx)
        return self.xx
    @x.setter
    def x (self, x):
        print('set x<==',x)
        self.xx = x

sample=Sample(12)
sample.x + = 1
print(sample.x)
sample.x = sample.x+1
print(sample.x)

[Results]

get x==>12
set x<==13
get x == > 13
13
get x == > 13
set x<==14
get x == > 14
14

Additional 2

"For those who add up, x is evaluated only once" is suspicious.

is withdrawn.

From answers and comments from dosec, OOPer, peppaa, oriri5,

A cumulative assignment expression, such as x+=1, can be rewritten as x=x+1, but is not strictly equivalent.For the cumulative assignment, x is evaluated only once.

If interpreted as having a different number of evaluations of 」x を before ++= や or ++ 」 operations, の it is understandable that xx is evaluated only once しか.

Different values for each f() called
The reason why x[f()]=x[f()]+1 and x[f()]+=1 results are different is because x[f()] evaluates differently.


2022-09-30 19:38

If the left side x has side effects, you will be in trouble if you don't specify a one-time evaluation

Example of if other languages are acceptable

int*p=&array[i];
*p+++=1; // *p++=*p+++1; replaces "undefined behavior"
// I don't know if p[i] will change or p[i+1] will change if there is only one evaluation.

Example

inta, debugcount;
int&func() {++ debug count;return a;}
func()+=1;// Same as above, debugcount is confirmed to increase by 1 for one evaluation


2022-09-30 19:38

What does it mean to say that x is evaluated only once in an accumulated substitution sentence such as x+=1?

It literally means that x is evaluated only once, but I think it is intended to be the expression +=1.
Here's an example of OOper essentially the same as what he says, but different from the substitution statement.

7.2.1. Aggregated assignment statement

augmented_assignment_stmt::=ugtarget augop(expression_list|yield_expression)
target:: = identifier | attributeref | subscription | slicing
augop::="+="|"-="|"*="|"@="|"/="|"//="|"%="|"**="
| ">>="|"<="|"&="|"^="|"|="

There is a subscription in the target, and the subscript notation is also covered, so lst is used as the
lst[n]+=1
is also applicable.
6.3.2.Subscription

subscription::=primary"["expression_list"]"
If the primary is a sequence, the evaluation result of the expression list must be an integer or a slice (discussed in the following section).

In the description, you can specify an expression that returns an integer to n for the list.
That's why

lst=[1,3,5]
it=iter(range(5))
lst[next(it)]+=1#lst[0]+=1
print(lst)# [2,3,5]

If so, lst[next(it)] is evaluated only once, so lst[0]+=1 but

lst=[1,3,5]
it=iter(range(5))
lst [next(it)] = lst [next(it)] +1 #lst[1] = lst[0] +1
print(lst)#[1,2,5]

In this case, 6.16. According to the evaluation order, the right-hand lst [next(it)] is evaluated first to lst[0], and the left-hand lst[next(it) is evaluated later, so it is different from lst[1].


2022-09-30 19:38

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.