1

I am new to python, previously was using Matlab, and have some confusion regarding variables in python.

I am trying to rewrite a Matlab code in python, and here is where confusion happens. Lets say I have the following case:

>>> A = np.array([[1,2,3],[4,5,6]])
>>> out = np.array([[True, False, True],[False, True, False]])
>>> 
>>> B = A
>>> 
>>> B[out] = A[out]+1
>>> 
>>> B
array([[2, 2, 4],
       [4, 6, 6]])
>>> A    
array([[2, 2, 4],
       [4, 6, 6]])

In Matlab, A does not change with the same piece of code, but in python, it does. Anyone can explain why and what is the best way to avoid the change of A?

Code-image: why assigning A to B is kept in the flow?

Community
  • 1
  • 1
  • 1
    Welcome to Stack Overflow! [Please don't post your code as an image](//meta.stackoverflow.com/q/285551). It's hard to read, prevents text-based searching, and lowers the overall presentation value of the post. @Kevin Helping ppl by "inlining" the image is not really helping the quality of the post. – Patrick Artner Jan 03 '19 at 16:06
  • 2
    In Python, when you have a complex structure like an array assigned to `A`, `A` actually holds a *reference* (pointer) to the data. When you write `B = A`, this is assigning the "reference" to the variable to `B`. Both `A` and `B` *point* to the same array. See, [How to clone or copy a list](https://stackoverflow.com/questions/2612802/how-to-clone-or-copy-a-list) – lurker Jan 03 '19 at 16:07
  • See https://stackoverflow.com/questions/45053461/what-happens-when-you-assign-the-value-of-one-variable-to-another-variable-in-py?noredirect=1&lq=1 and https://stackoverflow.com/questions/6431973/how-to-copy-data-from-a-numpy-array-to-another –  Jan 03 '19 at 16:08
  • Read the following: https://nedbatchelder.com/text/names.html – juanpa.arrivillaga Jan 03 '19 at 17:09

1 Answers1

2

By doing

B = A

you are creating another reference to the same object A so all the changes incurred by A will be automatically reflected in B. The proper (few) ways to copy the list/array in this case

B = A[::]

or

B = A.copy()

This way you copy the elements into a list variable without creating a pointer to the original variable A thereby decoupling them in term sof memory addresses.

As pointed out by Jon Clements,

[::] means start, end with a step size of 1 which means [0:len(obj):1] whereas [:] means [:len(obj)] where obj is your object.

As pointed out by @Patrick below, if you A is a numpy matrix, you can also do

 B = np.copy(A)
Sheldore
  • 37,862
  • 7
  • 57
  • 71
  • 1
    @PatrickArtner: I just tried and it seems both does the same thing, i.e., create a copy without a reference – Sheldore Jan 03 '19 at 16:10
  • 1
    @PatrickArtner it's the same as `[:]`... it's just that `[::]` translates to start, end with a step size of 1... so `[:]` is the same as `[:len(obj)]` and `[::]` is the same as `[0:len(obj):1]` kind of thing... – Jon Clements Jan 03 '19 at 16:12
  • @JonClements: So if I am not wrong, `[:]` is basically taking the default step size of 1 too. – Sheldore Jan 03 '19 at 16:14
  • Yes... it's just syntax... so either `:` or `::` is enough to just make everything defaults... it's very weird to see `::` in the wild though... :) – Jon Clements Jan 03 '19 at 16:16
  • @JonClements: Let me put your suggestion and comments in my answer to make it more elaborative. Thanks a lot for the words – Sheldore Jan 03 '19 at 16:16
  • Yeah... I'm not convinced I've explained that very well... basically `:` is convenience syntax for [slice objects](https://docs.python.org/3/library/functions.html#slice) themselves... – Jon Clements Jan 03 '19 at 16:20