When I assign a value into an array the scope of the variable remain local (see loc()
).
However if I access the element of an array the scope becomes global ( see glob()
)
import numpy as np
M = np.array([1])
def loc():
M = 2
return 0
def glob():
M[0] = 3
return 0
loc()
print M
>>> [1]
glob()
print M
>>> [3]
Why does this happen ? How can i locally modify the elements of an array without modifying the array globally? I need to have a loop inside my function changing one element at a time.
You're mixing several things here.
First of all, M = 2
creates a local variable named M
(you can see it in locals()
) and prevents you from accessing the original M
later on (although you're not doing it... But just to make a point). That's sometimes referred to as "shadowing".
Second of all, the np.array
is a mutable object (the opposite of an immutable object), and changes to it will reflect in any reference to it. What you have in your glob
function is a reference to M
.
You can look at an np.array
as a piece of memory that has many names, and if you changed it, the changes will be evident no matter what name you're using to access it. M[0]
is simply a reference to a specific part of this memory. This reflects the object's "state".
If you'd do something like:
M = np.array([1])
def example()
another_name_for_M = M
M = 2
another_name_for_M[0] = 2
you would still see the global M
changing, but you're using a new name to access it.
If you would use a string
, a tuple
, a frozenset
and the likes, which are all immutable objects that can not be (easily) changed, you wouldn't be able to actually change their state.
Now to your question, if you don't want the function to mutate the array just send a copy of it using np.copy
, and not the actual one:
import numpy as np
my_array = np.array([1])
def array_mutating_function(some_array):
some_array[0] = 1337
print some_array # prints [1337]
# send copy to prevent mutating the original array
array_mutating_function(np.copy(my_array))
print my_array # prints [1]
This will effectively make it immutable on the outer scope, since the function will not have a reference to it unless it's using it's name on the outer scope, which is probably not a good idea regardless.
If the function should never change any array, move the copy to be made on inside the function no matter what array is sent, preventing it from changing any array that was sent to it:
def array_mutating_function(some_array):
some_array = np.copy(some_array)
some_array[0] = 1337
SImply explaining.:
- cannot update a global varaible inside a funcion unless access it as global inside function.
- But it can modify
Check:
import numpy as np
M = np.array([1])
def loc():
global M
M = 2
return 0
def glob():
M[0] = 3
return 0
loc()
print M
>>>2