Homework Answers
Contents
4.3. Homework Answers#
4.3.1. Question 1#
Solution to Exercise 3.1
a.
>>> val = 5.0
>>> increase_by_one(val)
>>> print(val)
6.0
This is not possible because the variable val
is of type float
which is an immutable type. The attempt below won’t work. Even though the local variable x
and the global variable val
reference the same object 5.0
, the line x += 1
creates a new local variable x
rather than mutating the value of the object 5.0
.
def increase_by_one(x):
x += 1
b.
>>> val = "hello"
>>> increase_by_one(val)
>>> print(val)
hello1
This is not possible for the same reason as a. Strings are immutable and so any attempt to change the value of the string will either fail,
def increase_by_one(x):
x.append("")
…or result in the local variable x
referencing a new object.
def increase_by_one(x):
x += "1"
c.
>>> val = [0, 0, 0]
>>> increase_by_one(val)
>>> print(val)
[0, 0, 0, 1]
This is possible. The append
method mutates the list. The local variable x
and global variable val
both reference the same list and mutating the list affects both variables.
def increase_by_one(x):
x.append(1)
d.
>>> val = np.array([0, 0, 0])
>>> increase_by_one(val)
>>> print(val)
[0 0 0 1]
This is not possible. Even though the Numpy array is a mutable type, it is not possible to change the size of a Numpy array.
https://numpy.org/doc/stable/reference/generated/numpy.ndarray.html
For example, the function numpy.append
doesn’t mutate arrays, but returns a new one. This won’t work:
def increase_by_one(x):
np.append(x, 1)
Marks
1 mark for identifying this case [c].
[a, b] 1 mark for stating that floats/strings are immutable and 1 mark for stating that the value referenced by immutable variables cannot be changed (or similar).
[c] 1 mark for a correct function definition. No marks if a return
statment included, or if the function call has been changed (eg val = increase_by_one(val)
)
[d] Even though arrays are mutable 1 mark they are of fixed size (or do not have an append function or similar) 1 mark
4.3.2. Question 2#
One way to swap the two arrays is to make a temporary copy of the values. Perhaps the simplest way to do this is to copy all of the value into a temporary array first. This works:
def swap_lists(x, y):
z = x[:] # create temporary copy of x
x[:] = y # mutate value of x
y[:] = z # mutate value of y
Note that this works because x[:]
makes a copy of the values of x
. Another way to do the exact same is x.copy()
.
This solution is fine, but we might like to consider if there are other solutions which don’t require making a copy of the list elements. For example, the following code moves one value at a time from x
to y
then one item at a time from y
to x
. Note that we must be careful to move items in the correct order - otherwise we end up revering the list!
def swap_lists(x, y):
n = len(y)
while len(x) > 0:
item = x[0]
x.remove(item) # remove first element of x
y.append(item) # append to end of y
for i in range(n):
item = y[0]
y.remove(item) # remove first element of y
x.append(item) # append to end of x
In most applications this second method is probably not better (it is certainly more complicated) but it has one key advantage: it doesn’t copy any data and therefore doesn’t use any extra memory.
It is not possible to write a function which swaps two strings because strings are immutable (see Question 1d).
Marks
4 marks for a function which correctly swaps the arrays in place. 2 marks if the function works correctly except to reverse the order of the elements.
Deduct 1 mark if a redundant return
statement is included or an attempt is made to change global variables from inside the function, but the function otherwise works.
0 marks if the function does not swap the lists in-place or if the function call is changed to an assignment (eg x, y = swap_lists(x, y)
).
1 mark for stating that strings are immutable.