You did not modify the elements of the original array, but rather re-assigned a new list to the arr variable. Your intuition of thinking changes to elements would be reflected in arr1 if you properly accessed its elements is indeed true as lists are mutable in Python. For instance,
arr = [1,2,3]
arr1 = arr
arr[1] = 4
print(arr1) #this prints [1,4,3]
Answer from miradulo on Stack OverflowYou did not modify the elements of the original array, but rather re-assigned a new list to the arr variable. Your intuition of thinking changes to elements would be reflected in arr1 if you properly accessed its elements is indeed true as lists are mutable in Python. For instance,
arr = [1,2,3]
arr1 = arr
arr[1] = 4
print(arr1) #this prints [1,4,3]
There are several ways to copy an array, but
arr1 = arr
is not one of them (in C-speak, that is just an aliased pointer). Try one of
arr1 = arr[:] # slice that includes all elements, i.e. a shallow copy
arr1 = copy.copy(arr) # from the copy module, does a shallow copy
arr1 = copy.deepcopy(arr) # you guessed it.. ;-)
after any of those you will see that changes to arr1 and arr are independent (of course if you're using a shallow copy then the items in the list will be shared).
Apologies if this is mentioned somewhere else. I have been searching the web but not found an example that helped me understand.
I would like to create an array where each element is a reference to an element in another array. Syntax may not be exact but the general idea is:
a = [1, 2, 3] b = [] b.append(a[2]) #create references to a but reverse the order b.append(a[1]) #this would be done dynamically in the real code b.append(a[0]) a[0] = 10
Now I would like a situation where because I set b[2] equal to a[0], when a[0] = 10, b[2] 'points' to it and asking for b[2] also gives 10. Is this possible? Do I have to create array b in a different way?
Thanks in advance for any help. I read all comments even if a solution is already found.
I have been learning how to use 2D arrays in python this year for my computer science class. I thought I understood them until I tried using them in my Tkinter program which will hopefully eventually become battleship for an assignment. I asked my teacher if he knew the problem here, but he is also stumped. I am trying to reference a value in an array in a function, but every time the value is called in the function, the first value is messed up. I am not sure what the problem is, and neither of us could understand it. When a button is pushed, the terminal should print the values listed on the button, however the first value is always 6. If anyone could suggest anything I am more than welcoming of feedback at this point. My entire program is outlined below. Thanks in advance!
from tkinter import *
from tkinter import ttk import platform
opSys = platform.system()
def clicked(b): info = b.grid_info() print ("\n") print (str(info["column"]) + ", " + str(info["row"])) print (playerGridArray[(info["column"])][(info["row"])]) print (playerGridArray[2][0])
playerGridArray = [[0]*7]*7
win = Tk() win.title("Battleship") win.config(bg="light sky blue")
x = 0 y = 0 n = 1
while y < 7: b = Button(win, text=(str(x) + ", " + str(y)), width = 3, height = 2, ) b["command"] = lambda b=b: clicked(b)
b.grid(row = y, column = x)
print (str(x) + " " + str(y))
playerGridArray[x][y] = str(x) + ", " + str(y)
print(playerGridArray[x][y])
n = n + 1
if x == 6:
x = 0
y = y + 1
else:
x = x + 1
In Python, all variable names are references to values.
When Python evaluates an assignment, the right-hand side is evaluated before the left-hand side. arr - 3 creates a new array; it does not modify arr in-place.
arr = arr - 3 makes the local variable arr reference this new array. It does not modify the value originally referenced by arr which was passed to foo. The variable name arr simply gets bound to the new array, arr - 3. Moreover, arr is local variable name in the scope of the foo function. Once the foo function completes, there is no more reference to arr and Python is free to garbage collect the value it references. As Reti43 points out, in order for arr's value to affect a, foo must return arr and a must be assigned to that value:
def foo(arr):
arr = arr - 3
return arr
# or simply combine both lines into `return arr - 3`
a = foo(a)
In contrast, arr -= 3, which Python translates into a call to the __iadd__ special method, does modify the array referenced by arr in-place.
Python passes the array by reference:
$:python
...python startup message
>>> import numpy as np
>>> x = np.zeros((2,2))
>>> x
array([[0.,0.],[0.,0.]])
>>> def setx(x):
... x[0,0] = 1
...
>>> setx(x)
>>> x
array([[1.,0.],[0.,0.]])
The top answer is referring to a phenomenon that occurs even in compiled c-code, as any BLAS events will involve a "read-onto" step where either a new array is formed which the user (code writer in this case) is aware of, or a new array is formed "under the hood" in a temporary variable which the user is unaware of (you might see this as a .eval() call).
However, I can clearly access the memory of the array as if it is in a more global scope than the function called (i.e., setx(...)); which is exactly what "passing by reference" is, in terms of writing code.
And let's do a few more tests to check the validity of the accepted answer:
(continuing the session above)
>>> def minus2(x):
... x[:,:] -= 2
...
>>> minus2(x)
>>> x
array([[-1.,-2.],[-2.,-2.]])
Seems to be passed by reference. Let us do a calculation which will definitely compute an intermediate array under the hood, and see if x is modified as if it is passed by reference:
>>> def pow2(x):
... x = x * x
...
>>> pow2(x)
>>> x
array([[-1.,-2.],[-2.,-2.]])
Huh, I thought x was passed by reference, but maybe it is not? -- No, here, we have shadowed the x with a brand new declaration (which is hidden via interpretation in python), and python will not propagate this "shadowing" back to global scope (which would violate the python-use case: namely, to be a beginner level coding language which can still be used effectively by an expert).
However, I can very easily perform this operation in a "pass-by-reference" manner by forcing the memory (which is not copied when I submit x to the function) to be modified instead:
>>> def refpow2(x):
... x *= x
...
>>> refpow2(x)
>>> x
array([[1., 4.],[4., 4.]])
And so you see that python can be finessed a bit to do what you are trying to do.
You can't create a reference to a single element, but you can get a view over that single element:
>>> x = numpy.arange(10)
>>> y = x[3:4]
>>> y[0] = 100
>>> x
array([0, 1, 2, 100, 4, 5, 6, 7, 8, 9])
The reason you can't do the former is that everything in python is a reference. By doing y = 100, you're modifying what y points to - not it's value.
If you really want to, you can get that behaviour on instance attributes by using properties. Note this is only possible because the python data model specifies additional operations while accessing class attributes - it's not possible to get this behaviour for variables.
No you cannot do that, and that is by design.
Numpy arrays are of type numpy.ndarray. Individual items in it can be accessed with numpy.ndarray.item which does "copy an element of an array to a standard Python scalar and return it".
I'm guessing numpy returns a copy instead of direct reference to the element to prevent mutability of numpy items outside of numpy's own implementation.
Just as a thoughtgame, let's assume this wouldn't be the case and you would be allowed to get reference to individual items. Then what would happen if: numpy was in the midle of calculation and you altered an individual intime in another thread?