This question already has answers here:
Confusing [...] List in Python: What is it?
(9 answers)
Closed 9 years ago.
I just seen a output like below - just want to know what is happening here.
>>> l = [1,2,3,4]
>>> l[0]=l
>>> l
[[...], 2, 3, 4]
Why the l[0] value has displayed like this? Can anyone explain me why this behavior.
I was thinking it'd return like, [[1,2,3,4], 2, 3, 4].
Cheers,
Kalai
It shows the ... because otherwise it would have to infinitely recurse.
A list object in Python is a pointer to a list- assigning it like l[0] = l doesn't make a copy. For instance, try
l1 = [1, 2, 3, 4]
l2 = [1, 2]
l2[0] = l1
print l2
# [[1, 2, 3, 4], 2]
l2[0].append(5)
print l1
# [1, 2, 3, 4, 5]
Notice that even though you never changed l1 explicitly, it has now been appended to.
Therefore, when you place a list within itself, that item of the list is still a link to the entire list. After your code above, try doing:
l[1] # ==> 2
l[0][1] # ==> 2
l[0][0][1] # ==> 2
Use a copy of the list to avoid infinite recursion:
In [10]: l = [1,2,3,4]
In [11]: l[0] = l[:]
In [12]: l
Out[12]: [[1, 2, 3, 4], 2, 3, 4]
If you would have used a PrettyPrinter, the output would had been self explanatory
>>> l = [1,2,3,4]
>>> l[0]=l
>>> l
[[...], 2, 3, 4]
>>> pp = pprint.PrettyPrinter(indent = 4)
>>> pp.pprint(l)
[<Recursion on list with id=70327632>, 2, 3, 4]
>>> id(l)
70327632
Related
This question already has answers here:
How to deep copy a list?
(10 answers)
How do I clone a list so that it doesn't change unexpectedly after assignment?
(24 answers)
What is the best way to copy a list? [duplicate]
(7 answers)
Closed 1 year ago.
Let's assume that a is some reference variable and I want to put it into a list three times:
a = [1,2,3]
b = [a]*3
>>> b
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
So this still works as expected. But if I append an element to one of the reference variables it is reflected to all of them:
>>> b[0].append(4)
>>> b
[[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]]
Does this happen because the * operator in the first code block only copies the references and the list only points to a? Do I need a for-loop in order to be able to have a list of independent reference variables (copies) n times? (where n is 3 in the example above)
How excactly does the * operator work in this instance?
With a for-loop and the append()-Method the behaviour is the same - are references also used here?:
>>> a = [1,2,3]
>>> b = []
>>> for i in range(2):
... b.append(a)
...
>>> b
[[1, 2, 3], [1, 2, 3]]
>>> b[0].append(4)
>>> b
[[1, 2, 3, 4], [1, 2, 3, 4]]
When inserting copies the behaviour is as expected:
>>> a = [1,2,3]
>>> b = []
>>> for i in range(2):
... b.append(a.copy())
...
>>> b
[[1, 2, 3], [1, 2, 3]]
>>> b[0].append(4)
>>> b
[[1, 2, 3, 4], [1, 2, 3]]
Is there a shorter, more convenient way to do this than to loop with .append() and .copy() as I did above?
My Python-Version is Python 3.8.6
Note that my questions go beyond just using deep_copy() as it is about inserting elements more often in a list and the *-operator - I know what deep_copy() is!
Following can be used to add a slice to append to front of list.
>>> a = [5,6]
>>> a[0:0] = [1,2,3]
>>> a
[1,2,3,5,6]
what slice to use to append to the end of list.
If you really want to use slice, you can use the length of a:
a = [5, 6]
a[len(a):] = [1, 2, 3]
a
output:
[5, 6, 1, 2, 3]
But the simplest is to directly extend a:
a = [5, 6]
a += [1, 2, 3] # or a.extend([1, 2, 3])
I think you should consider extend():
>>> a = [1, 2, 3]
>>> a.extend([4, 5, 6])
>>> a
[1, 2, 3, 4, 5, 6]
Both + and += operators are defined for list, which are semantically
similar to extend.
list + list2 creates a third list in memory, so you can return the
result of it, but it requires that the second iterable be a list.
list += list2 modifies the list in-place (it is the in-place operator,
and lists are mutable objects, as we've seen) so it does not create a
new list. It also works like extend, in that the second iterable can
be any kind of iterable.
Time Complexity
Append has constant time complexity, O(1).
Extend has time complexity, O(k).
Iterating through the multiple calls to append adds to the complexity,
making it equivalent to that of extend, and since extend's iteration
is implemented in C, it will always be faster if you intend to append
successive items from an iterable onto a list.
↳ More Information
>>> a = [1, 2, 3]
>>> a[len(a):] = [4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6]
or
>>> a = [1, 2, 3]
>>> a += [4, 5, 6]
>>> a
[1, 2, 3, 4, 5, 6]
You have got short answer from Jeevaa and Reblochon Masque but if you want to use for loop then try this:
a = [5,6]
b = [1,2,3]
for val in b[::-1]:#Reverse b and insert it to a
a.insert(0,val)
print(a)
Output
[1,2,3,5,6]
Example one: Changing the value that has been appended to b changes the value in the original list l
>>> l = [1 , 2, 3]
>>> b = []
>>> b.append(l)
>>> b[0].append(4)
>>> b
[[1, 2, 3, 4]]
>>> l
[1, 2, 3, 4]
Example 2: l1 is appended to ans and then the value of l1 is modified. However, the value in ans remains the same.
>>> l1 = [1, 2, 3]
>>> ans = []
>>> ans.append(l1)
>>> ans
[[1, 2, 3]]
>>> l1 = [2, 3, 4]
>>> ans
[[1, 2, 3]]
I seem to be missing some fundamental point about the mutability of lists. Could someone please point it out?
You are not mutating l1. You are assigning a new object to the same name, which makes that name point to a new object. You are moving a label, not modifying an object. The only remaining reference to the list that l1 used to point to is now ans[0].
In your first example, l is a pointer, as well as b.
l is then appended to b, so b[0] now refers to the pointer.
Next, you append 4 to b[0], which is the same thing as l, so 4 is added to both b[0] and l.
In your second example, ans contains the pointer of l1, just like b contained the pointer of l
Then, you changed l1 itself by assigning it to a different array, so l1 changed but ans[0] did not.
The biggest takeaway from this is that append just changes the list, and the pointer remains the same. But when you set a variable to a different list, the pointer changes.
Replace
>>> l1 = [2, 3, 4]
with
>>> l1[:] = [2, 3, 4]
That will not assign a new list to l1.
This question already has answers here:
What do ellipsis [...] mean in a list?
(5 answers)
Circular Reference with python lists
(3 answers)
Closed 9 years ago.
I've created a list in python,
list1 = [1,2,3,4]
and tried to append it tp itself,
list1.append(list1)
this is what i've got, it's kind of never ending!
could someone please explain me what is happening?
>>> list1=[1,2,3,4]
>>> list1.append(list1)
>>> list1
[1, 2, 3, 4, [...]]
>>> len(list1)
5
>>> len(list1[4])
5
>>> print list1[4]
[1, 2, 3, 4, [...]]
>>> print list1[4][4]
[1, 2, 3, 4, [...]]
>>> print list1[4][4][4]
[1, 2, 3, 4, [...]]
>>> print list1[4][4][4][4]
[1, 2, 3, 4, [...]]
>>> print list1[4][4][4][4][4]
[1, 2, 3, 4, [...]]
>>> print list1[4][4][4][4][4][4]
[1, 2, 3, 4, [...]]
>>> print list1[4][4][4][4][4][4][4]
[1, 2, 3, 4, [...]]
>>> print list1[4][4][4][4][4][4][4][4]
[1, 2, 3, 4, [...]]
>>> print list1[4][4][4][4][4][4][4][4][4]
[1, 2, 3, 4, [...]]
that's never ending.
Thank You
Names in Python are pointers to objects. In this case
>>> lst = [1, 2, 3, 4]
you create a new list object with 4 int values in, and assign that to the name lst. Next
>>> lst.append(lst)
you add a new item to the end of your list; a pointer to the list itself. This creates the circular reference, that Python prints as [...]. This is because the last item in lst points to lst, in which the last item points to lst, in which...
If you want to append the content of the list to your list, you need to copy the object, which you can do with a slice:
>>> lst.append(lst[:])
>>> lst
[1, 2, 3, 4, [1, 2, 3, 4]]
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Python append() vs. + operator on lists, why do these give different results?
What is the actual difference between "+" and "append" for list manipulation in Python?
There are two major differences. The first is that + is closer in meaning to extend than to append:
>>> a = [1, 2, 3]
>>> a + 4
Traceback (most recent call last):
File "<pyshell#13>", line 1, in <module>
a + 4
TypeError: can only concatenate list (not "int") to list
>>> a + [4]
[1, 2, 3, 4]
>>> a.append([4])
>>> a
[1, 2, 3, [4]]
>>> a.extend([4])
>>> a
[1, 2, 3, [4], 4]
The other, more prominent, difference is that the methods work in-place: extend is actually like += - in fact, it has exactly the same behavior as += except that it can accept any iterable, while += can only take another list.
Using list.append modifies the list in place - its result is None. Using + creates a new list.
>>> L1 = [1,2,3]
>>> L2 = [97,98,99]
>>>
>>> # Mutate L1 by appending more values:
>>> L1.append(4)
>>> L1
[1, 2, 3, 4]
>>>
>>> # Create a new list by adding L1 and L2 together
>>> L1 + L2
[1, 2, 3, 4, 97, 98, 99]
>>> # L1 and L2 are unchanged
>>> L1
[1, 2, 3, 4]
>>> L2
[97, 98, 99]
>>>
>>> # Mutate L2 by adding new values to it:
>>> L2 += [999]
>>> L2
[97, 98, 99, 999]
+ is a binary operator that produces a new list resulting from a concatenation of two operand lists. append is an instance method that appends a single element to an existing list.
P.S. Did you mean extend?
The + operation adds the array elements to the original array. The array.append operation inserts the array (or any object) into the end of the original array.
[1, 2, 3] + [4, 5, 6] // [1, 2, 3, 4, 5, 6]
b = [1, 2, 3]
b.append([4, 5, 6]) // [1, 2, 3, [4, 5, 6]]
Take a look here: Python append() vs. + operator on lists, why do these give different results?