Two names, one list
In the theme on variables, a name was a tag on a string. The tag is tied to an object and only points at it. Any number of tags can be tied to one object. Let's go back to the train holding a list and tie a second tag to it.
The assignment b = a does not copy a list. It ties a second tag to the same train, and a change made through one name is visible through the other:
a = [1, 2, 3]
b = a
b.append(4)
print(a) # [1, 2, 3, 4]
print(len(b)) # 4Let's go through it line by line:
a = [1, 2, 3]builds a list and ties the tagato it.b = aties a second tagbto the same list. No new list appears.b.append(4)couples a wagon onto the train thatbhangs on—the same oneahangs on.print(a)prints[1, 2, 3, 4], andlen(b)gives4: both tags lead to one train.
In the theme on variables, b = a with a number behaved differently: after a = 20, the name b still referred to 10. There, a new assignment retied one tag to another object. Here there is no assignment: b.append(4) changes the object itself, and both tags are tied to it.
To get a separate list, make a copy: a.copy() or the full slice a[:] builds a second train with the same tiles. Click "Next step" and watch a, b and c in the <module> frame. The note on each step says whether there is one object or two.
1a = [1, 2, 3]2b = a3b.append(4)4print(a)5c = a.copy()6c.append(5)7print(a)8print(c)9print(a is b, a is c)
One list is created, and the name a is tied to it.
is and ==
The is operator checks identity: whether two names refer to one and the same object. The == operator compares values. Two different lists with the same elements are equal but not identical:
a = [1, 2, 3]
c = a[:]
print(a == c, a is c) # True False
c.append(4)
print(a, c) # [1, 2, 3] [1, 2, 3, 4]
d = list(a)
e = a.copy()
print(d == a, d is a, e is a) # True False FalseLet's go through the example:
c = a[:]builds a new list:a == cgivesTrue, anda is cgivesFalse.c.append(4)changes only the copy, andastays[1, 2, 3].list(a)anda.copy()also give separate lists:isreturnsFalsefor them.
Numbers, strings and lists are compared with ==. is checks whether it is the same object. It also compares with None—x is None—since a program has only one None object.
Three ways to copy
A new list with the same elements is called a copy. There are three ways to make one, and they give the same result:
a[:], the full slice;list(a), thelistfunction;a.copy(), the list method.
Changes to a copy do not touch the original list. Here the tag analogy simplifies things: with a real tag you can see where its string leads. In code, a and b look like two independent variables, and only is shows that they share one object.
A list in a function
A function parameter is one more tag on the object passed in the call. If the function changes a list through its parameter, the change is visible outside too:
def add_bonus(scores):
scores.append(10)
marks = [7, 8]
add_bonus(marks)
print(marks) # [7, 8, 10]Assigning to the parameter, on the other hand, leaves the caller's list alone. scores = [10] in the function reties only the local name scores to a new list.
Interviewers like to ask this: "How does Python pass arguments to a function?" The answer:
- the function gets not a copy but the same object: the parameter is one more name for it;
- a change to the object through the parameter is visible to the calling code;
- assigning to the parameter reties only the local name.
Sometimes a function is written precisely to change the list passed to it. When the caller's list must not change, the function works with a copy or builds a new list.
Common mistake
A function finds the median—the middle element by size—and sorts its argument to do it:
def median(nums):
nums.sort() # ✗
return nums[len(nums) // 2]
data = [5, 1, 3]
print(median(data)) # 3
print(data) # [1, 3, 5]The median is right, but sort reordered the elements of data. There is no error message, and the order breaks silently for any later code that needs the original data. Inside the function, use a sorted copy: ordered = sorted(nums), and then work with ordered.
Key points
b = aties a second name to the same list: a change throughbis visible througha.a[:],list(a)anda.copy()create a separate list with the same elements.ischecks whether it is the same object, and==compares values.- A function that changes a list through its parameter changes the caller's list.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.