What's the underlining machanism of append in python's list?
IE. a = [1,2,3]; a.append(3) then a is [1,2,3,3]
Dose python actually create a new list tmp [1,2,3,3], then assign that list to a?
No, it doesn't. List is mutable type in Python which means the append operation would change the original structure in memory.
>>> a = [1,2,3]
>>> id(a)
4325551112
>>> a.append(4)
>>> id(a)
4325551112
this is it.
No it modifies the original list , but does not return a new one, as lists are mutable.
to give you an example:
a = [1,2,3]
print a.append(4)
will return None, as append does not return a new list.
print a.pop(1)
will print 1 as pop removes and returns 1
Related
I tried the following in the python interpreter:
>>> a = []
>>> b = {1:'one'}
>>> a.append(b)
>>> a
[{1: 'one'}]
>>> b[1] = 'ONE'
>>> a
[{1: 'ONE'}]
Here, after appending the dictionary b to the list a, I'm changing the value corresponding to the key 1 in dictionary b. Somehow this change gets reflected in the list too. When I append a dictionary to a list, am I not just appending the value of dictionary? It looks as if I have appended a pointer to the dictionary to the list and hence the changes to the dictionary are getting reflected in the list too.
I do not want the change to get reflected in the list. How do I do it?
You are correct in that your list contains a reference to the original dictionary.
a.append(b.copy()) should do the trick.
Bear in mind that this makes a shallow copy. An alternative is to use copy.deepcopy(b), which makes a deep copy.
Also with dict
a = []
b = {1:'one'}
a.append(dict(b))
print a
b[1]='iuqsdgf'
print a
result
[{1: 'one'}]
[{1: 'one'}]
use copy and deep copy
http://docs.python.org/library/copy.html
This question already has answers here:
Why do these list operations (methods: clear / extend / reverse / append / sort / remove) return None, rather than the resulting list?
(6 answers)
Closed 6 years ago.
What is the actual difference between list1.append() and list1+list2 in python??
Along with this, why the following statement return NULL?
print(list1.append(list2))
{where list1 and list2 are 2 simple list}
list.append() modifies the object and returns None.
[] + [] creates and "returns" new list.
https://docs.python.org/2.7/tutorial/datastructures.html#more-on-lists
Recommended reading: http://docs.python-guide.org/en/latest/writing/gotchas/
Returning None is a way to communicate that an operation is side-effecting -- that is, that it's changing one of its operands, as opposed to leaving them unchanged and returning a new value.
list1.append(list2)
...changes list1, making it a member of this category.
Compare the following two chunks of code:
# in this case, it's obvious that list1 was changed
list1.append(list2)
print list1
...and:
# in this case, you as a reader don't know if list1 was changed,
# unless you already know the semantics of list.append.
print list1.append(list2)
Forbidding the latter (by making it useless) thus enhances the readability of the language.
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> a.append(b) # append just appends the variable to the next index and returns None
>>> print a
[1,2,3,[4,5,6]]
>>> a.extend(b) # Extend takes a list as input and extends the main list
[1,2,3,4,5,6]
>>> a+b # + is exactly same as extend
[1,2,3,4,5,6]
When you print a function, you print what it returns and the append method does not return anything. However your list now has a new element. You can print the list to see the changes made.
list1 + list2 means that you combine 2 lists into one big list.
list1.append(element) adds one element to the end of the list.
Here's an example of append vs +
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> a + b
[1, 2, 3, 4, 5, 6]
>>>
>>> a.append(b)
>>> a
[1, 2, 3, [4, 5, 6]]
This question already has answers here:
Different ways of deleting lists
(6 answers)
Closed 7 years ago.
Please what is the most efficient way of emptying a list?
I have a list called a = [1,2,3]. To delete the content of the list I usually write a = [ ]. I came across a function in python called del. I want to know if there is a difference between del a [:] and what I use.
There is a difference, and it has to do with whether that list is referenced from multiple places/names.
>>> a = [1, 2, 3]
>>> b = a
>>> del a[:]
>>> print(b)
[]
>>> a = [1, 2, 3]
>>> b = a
>>> a = []
>>> print(b)
[1, 2, 3]
Using del a[:] clears the existing list, which means anywhere it's referenced will become an empty list.
Using a = [] sets a to point to a new empty list, which means that other places the original list is referenced will remain non-empty.
The key to understanding here is to realize that when you assign something to a variable, it just makes that name point to a thing. Things can have multiple names, and changing what a name points to doesn't change the thing itself.
This can probably best be shown:
>>> a = [1, 2, 3]
>>> id(a)
45556280
>>> del a[:]
>>> id(a)
45556280
>>> b = [4, 5, 6]
>>> id(b)
45556680
>>> b = []
>>> id(b)
45556320
When you do a[:] you are referring to all elements within the list "assigned" to a. The del statement removes references to objects. So, doing del a[:] is saying "remove all references to objects from within the list assigned to a". The list itself has not changed. We can see this with the id function, which gives us a number representing an object in memory. The id of the list before using del and after remains the same, indicating the same list object is assigned to a.
On the other hand, when we assign a non-empty list to b and then assign a new empty list to b, the id changes. This is because we have actually moved the b reference from the existing [4, 5, 6] list to the new [] list.
Beyond just the identity of the objects you are dealing with, there are other things to be aware of:
>>> a = [1, 2, 3]
>>> b = a
>>> del a[:]
>>> print a
[]
>>> print b
[]
Both b and a refer to the same list. Removing the elements from the a list without changing the list itself mutates the list in place. As b references the same object, we see the same result there. If you did a = [] instead, then a will refer to a new empty list while b continues to reference the [1, 2, 3] list.
>>> list1 = [1,2,3,4,5]
>>> list2 = list1
To get a better understanding, let us see with the help of pictures what happens internally.
>>> list1 = [1,2,3,4,5]
This creates a list object and assigns it to list1.
>>> list2 = list1
The list object which list1 was referring to is also assigned to list2.
Now, lets look at the methods to empty an list and what actually happens internally.
METHOD-1: Set to empty list [] :
>>> list1 = []
>>> list2
[1,2,3,4,5]
This does not delete the elements of the list but deletes the reference to the list. So, list1 now points to an empty list but all other references will have access to that old list1.
This method just creates a new list object and assigns it to list1. Any other references will remain.
METHOD-2: Delete using slice operator[:] :
>>> del list1[:]
>>> list2
[]
When we use the slice operator to delete all the elements of the list, then all the places where it is referenced, it becomes an empty list. So list2 also becomes an empty list.
Well, del uses just a little less space in the computer as the person above me implied. The computer still accepts the variable as the same code, except with a different value. However, when you variable is assigned something else, the computer assigns a completely different code ID to it in order to account for the change in memory required.
Could someone please offer a concise explanation for the difference between these two Python operations in terms of modifying the list?
demo = ["a", "b", "c"]
for d in demo:
d = ""
print demo
#output: ['a', 'b', 'c']
for c in range(len(demo)):
demo[c] = ""
print demo
#output: ['', '', '']
In other words, why doesn't the first iteration modify the list? Thanks!
The loop variable d is always a reference to an element of the iterable object. The question is not really a matter of when or when isn't it a reference. It is about the assignment operation that you are performing with the loop.
In the first example, you are rebinding the original reference of an element in the object, with another reference to an empty string. This means you don't actually do anything to the value. You just assign a new reference to the symbol.
In the second example, you are performing an indexing operation and assigning a new reference to the value at that index. demo remains the same reference, and you are replacing a value in the container.
The assignment is really the equivalent of: demo.__setitem__(c, "")
a = 'foo'
id(a) # 4313267976
a = 'bar'
id(a) # 4313268016
l = ['foo']
id(l) # 4328132552
l[0] = 'bar'
id(l) # 4328132552
Notice how in the first example, the object id has changed. It is a reference to a new object. In the second one, we index into the list and replace a value in the container, yet the list remains the same object.
In the first example, the variable d can be thought of a copy of the elements inside the list. When doing d = "", you're essentially modifying a copy of whatever's inside the list, which naturally won't change the list.
In the second example, by doing range(len(demo)) and indexing the elements inside the list, you're able to directly access and change the elements inside the list. Therefore, doing demo[c] would modify the list.
If you do want to directly modify a Python list from inside a loop, you could either make a copy out the list and operate on that, or, preferably, use a list comprehension.
So:
>>> demo = ["a", "b", "c"]
>>> test = ["" for item in demo]
>>> print test
["", "", ""]
>>> demo2 = [1, 5, 2, 4]
>>> test = [item for item in demo if item > 3]
>>> print test
[5, 4]
When you do d = <something> you are making the variable d refer to <something>. This way you can use d as if it was <something>. However, if you do d = <something else>, d now points to <something else> and no longer <something> (the = sign is used as the assignment operator). In the case of demo[c] = <something else>, you are assigning <something else> to the (c+1)th item in the list.
One thing to note, however, is that if the item d has self-modifying methods which you want to call, you can do
for d in demo:
d.<some method>()
since the list demo contains those objects (or references to the objects, I don't remember), and thus if those objects are modified, the list is modified too.
Lest say you want the last element of a python list: what is the difference between
myList[-1:][0]
and
myList[len(myList)-1]
I thought there was no difference but then I tried this
>>> list = [0]
>>> list[-1:][0]
0
>>> list[-1:][0] += 1
>>> list
[0]
>>> list[len(list)-1] += 1
>>> list
[1]
I was a little surprised...
if you use slicing [-1:], the returned list is a shallow-copy, not reference. so [-1:][0] modifies the new list. [len(list)-1] is reference to last object.
list[-1:] creates a new list. To get the same behaviour as list[len(list)-1] it would have to return a view of some kind of list, but as I said, it creates a new temporary list. You then proceed to edit the temporary list.
Anyway, you know you can use list[-1] for the same thing, right?
Slicing creates copy (shallow copy). It's often used as an shallow copy idiom.
i.e.
list2 = list1[:]
is equivalent to
import copy
list2 = copy.copy(list1)