Indexing of lists within a list in python [duplicate] - python

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Python list multiplication: [[...]]*3 makes 3 lists which mirror each other when modified [duplicate]
(4 answers)
Closed 6 years ago.
I have a list of lists in python.
z=[[0]*6]*7
Since all elements are 0. But now if i want to change an individual element within a list e.g
z[0][0]=2
This should change the first element of the first list. But it actually changes the first element of all elements. This is so illogical to me.
Can some one help.
[2, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 0],
[2, 0, 0, 0, 0, 0]]

That's a classical "programmer's trap" in python.
l = [ 0 ] * 6
creates a list containing six times a reference to the same python object, here, the numerical constant 0.
Now, setting
l[0] = 1
will replace the first reference to the const 0 object by a reference to another object, the const 1 object.
Now, let's look at
z=[[0]*6]*7
This first creates a list containing six references to the const 0 object, and then it creates a list containing seven references to that single six-element list.
Now,
z[0]
will give you the first element from z, which is simply the same as all the six other elements.
Proof:
print id(z[0]) == id(z[1])
different objects have different IDs.
So you never actually made a list of different lists, but just the same list all over.
You can actually create different sublists and put them into one by doing something like
z = [ [0]*6 for _ in range(7) ]
However, I get the feeling you actually might want to use matrices – if that's really the case, numpy's ndarray is what you're after, because:
import numpy
z = numpy.ndarray((7,6))
actually gives you a matrix with 42 numeric elements.

Related

