4

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?

Steyn W.
  • 86
  • 8

3 Answers3

4

This statement is rather nasty:

a[:] += da[:]

It translates into this:

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

This makes unnecessary copies of both lists.

Assuming a and da are lists, you could much more reasonably use the extend() method:

a.extend(da)
Kevin
  • 28,963
  • 9
  • 62
  • 81
4

If you want to modify a list in place, rather than replace it with a new list, you need to use the slicing syntax.

a[:] = da[:]

In this case though, += will always modify the list in place, so the slicing is redundant.

This might be a perfect example of cargo cult programming.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
4

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.

Community
  • 1
  • 1
shx2
  • 61,779
  • 13
  • 130
  • 153
  • Can you tell whether the slicings make any sense for numpy arrays (or mix of array and list)? The OP confirmed my suspicion and updated the question, and I'm curious about it as well. – Stefan Pochmann May 08 '15 at 10:33