This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Inconsistence in multiply list
Type: behavior Stage:
Components: Interpreter Core Versions: Python 2.5
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: beco, georg.brandl
Priority: normal Keywords:

Created on 2007-11-08 20:59 by beco, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Messages (2)
msg57279 - (view) Author: (beco) Date: 2007-11-08 21:14
There is no way to create a big nested list without references using the
multiplication operator.

'*' is supposed to work like + ... + in this cases:

>>> a=[0, 0]
>>> b=[a[:]]+[a[:]]
>>> b
[[0, 0], [0, 0]]
>>> b[0][0]=1
>>> b
[[1, 0], [0, 0]]

Ok! Copy here, not reference. Mainly because we use [:] explicitly
expressing we want a copy.

>>> c=[a[:]]*2
>>> c
[[0, 0], [0, 0]]
>>> c[0][0]=2
>>> c
[[2, 0], [2, 0]]

Inconsistence here. It is supposed to be clear and copy, not reference
in between.

Consequence: there is no clear way to create a nested list of, lets say,
60x60, using multiplications.

Even when using this, we cannot deal with the problem:

>>> import copy
>>> d=[copy.deepcopy(a[:])]*2
>>> d
[[0, 0], [0, 0]]
>>> d[0][0]=3
>>> d
[[3, 0], [3, 0]]

Workaround:
>>> from numpy import *
>>> a=zeros((2,2),int)
>>> a
array([[0, 0],
       [0, 0]])
>>> b=a.tolist()
>>> b
[[0, 0], [0, 0]]
>>> b[0][0]=4
>>> b 
[[4, 0], [0, 0]]

And that is the expected behaviour.

Thanks.
msg57300 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2007-11-09 13:19
I'm sorry, this is no bug. List multiplication works by referencing,
there is no way to implement it differently in a straightforward way.

Note that in
>>> [a[:]] + [a[:]]
the expression "a[:]" is evaluated twice, yielding two independent
copies of a. In contrast,
>>> [a[:]] * 2
evaluates "a[:]" only once, before the list multiplication is done.
Because of the same reason,
>>> [deepcopy(a)] * 2
doesn't work as you want.

One way to do what you have in mind is
>>> [a[:] for i in range(2)]
which evaluates the "a[:]" once for each iteration of the list
comprehension loop.
History
Date User Action Args
2022-04-11 14:56:28adminsetgithub: 45749
2007-11-09 13:19:47georg.brandlsetstatus: open -> closed
resolution: not a bug
messages: + msg57300
nosy: + georg.brandl
2007-11-08 21:14:08becosetmessages: + msg57279
2007-11-08 20:59:21becocreate