Indexed array filled incorrectly [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 3 years ago.
I just started programming with Python and I have a question concerning 2D arrays.
I need to create a matrix (numpy forbidden) of a certain size from av[1] and save it so that I can multiply it with another one later on.
The logical thing for me was:
1- Get the length of av[1]; 2- Transform the av[1][] to it's ASCII equivalent with ord and finally 3- Insert that value into a list called key_matrix.
The matrix needs to be the smallest size possible and in a "square form", so I calculate the smallest square containing the len of av[1] ( called matrix_size ) and then I initialize my array like this:
key_matrix = [[0] * matrix_size] * matrix_size;
Like that I get my square matrix filled with 0.
If matrix_size = 3 for example I get:
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Now the strange part is (and also the part that I'm stuck on) the following, I use
index1 = 0;
index2 = 0;
key_matrix[index1][index2] = ord(sys.argv[1][0]);
print(key_matrix);
to fill only the 1st element of the 1st line.
While the result should be:
[[97, 0, 0], [0, 0, 0], [0, 0, 0]]
I get:
[[97, 0, 0], [97, 0, 0], [97, 0, 0]]
Me and my friends really cant seem to figure out the reason why it does this, any help is welcome!
Thank you all for reading :)
The memory address of the lists are the same when you write [[0] * matrix_size] * matrix_size, it basically reuses the memory address of the first [0] * matrix_size array as the same reference for multiple times for other lists. Since these lists are not independent from memory address perspective, we would have issue modifing only one of the list. You can do below as a quick fix for the issue:
>>> key_matrix2 = [[0] *3 for i in range(matrix_size)]
>>> key_matrix2
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> key_matrix2[0][1] = 2
>>> key_matrix2
[[0, 2, 0], [0, 0, 0], [0, 0, 0]]

How does this Python's list value assignment works in this case? [duplicate]

This question already has answers here:
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
Closed 3 years ago.
I have come across a strange behaviour in Python's value assignment. If I create a list such as List =[[0, 0], [0, 0]] and want to change a value indexed 1 in the list indexed as 1 I simply use: List[1][1] = 1. However, this is not a case of the code below. Eventhough the list seems same as the one mentioned above, it assigns more values then I expect. Is there anyone who can explain how this work?
size = 2
matrix = [[]]
for j in range(size):
matrix[0].append(0)
for i in range(size-1):
matrix.append(matrix[0])
matrix[1][1] = 1
print(str(matrix))
I would expect the output as [[0, 0], [0, 1]], but the actual output is [[0, 1], [0, 1]]. Why is the value at position matrix[0][1] assigned as 1??
When you do:
matrix.append(matrix[0])
You're appending to matrix the reference to the object matrix[0] (which is a list), it isn't creating a new list.

Dot product of multiple numpy arrays [duplicate]

This question already has answers here:
How do I create variable variables?
(17 answers)
Closed 4 years ago.
I have the code below in Python3:
matrix = np.array([[1,2,3],
[2,3,4],
[5,3,4]])
sig_d1 = np.array([[1, 0, 0],
[0, 0, -1],
[0, -1, 0]])
sig_d2 = np.array([[1, 0, 0],
[0, 0, 1],
[0, 1, 0]])
for i in range(1,3):
product=np.dot(sig_d+i,matrix)
However, I'm getting the error:
product = np.dot(sig_d+i,matrix.transpose())
NameError: name 'sig_d' is not defined
Could someone give some support?
Python does not allow you to dynamically access variables the way you're trying to do so. The best way to do this would be to put your arrays inside a dictionary and access values by key string.
array_dict = {'sig_d1' : sig_d1, 'sig_d2' : sig_d2}
for i in range(1,3):
product = np.dot(array_dict['sig_d{}'.format(i)], matrix)
If you have more arrays, I'd recommend a smarter way of initialising your array_dict, possibly through a loop or dict comprehension.

python how to change value of elements of sublists? [duplicate]

This question already has answers here:
Creating lists of lists in a pythonic way
(8 answers)
Closed 9 years ago.
I have the following code:
matrix = [[0] * 3] * 3
matrix[0][0] = 2
I want to get the following result:
[[2, 0, 0], [0, 0, 0], [0, 0, 0]]
However it changes the first element of each sublist and returns this list:
[[2, 0, 0], [2, 0, 0], [2, 0, 0]]
If I define matrix as follow:
matrix = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
then it works.
Could anyone tell me please, why it happens and how could solve this problem?
Thanks
This is happening because [[0] * 3] * 3 is actually creating an array of 3 of the same object (the [0] * 3 array). One way of looking at it is that the inner array is created once and copied. An alternative would be to use [[0] * 3 for x in xrange(3)], as this executes [0] * 3 each iteration in list comprehension, creating a new array each time.
Here's your problem, matrix, in this example, is basically identical to:
>>> a = [0,0,0]
>>> matrix1 = [a,a,a]
that means when you do matrix1[0][0] = 2, what Python does is follow its pointer located at the first index of matrix1, which points to object a, then looks at the pointer located at the first index of a, which reads 0, then changes that to 2. Then when you ask it to evaluate matrix1, it looks up a three times and finds [2,0,0] each time.
Sean had a good solution above mine, using list comprehensions to force new objects instead of adding pointers for objects that already exist. That may serve you better :)
Python assigns by pointer rather than value* which sometimes leads to undesirable results such as this one. Here is a tutorial that explains what is really happening: http://www.python-course.eu/variables.php Here is one possible fix http://www.python-course.eu/deep_copy.php
*(as has been pointed out this is not quite right, however it similar in result to what happens in other languages like C which I'm more familiar with if you passed a pointer to a variable rather than a copy of the value of the variable.)

Python multiple dimension arrays [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to initialize a two-dimensional array in Python?
In solving a simple problem regarding a two dimensional array I came across a solution on this site that explained how to declare one in Python using the overload operator.
Example:
Myarray = [[0]*3]*3
this would produce the following array (list)
[[0,0,0],[0,0,0],[0,0,0]]
This seems fine until you use it:
if you assign an element for example:
Myarray [0][0] = 1
you get the unexpected output:
[[1,0, 0],[1,0,0] , [1,0,0]]
In effect assigning Myarray [1][0] and Myarray[2][0] at the same time
My solution:
Myarray = [[][][]]
for i in range(0,3):
for j in range (0,3):
Myarray[i].append(0)
This solution works as intended:
Marray[0][1] = 1
gives you
[[1,0, 0],[0,0,0] , [0,0,0]]
Is there a simpler way to do this? This was a solution to an A level Cambridge question and seems too long winded for students compared to other languages.
With vanilla Python, you could use this, a nested list comprehension
>>> m = [[0 for y in range(3)] for x in range(3)]
>>> m
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
Unlike the multiplied list you showed in your example, it has the desired behavior
>>> m[1][0] = 99
>>> m
[[0, 0, 0], [99, 0, 0], [0, 0, 0]]
However, for serious use of multidimensional arrays and/or numerical programming, I'd suggest you use Numpy arrays.

Categories

Resources