Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unclarity on variable cloning behavior

Along with a book I was provided with a Python program, into which I am digging deep now.

The program uses a global data structure named globdat, in a specific routine a numpy array inside globdat is assigned to a local variable:

a = globdat.array

Then in a following while loop the variable a is updated every iteration according to:

a[:] += da[:]

The result of this operation is that globdat.array is updated, which is used in subsequent operations.

Is the usage of [:] required here, or is it merely used to indicate that it also clones into globdat.array? Can anyone clarify this coding style?

like image 217
Steyn W. Avatar asked Dec 15 '22 14:12

Steyn W.


1 Answers

The second [:], in the right-hand-side, is redundant. It just copies da before using it in the concatenation, which is pointless.

We're left with:

a[:] += da

First, let's understand what a += da does. It maps to:

a = a.__iadd__(da)

The call to __iadd__ extends the original list a, and returns self, i.e. a reference to the list. The assignment which happens after, then, has no effect in this case (same as a=a).

This achieves the original goal, i.e. to extend the global array.


Now, What does a[:] += da do? It maps to:

a[:] = a[:].__iadd__(da)

Or more tediously to:

a.__setitem__(slice(None), a.__getitem__(slice(None)).__iadd__(da))

For readability, let's write it as (not a valid python syntax):

a.__setitem__(:, a.__getitem__(:).__iadd__(da))

So a[:].__iadd__(da):

  1. creates a copy of a (call is a2)
  2. concatenate da to a2 in place
  3. return a2

Then the assignment a[:] = ...:

  1. replaces all values in a with all values in a2 in place.

So that too, achieves the original goal, but is wayyyyyy less efficient.


There are some interesting details about this stuff in the answers to this question.

like image 71
shx2 Avatar answered Dec 17 '22 02:12

shx2