Python Forum
2 ways to initialize a list with all zero - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: 2 ways to initialize a list with all zero (/thread-34507.html)



2 ways to initialize a list with all zero - quazirfan - Aug-05-2021

Python beginner here :: Is there a difference between the following two ways to initialize a list of all zero?

x = [0] * 10 
# vs
x = [0 for _ in range(10)]



RE: 2 ways to initialize a list with all zero - bowlofred - Aug-05-2021

Because the thing you put in your list (the int 0) is immutable, then the objects you get back from these two are equivalent. Both of them create a new list, and both are populated with 10 instances of the same object.

If you tried this with a mutable object (like an empty list), then there could be a difference. The first one will always have multiple copies of the same object. The second one depends on how the object is created/named/instantiated.

To see this, I will have python tell me the id of the objects in the two lists. For the int, these are identical.
>>> x = [0] * 10 ; [id(z) for z in x]
[4444915984, 4444915984, 4444915984, 4444915984, 4444915984, 4444915984, 4444915984, 4444915984, 4444915984, 4444915984]
>>> x = [0 for _ in range(10)] ; [id(z) for z in x]
[4444915984, 4444915984, 4444915984, 4444915984, 4444915984, 4444915984, 4444915984, 4444915984, 4444915984, 4444915984]
But for a list (or dict, or set, ...), the second one creates independent objects each time through the loop.

>>> x = [[]] * 10 ; [id(z) for z in x]
[4446960960, 4446960960, 4446960960, 4446960960, 4446960960, 4446960960, 4446960960, 4446960960, 4446960960, 4446960960]
>>> x = [[] for _ in range(10)] ; [id(z) for z in x]
[4446970560, 4446928512, 4446273920, 4445232704, 4446929408, 4446970240, 4446961216, 4446970368, 4446970496, 4446970880]



RE: 2 ways to initialize a list with all zero - deanhystad - Aug-06-2021

Example A:
x = [0] * 10
# is the same as:
v = 0
x = []
for _ in range(10):
    x.append(v)
x[0] = 1
print(x)


x = [0 for _ in range(10)]
# is the same as
x = []
for _ in range(10):
    v = 0
    x.append(v)
x[0] = 1
print(x)
Output:
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0] [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
These will give you the same results for 0 or any immutable object. Any zero is the same as any other zero. Not just the same value, but the same int object. The same would be true for making a list of 'zero' strings.

Things change when you replace the immutable object with some kind of container. Instead of making a list of 0, lets make a list of lists that contain 0.

Example B
x = [[0]] * 10
# is the same as:
v = [0]
x = []
for _ in range(10):
    x.append(v)
x[0][0] = 1
print(x)


x = [[0] for _ in range(10)]
# is the same as
x = []
for _ in range(10):
    v = [0]
    x.append(v)
x[0][0] = 1
print(x)
Output:
[[1], [1], [1], [1], [1], [1], [1], [1], [1], [1]] [[1], [0], [0], [0], [0], [0], [0], [0], [0], [0]]
These do not give the same results. In both examples we create a list [0], but in the top example this list is only created once and the zero list is appended to x 10 times. Since all 10 lists are the same object, changing x[4] is the same as changing x[0] or x[9]. In the lower example each iteration of the for loop creates a new zero list. x[4] is a different object than x[0] which is a different object than x[9].

It is important to note that this is not a mutable vs immutable thing. In Example A we modify the value in the x list (x[0] = 1). In Example B we modify the value inside an object in the x list (x[0][0] = 1). Example C below is more comparable to Example A, and you can see that it acts the same way as Example A.

Example C
x = [[0]] * 10
# is the same as:
v = [0]
x = []
for _ in range(10):
    x.append(v)
x[0] = [1]
print(x)


x = [[0] for _ in range(10)]
# is the same as
x = []
for _ in range(10):
    v = [0]
    x.append(v)
x[0] = [1]
print(x)
Output:
[[1], [0], [0], [0], [0], [0], [0], [0], [0], [0]] [[1], [0], [0], [0], [0], [0], [0], [0], [0], [0]]
So choosing between x = [[v] * 10] and x = [[v] for _ in range(10)] comes down what v means, not if v is mutable or immutable. Sure the two methods can be used interchangeably if v is immutable, but v being mutable does not mean you have to use the comprehension. Having repeating mutable objects may make sense for the application.