Python · Advanced 1
Names, Objects and Memory
Name
Class
Date
Mark / 32
Section A
Circle the letter of the correct answer. One mark each.
- 1After
a = [1, 2]andb = a, what doesa.append(3)do to b?1- AIt raises an error
- BNothing: b is a separate copy
- CIt sets b to None
- Db shows [1, 2, 3] too, because both names refer to one list
- 2What is the difference between
==andis?1- A
==tests identity;iscompares values - B
==compares values;istests whether two names refer to the same object - CThey are the same
- D
iscan only be used with numbers
- A
- 3Which of these is immutable?1
- AA list
- BA set
- CA dictionary
- DA tuple
- 4Why can a list not be used as a dictionary key?1
- AIt is mutable, so its hash could change
- BLists have no length
- CIt is too large
- DKeys must be strings
- 5What does this print?
def f(x=[]): x.append(1); return xthenf(); print(f())1- A[]
- B[1, 1]
- C[1]
- DAn error
- 6What is the safe way to give a function a default empty list?1
- AIt cannot be done
- BUse a global list
- CUse None as the default and create the list inside the function
- DUse [] but copy it after
- 7Which copy shares the inner lists with the original?1
- AA shallow copy
- BA deep copy
- CNeither
- DBoth
- 8Why is
[[0] * 3] * 3a poor way to build a grid?1- AIt makes a tuple
- BIt uses too much memory
- CIt makes the grid too small
- DAll three rows are the same list object
- 9What happens to an object when its reference count reaches zero?1
- AIt is freed immediately
- BIt is moved to the disk
- CIt is copied
- DIt is kept until the program ends
- 10Why does Python need a garbage collector as well as reference counting?1
- AReference counting only works for numbers
- BReference counting cannot free lists
- CObjects in a reference cycle never reach a count of zero
- DReference counting is too fast
Section B
Answer in the space provided. The number of marks tells you how many separate points to make.
- 1ExplainExplain the difference between passing a parameter by value and passing it by reference.4
- 2StateThe program shown is run. State what is output by each of the two print statements, and explain why the outputs are different.4Python
a = [1, 2, 3] b = a c = a[:] b.append(4) c.append(5) print(a) print(c) - 3ExplainThe subprogram shown is called twice, first with add('apple') and then with add('bread'). State what is returned by the second call, explain why, and show how the subprogram could be rewritten to avoid the problem.5Python
def add(item, basket=[]): basket.append(item) return basket - 4DescribeDescribe the difference between a shallow copy and a deep copy of a list of lists.4
- 5ExplainExplain how reference counting is used to recover memory, and explain why a garbage collector is also needed.5
Mark scheme
Section A
Section B
1 Explain the difference between passing a parameter by value and passing it by reference. 4
One mark for each of the following, to a maximum of 4.
- By value: the subprogram receives a copy of the value
- So changes made to the parameter inside the subprogram do not affect the original variable
- By reference: the subprogram receives a reference (the address) to the original variable or object
- So changes made to the parameter do affect the original
Model answer. When a parameter is passed by value, the subprogram receives a copy of the value, so any changes made to the parameter inside the subprogram do not affect the original variable. When a parameter is passed by reference, the subprogram receives a reference to the original variable or object, such as its address, so changes made to the parameter do affect the original. Python passes a reference to the object, so a mutable object such as a list can be changed by the subprogram, though rebinding the parameter to a new object does not affect the caller.
2 The program shown is run. State what is output by each of the two print statements, and explain why the outputs are different. 4
One mark for each of the following, to a maximum of 4.
- The first print outputs [1, 2, 3, 4]
- The second print outputs [1, 2, 3, 5]
- b = a makes b another name for the same list, so appending through b changes the list a refers to
- a[:] makes a (shallow) copy, so c is a separate list and the append to c does not affect a
Model answer. The first print outputs [1, 2, 3, 4] and the second outputs [1, 2, 3, 5]. The statement b = a does not copy the list: it makes b a second name for the same list, so b.append(4) changes the one list that both a and b refer to. The statement c = a[:] makes a copy of the list, so c is a separate list. The append of 5 changes only c, and a is not affected.
3 The subprogram shown is called twice, first with add('apple') and then with add('bread'). State what is returned by the second call, explain why, and show how the subprogram could be rewritten to avoid the problem. 5
One mark for each of the following, to a maximum of 5.
- The second call returns ['apple', 'bread']
- The default list is created only once, when the subprogram is defined
- So every call that uses the default shares the same list, which keeps the earlier item
- Rewrite with a default of None
- and create a new empty list inside the subprogram if the parameter is None
Model answer.
def add(item, basket=None):
if basket is None:
basket = []
basket.append(item)
return basket
print(add("apple"))
print(add("bread"))The second call to the original returns ['apple', 'bread']. The default list is created only once, when the subprogram is defined, so every call that does not supply its own list shares that one list, and the apple from the first call is still in it. The rewritten version uses None as the default and creates a new empty list inside the subprogram each time, so each call starts with its own list.
4 Describe the difference between a shallow copy and a deep copy of a list of lists. 4
One mark for each of the following, to a maximum of 4.
- A shallow copy creates a new outer list
- but the inner lists in it are the same objects as in the original (they are shared)
- so changing an inner list through one copy is visible through the other
- A deep copy creates new copies of the inner lists as well, so the two are completely independent
Model answer. A shallow copy creates a new outer list, but the inner lists in it are the same objects as the ones in the original list, so they are shared. Changing an inner list through one copy is therefore visible through the other. A deep copy creates new copies of the inner lists as well, and of anything inside them, so the original and the copy are completely independent and a change to one never affects the other.
5 Explain how reference counting is used to recover memory, and explain why a garbage collector is also needed. 5
One mark for each of the following, to a maximum of 5.
- Each object keeps a count of the number of references to it
- The count goes up when a new reference is made and down when one is removed
- When the count reaches zero the object cannot be reached, so its memory is freed
- Objects that refer to each other (a cycle) keep each other's counts above zero even when nothing else can reach them
- A garbage collector finds such unreachable cycles and frees them
Model answer. Each object keeps a count of how many references there are to it. The count goes up when a new reference is made, for example by assigning it to a name, and goes down when a reference is removed. When the count reaches zero the object can no longer be reached by the program, so its memory is freed immediately. This does not work for objects that refer to each other in a cycle, because each keeps the other's count above zero even when nothing else in the program can reach either of them. A garbage collector is therefore also needed, which periodically finds groups of unreachable objects such as these and frees them.