0

I have the following code:

aaa = np.random.rand(20, 1)
aaa *= 200
aaa -= 100

I wonder if it is possible to chain *= and -= operators on the same line. So, the loop over the array would be done only one time and I suppose a slight gain in performance results (of course for big arrays).

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Stef1611
  • 1,978
  • 2
  • 11
  • 30
  • 1
    Why would you assume `aaa *= 200` is faster than `aaa = aaa * 200` ? – Tom Wojcik Apr 20 '21 at 12:05
  • `np.add(np.multiply(aaa,200,out=aaa),100,out=aaa)` might work. Do your own timings. – hpaulj Apr 20 '21 at 12:13
  • @Tom Wojcik. Very good remark. I supposed that with `*=` there was only one operation because there was only one operator and with `a=a*200`, there were two operations multiplication and then affectation. It is not the case, second solution is faster. I am going to ask a new question when I will have done tests. – Stef1611 Apr 20 '21 at 13:39
  • `np.add.at` describes an unbuffered in place `ufunc` operation. This is useful for `a[indicies]+=b` cases where indices contains duplicates. Due to buffering this does not produce the same thing as an iterative calculation. Remember `numpy` is python; it does not rework python syntax or interpretation. It just adds a new class with fast compiled methods. I like to think of it as a LEGO set. It has many fancy pieces, but it does not include a custom plastic injection machine. – hpaulj Apr 20 '21 at 16:26

2 Answers2

2

You cannot chain assignments in Python the way you can in C.

That is because in C an assignment is an expression: it has a value that can be assigned to a variable, or used in another expression. C got this idea from Algol, and those who come from the Pascal tradition tend to regard it as a misfeature. Because...

It is a trap for unwary novices who code if (a = b + c) when they mean if (a == b + c). Both are valid, but generally the second one is what you meant, because the first assigns the value of b + c to a and then tests the truth value of a.

Because assignments are not expressions in Python but statements, you will get a syntax error for if (a = b + c). It's just as invalid as if (return).

If you want to achieve what the C idiom does you can use an assignment expression (new in 3.8). You can explicitly code if (a := b + c) if what you really want to do is assign the value of b + c to a and then test the truth value of a (though technically I believe it actually tests the truth value of b + c; which comes to the same thing).

[And to the style martinets, yes, I do know that parens are redundant in a Python if statement.]

BoarGules
  • 16,440
  • 2
  • 27
  • 44
  • Thanks a lot for this synthetic and clear answer. I am a python beginner and I usually program in C. So, I understand everything with your answer : _in C an assignment is an expression_ and _assignments are not expressions in Python but statements_. I read the PEP 572 and after, I think, I will have a new question. – Stef1611 Apr 20 '21 at 13:03
  • I read something interesting in the PEP 572 _the = statement can be augmented to += and its friends, can be chained, and can assign to attributes and subscripts._ Nevertheless, the = statement can be augmented, can be chained but it is not possible to augment and chain this statement in the same line : `a *=10 -= 20` for example. Right ? – Stef1611 Apr 20 '21 at 13:15
  • Right. Not possible. You get a syntax error. You can chain `=` assignments, as in `a = b = c`, but it is not equivalent to `a = (b = c)` as it is in C, but rather to something like `a,b = (c,) * 2`. – BoarGules Apr 20 '21 at 13:32
  • Reading your comment, I tested (for fun) `(a,b)*=(10,100)` and it does not work. So, `=` could not be augmented in all situation. – Stef1611 Apr 20 '21 at 13:48
1

Doing them in one line would simply be

aaa = (aaa * 200) - 100

Though I doubt you'll see any performance difference between this version and what you wrote.

Cory Kramer
  • 114,268
  • 16
  • 167
  • 218
  • May I suppose that with this expression : 1) aaa is loop over one time for multiplication and a temporary array is created, 2) then this temporary array is loop over for substraction 3) then finally an affectation is done to the initial array aaa ? – Stef1611 Apr 20 '21 at 12:48