Jerry
Jerry

Reputation: 434

Python3 list filled with empty dict

I found the way to make a list filled with the same literal.

So I did following:

my_list_of_dict = [{}] * 3

my_list_of_dict[0][0] = 1
my_list_of_dict[0][1] = 2

print(my_list_of_dict)
# What I thought : [{0: 1, 1: 2}, {}, {}]
# What actually happened : [{0: 1, 1: 2}, {0: 1, 1: 2}, {0: 1, 1: 2}]

Is this a bug? or an intended feature?

It seems like python doesn't initialize new dict every time but just assigning given dict to the list.

Plus, How do I call(pronouce) [] * n? is this a kind of list comprehension?

Upvotes: 2

Views: 58

Answers (1)

Netwave
Netwave

Reputation: 42746

{} returns a reference to the dict, and then by *3 you are making 3 references to the same dict. To fix this, use a different approach:

[{} for _ in range(3)]

With zeros (0) it doesnt matter because they are inmutable so once you modify the value inside the list you are "creating" a new number and then reference it through the list:

>>> l = [0]*3
>>> [id(x) for x in l]
[10910368, 10910368, 10910368]
>>> l[0] = 10
>>> [id(x) for x in l]
[10910688, 10910368, 10910368]

But with mutable objects you are modifiying the object referenced directly, so all the positions in the list are aware of that change, since they point to the same object:

>>> l = [[]]*3
>>> l
[[], [], []]
>>> l[0].append(10)
>>> l
[[10], [10], [10]]
>>> [id(x) for x in l]
[139858640463368, 139858640463368, 139858640463368]

By using the other comprehension, you are creating a new instance in each loop of the comprehension:

>>> l = [{} for _ in range(3)]
>>> l[0]["foo"] = 10
>>> l
[{'foo': 10}, {}, {}]

Upvotes: 5

Related Questions