Value changing at multiple positions in a list of list when trying to change at one place

后端 未结 2 374
遇见更好的自我
遇见更好的自我 2021-01-20 20:54

The following Code in python:

matrix = [[0]*3]*2
matrix[0][1] = 1

seeems to be changing the value at all the matrix[][1]th pos

相关标签:
2条回答
  • 2021-01-20 21:50

    There are some subtleties on how the multiplication operator * works on lists in python.

    More generally, there are differences on its effects when applied on immutable objects such integers or strings, and how those it has when applied on mutable objects like lists and dictionaries.

    This might clarify the issue:

    >>> l = [0] * 3  #a list of immutable integers
    >>> l
    [0, 0, 0]
    >>> l[0] = 1
    >>> l
    [1, 0, 0]
    >>> l = [[0]] * 3  #a list of mutable lists
    >>> l
    [[0], [0], [0]]
    >>> l[0][0] = 1
    >>> l
    [[1], [1], [1]]
    

    EDIT (kudos to @lazyr in the comments) Under the hood, in both cases the * operator creates a list of objects with the same identity (memory address), so each number (and each list) in the array are really the same object, however, immutable types can not be modified but only replaced, so when you try to assign a new value to the integer array, you will factually replace the entire object, while this is not the case with lists. Bulding on the previous example (keep in mind that the id function returns the object's memory address):

    >>> m = [1] * 3
    >>> id(m[0])
    39356344
    >>> id(m[1])
    39356344
    >>> m[1] = 2
    >>> id(m[1])
    39356320  # new memory addres = different object!
    >>> m = [[1]] * 3
    >>> id(m[0])
    40275408
    >>> id(m[1])
    40275408
    >>> m[1][0] = 2
    >>> id(m[1])
    40275408  # same memory address = still the same object!
    

    So, in your case a possible workaround would be to initialise the matrix like this:

    >>> matrix = [[0 for i in range(3)] for j in range(2)]
    >>> matrix
    [[0, 0, 0], [0, 0, 0]]
    >>> matrix[0][2] = 1
    >>> matrix
    [[0, 1, 0], [0, 0, 0]]
    

    An alternative - more radical - way would be to altogether switch to numpy, which is faster and thought from the ground up for extremely fast matrix and multidimensional vectors manipulation, but it is also harder to use.

    HTH!

    0 讨论(0)
  • 2021-01-20 21:54

    Try:

    matrix = [[0]*3 for j in xrange(2)]
    
    0 讨论(0)
提交回复
热议问题