3

I think here is a very strange python code, but i don't know the reason:

In [7]: a = [[]] * 3

In [8]: b = [[], [], []]

In [9]: a == b
Out[9]: True

In [10]: a[0].append(1)

In [11]: b[0].append(1)

In [12]: a == b
Out[12]: False

In [13]: a
Out[13]: [[1], [1], [1]]

In [14]: b
Out[14]: [[1], [], []]

Why a is [[1], [1], [1]] after a[0].append(1)?

A similar problem is:

In [15]: c = dict.fromkeys(range(3),[])

In [16]: d = {0:[], 1:[], 2:[]}

In [17]: c == d
Out[17]: True

In [18]: c[0].append(1)

In [19]: d[0].append(1)

In [20]: c == d
Out[20]: False

In [21]: c
Out[21]: {0: [1], 1: [1], 2: [1]}

In [22]: d
Out[22]: {0: [1], 1: [], 2: []}

In my understand, a is b, and c is also equal to d, but it isn't. WHY? can anyone help me? Thanks very much!

Steve Barnes
  • 27,618
  • 6
  • 63
  • 73
prime_tang
  • 128
  • 7

4 Answers4

4

The first version:

>>> a = [[]] * 3

creates a list that contains three times the same list. Look the ids of the elements:

>>> [id(x) for x in a]
[4454962120, 4454962120, 4454962120]

While this:

>>> b = [[], [], []]

creates three different lists:

>>> [id(x) for x in b]
>>> [4454963720, 4455011592, 4454853448]

You can create a large list containing different sub-lists with a list comprehension:

>>> size = 100
>>> long_list = [[] for x in range(size)]

Now appending to the first sub-list:

>>> long_list[0].append(10)
>>> long_list[:10]

changes only the first sub-list:

>>> long_list[:10]
[[10], [], [], [], [], [], [], [], [], []]
Mike Müller
  • 82,630
  • 20
  • 166
  • 161
  • Thank you! If I want to create a long list just like `b`, for example, it will contain 100 `[]`s. Obviously, `b = [[], [], [], ...]` is not a good solution, how can I achieve it? – prime_tang Dec 09 '15 at 11:10
2

[[]]*3 creates a list of 3 references to the same list while [[],[],[]] creates a list of 3 references to 3 different lists.

Julien
  • 13,986
  • 5
  • 29
  • 53
2

For both a and c, you are creating a single empty list which is referenced 3 times. When you change it, all references to it change. For b and d, you create 3 separate empty lists which are completely independent.

You can check if two objects are the same by using the is operator, e.g. x is y. Here is what it shows in your first example:

>>> a = [[]] * 3
>>> b = [[], [], []]
>>>
>>> a[0] is a[1]
True
>>> b[0] is b[1]
False
>>>

And in your second example:

>>> c = dict.fromkeys(range(3), [])
>>> d = {0:[], 1:[], 2:[]}
>>>
>>> c[0] is c[1]
True
>>> d[0] is d[1]
False
>>>
Tom Karzes
  • 22,815
  • 2
  • 22
  • 41
0

In both cases a & c contain 3 references to a single empty list but b & d contain 3 empty lists. So when you compare them 3 lots of empty == 3 lots of empty.

When you append to the first element of both in a & c you append to the single list that you have 3 references to so all 3 become references to [1] but in b & d you append to the first of the 3 lists so only that one gets changed.

With the same definitions:

In [8]: a[0] is a[1]
Out[8]: True

In [9]: b[0] is b[1]
Out[9]: False
Steve Barnes
  • 27,618
  • 6
  • 63
  • 73