Search code examples
pythonlistpython-2.7operatorsin-place

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?


Solution

  • 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.