This question already has answers here:
Creating a list in Python with multiple copies of a given object in a single line
(6 answers)
Closed 9 years ago.
To make my program more beautiful instead of ugly, I am trying to find a more pythonic way of adding a single value multiple times to a list. I now use a loop, but I create a variable I do not use.
l = []; n = 5; v = 0.5
for i in xrange(n):
l.append(v)
Any ideas?
To add v, n times, to l:
l += n * [v]
Try using list.extend and the multiply operator for lists
l.extend([v] * n)
The most general answer to this is to use list.extend() and a generator expression:
l.extend(generate_value() for _ in range(n))
This will add a value n times. Note that this will evaluate generate_value() each time, side-stepping issues with mutable values that other answers may have:
>>> [[1]] * 5
[[1], [1], [1], [1], [1]]
>>> _[0].append(1)
>>> _
[[1, 1], [1, 1], [1, 1], [1, 1], [1, 1]]
>>> [[1] for _ in range(5)]
[[1], [1], [1], [1], [1]]
>>> _[0].append(1)
>>> _
[[1, 1], [1], [1], [1], [1]]
When using the multiplication method, you end up with a list of n references to the same list. When you change it, you see the change in every element of the list - as they are all the same.
When using a generator expression or list comprehension, a new list is created for each sub-item, so each item is a different value. Modifying one only affects that one.
Obviously, in your example, the values are immutable, so this doesn't matter - but it's worth remembering for different cases, or if the values might not be immutable.
Try this
n = 5
v = 0.5
l = [v]*n
Related
I think similar questions exist but I can't seem to find them out
x=list(([],)*3)
x[0].append(1)
x[1].append(2)
x[2].append(3)
print(x)
I want the result to look like this:
[[1],[2],[3]]
But instead, I get:
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
Also I really don't want to use any loops but if it is necessary then I'll try
Just realized you don't want to use a for loop.
Option 1: no for loops:
x = []
x.append([1])
x.append([2])
x.append([3])
print(x)
> [[1], [2], [3]]
Option 2: using loops.
Easiest and cleanest way is to use list comprehension like this:
x = [[i] for i in range(1,4)]
print(x)
> [[1], [2], [3]]
Or you can use a plain for loop and create an empty list before:
result = []
for i in range(1,4):
result.append([i])
result
Instead of the first line, use
x = [[] for _ in range(3)]
In the current code, x is a list of the empty lists which are actually the same object. That's how [...] * n works; it repeats the same objects n times. So appending an item to one of these empty lists would append the item to the others, because they are the same.
You can create an empty list first and starts appending each element as a list.
x=[]
x.append([1])
x.append([2])
x.append([3])
print(x)
i am a super beginner in python (took an introductory to python course 4 years ago!) and I am trying to append the numbers 0-3 each in a list inside a list, so:
[[0], [1], [2], [3]]
i have written the code below which should work but it doesn't and i can't figure out why:
l = 4
data = [[None]] * l
for k in range(l):
data[k].append(k)
print(data)
which produces this in the shell (don't worry about the None element in there I know how to get rid of those):
[[None, 0, 1, 2, 3], [None, 0, 1, 2, 3], [None, 0, 1, 2, 3], [None, 0, 1, 2, 3]]
i have been working on this for over an hour but i can't figure out what is wrong and how to fix it. any halp would be highly appriciated
Your data list consists of four references to the same inner list, which is initialized to [None]. As you append to this inner list in your loop, all four references to it are affected.
If you create a new list for each element, you won't have this issue:
l = 4
data = []
for k in range(l):
data.append([k])
print(data)
In the above code, the expression [k] creates a new list that contains only the int value k.
Simpler yet:
l = 4
data = [[k] for k in range(l)]
print(data)
l = 4
data = []
for k in range(l):
data.append([k])
print(data)
None will also stay in the list. You are not removing it. Also, it creates a reference to the same list. so, appending to it will modify all the inner lists.
Instead of appending to an inner list, you can append a list to the list with only one element in it.
Or you can use a list comprehension:
print([[k] for k in range(4)])
I create a list of lists and want to append items to the individual lists, but when I try to append to one of the lists (a[0].append(2)), the item gets added to all lists.
a = []
b = [1]
a.append(b)
a.append(b)
a[0].append(2)
a[1].append(3)
print(a)
Gives: [[1, 2, 3], [1, 2, 3]]
Whereas I would expect: [[1, 2], [1, 3]]
Changing the way I construct the initial list of lists, making b a float instead of a list and putting the brackets inside .append(), gives me the desired output:
a = []
b = 1
a.append([b])
a.append([b])
a[0].append(2)
a[1].append(3)
print(a)
Gives: [[1, 2], [1, 3]]
But why? It is not intuitive that the result should be different. I know this has to do with there being multiple references to the same list, but I don't see where that is happening.
It is because the list contains references to objects. Your list doesn't contain [[1 2 3] [1 2 3]], it is [<reference to b> <reference to b>].
When you change the object (by appending something to b), you are changing the object itself, not the list that contains the object.
To get the effect you desire, your list a must contain copies of b rather than references to b. To copy a list you can use the range [:]. For example:
>>> a = []
>>> b = [1]
>>> a.append(b[:])
>>> a.append(b[:])
>>> a[0].append(2)
>>> a[1].append(3)
>>> print a
[[1, 2], [1, 3]]
The key is this part:
a.append(b)
a.append(b)
You are appending the same list twice, so both a[0] and a[1] are references to the same list.
In your second example, you are creating new lists each time you call append like a.append([b]), so they are separate objects that are initialized with the same float value.
In order to make a shallow copy of a list, the idiom is
a.append(b[:])
which when doubled will cause a to have two novel copies of the list b which will not give you the aliasing bug you report.
This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 6 years ago.
Can anyone explain why is this happening?
Case 1:
>>> a = [[0]] *3
>>> print a
[[0], [0], [0]]
>>> a[1].append(0)
>>> print a
[[0, 0], [0, 0], [0, 0]]
Case 2:
>>> a = [[0],[0],[0]]
>>> print a
[[0], [0], [0]]
>>> a[1].append(0)
>>> print a
[[0], [0, 0], [0]]
Why is this going on? I am expecting that the behavior of the array in case 1 to be as in case 2 but it is not for some reason.
In the first case, the three elements in a actually reference to the same list objects. You can check their id:
>>> id(a[0])
4524132472
>>> id(a[1])
4524132472
>>> id(a[2])
4524132472
In the first case, you are creating a list [0] and duplicate it 3 times. This is the same object repeated three times. You should use the star form only with immutable type
To avoid this issue when you have a mutable type, use list comprehension:
a = [[0] for _ in range(3)]
I create a list of lists and want to append items to the individual lists, but when I try to append to one of the lists (a[0].append(2)), the item gets added to all lists.
a = []
b = [1]
a.append(b)
a.append(b)
a[0].append(2)
a[1].append(3)
print(a)
Gives: [[1, 2, 3], [1, 2, 3]]
Whereas I would expect: [[1, 2], [1, 3]]
Changing the way I construct the initial list of lists, making b a float instead of a list and putting the brackets inside .append(), gives me the desired output:
a = []
b = 1
a.append([b])
a.append([b])
a[0].append(2)
a[1].append(3)
print(a)
Gives: [[1, 2], [1, 3]]
But why? It is not intuitive that the result should be different. I know this has to do with there being multiple references to the same list, but I don't see where that is happening.
It is because the list contains references to objects. Your list doesn't contain [[1 2 3] [1 2 3]], it is [<reference to b> <reference to b>].
When you change the object (by appending something to b), you are changing the object itself, not the list that contains the object.
To get the effect you desire, your list a must contain copies of b rather than references to b. To copy a list you can use the range [:]. For example:
>>> a = []
>>> b = [1]
>>> a.append(b[:])
>>> a.append(b[:])
>>> a[0].append(2)
>>> a[1].append(3)
>>> print a
[[1, 2], [1, 3]]
The key is this part:
a.append(b)
a.append(b)
You are appending the same list twice, so both a[0] and a[1] are references to the same list.
In your second example, you are creating new lists each time you call append like a.append([b]), so they are separate objects that are initialized with the same float value.
In order to make a shallow copy of a list, the idiom is
a.append(b[:])
which when doubled will cause a to have two novel copies of the list b which will not give you the aliasing bug you report.