Python Programming Exercises 3 Notes: These exercises assume that you are comfortable with the contents of the two previous sets of exercises including variables, types, arithmetic expressions, logical expressions, conditional statements and defining functions. If you did not finish the previous set of exercises you really should finish those before moving on to this set. 1. Lists are declared using square brackets with the elements of the list separated by commas. Lists can hold an arbitrary number of values which can be of different types. We use the len( ) function to discover the number of elements in a list. Try these examples: >>> len([]) >>> len([0, 1, 2, 3, 4]) >>> len(["a", 1, []]) 2. Lists can be added together and multiplied by an integer: >>> x = [1, 2, 3] + [4, 5, 6] >>> y = ["a"] * 3 We can use the inline versions of addition and multiplication if the list has already been declared: >>> x += [7, 8, 9] >>> y *= 2 3. We can append individual items to an existing list using the append( ) method: 1
>>> x = [] >>> x.append(1) >>> x.append(2) Multiple items can be added using the extend( ) method: >>> x = [] >>> x.extend([1, 2]) 4. You must be careful with assignment of lists because, unlike variables that contain simple values, the contents of the list is not copied, just a reference to the list: >>> x = [] >>> y = x >>> x.append(1) >>> x == y If it is not your intention to have two variables pointing to the same list, then you must use the copy( ) method: >>> x = [] >>> y = x.copy() >>> x.append(1) >>> x!= y It is very important you understand the difference between these two examples! 5. We can find out if a list contains a value using the in operator, just like we did last time for strings: >>> x = [1, 1, 1, 2, 3, 3, 5] >>> 2 in x >>> 4 in x and find the number of occurances of a value with count( ): 2
>>> x.count(1) Write a function called append non dup(mylist, element) that accepts two arguments, a list (mylist) and another variable (element) that can be of any type. The function should only append element to mylist if it is not already present in the list (so the list does not contain any duplicate values). Does your function return the list? Does it matter to the result? Is returning the list a good idea? 6. The ordering of elements in a list does not change unless we reorder them explicitly. This is important because we want to use integers to index elements in the list directly. Programming languages tend to start counting from zero, so the first element in the list is found at index 0, the second element at index 1, etc: >>> x = [1, 2, 3, 4, 5] >>> x[0] >>> x[1] In Python you can additionally access elements with negative numbers, for example, the last element in the list has index -1. This is useful because then we do not need to calculate the length of the list to calculate the correct index: >>> x[-1] >>> x[len(x) - 1] # unnecessary! Your answer from the previous question prevents duplicates from being appended to a list. Rewrite your function to reject consecutive duplicates, i.e. it should work like this: x = [] append_non_dup(x, 1) append_non_dup(x, 2) append_non_dup(x, 2) append_non_dup(x, 1) if x == [1,2,1] : print("correct!") 3
7. Elements can be removed from a list by value using the remove( ) method or by index using the del keyword: >>> x = [1,1,2,2,3,3] >>> x.remove(3) # removes first 3 in the list >>> del x[-1] # removes the element at index -1 (the last one) What happens if you try to remove a value not present in the list or using an index outside of the range of the list? 8. As well as single values we can access subsets of the list. In Python these are called slices. Assume we have a list called x: >>> x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] and two integers to use as indices: slice start and slice end: >>> slice_start = 3 >>> slice_end = 6 We can extract the slice from index slice start (inclusive) to the end of the list: >>> x[slice_start : ] From the start of the list up to index slice end (exclusive): >>> x[ : slice_end] And, finally, from slice start (inclusive) to slice end (exclusive): >>> x[slice_start : slice_end] Make sure you understand how this works by doing a few more examples yourself. The following code helps to demonstrate why the start of the slice is inclusive and the end of the slice is exclusive (because using the same index will neatly split the list in two non-overlapping lists): 4
>>> x = [0,1,2,3,4,5] >>> x == x[:3] + x[3:] 9. All Python scripts have a predefined list called argv in the sys module, which contains all command line arguments given to a script when it is run: import sys print(len(sys.argv), "command line arguments") print(sys.argv) Copy the code above to a file (I have called my version argv.py ) and run it with some arguments: python3 argv.py hello world 1 2 3 Change the script above to only print out the command line arguments after the name of the script (to understand what I mean, run the example). 10. There are two methods to sort a list into order. For both methods to work all elements in the list must be orderable (i.e. values that can be compared with (==, <, <=, >, >=). The sort( ) method will sort a list in place, whereas the sorted( ) function returns a new list: >>> x = [2,5,1,3,4] >>> y = x.copy() >>> y.sort() >>> z = sorted(x) Both methods accept the reverse parameter to sort in reverse order: >>> sorted([2,5,1,3,4], reverse=true) 5
Python already has two functions called min( ) and max( ) that (as you would expect) returns the minimum and maximum values, respectively, from a list. Reimplement min( ) and max( ) using one of the sorting procedures. Which one is better for this problem: sort( ) or sorted( )? Why? 11. For loops in Python should be read as for each element in the sequence. The body of the for loop is executed once per item in the sequence (unless we interrupt it, see next exercises). numbers = [0,1,2,3,4] for i in numbers : Change the example above to only print out even numbers (Hint: you will need to use the modulus % operator). 12. Iterating over ranges of integers is such a common need that Python provides a special function called range( ) for that purpose: for i in range(10) : Change the code above to print out a triangle of asterisks, like this: * ** *** **** ***** 13. The range( ) function can accept two integers, a starting value (inclusive) and a stopping value (exclusive) : 6
for i in range(3, 10) : range( ) can also optionally take a third argument specifying a step value (i.e. only return every n th value in a given range). Try an example using a step value of 2. 14. Suppose we want to be able to associate the i th element in a list with the index i. Iterating through the list does not give us the index, but we can use len as the argument to range to generate a list of indices for use in our list: x = ["a", "b", "c", "d", "e", "f"] for i in range(len(x)) : print(i, x[i]) Change the example to only print out values at even numbered indices. Do not use an if statement, use the step argument in range( ). 15. Sometimes we do not want to iterate over all elements in a list, but stop when some condition is met (break out of the loop): x = [0,1,2,3,4,5,6,7,8,9] for i in x : if i > 4 : break Or skip the rest of the statements in the body of the loop (continue from the beginning): 7
x = [0,1,2,3,4,5,6,7,8,9] for i in x : if i > 3 and i < 6 : continue Play around with these two examples to ensure you understand what code is executed and why. In the case of a for loop, break and continue can always be replaced by different conditional statements, but using them can make your code more readable. Rewrite both examples without using either break or continue to prove this to yourself. 16. The sum( ) function returns the summation of a list of numbers: >>> sum([1,2,3]) Use the sum function to write a function called mean(x) that accepts a list of numbers as an argument and returns the arithmetic mean. Hint: the arithmetic mean for the values a 1, a 2,..., a n is 1 n ni=1 a i 17. Write your own version of sum( ) (you should call it something else). 18. Write a function that accepts a list of numbers as an argument and returns a new list where each value has been normalised (i.e. all elements sum to 1.0 in the same relative proportions as the input list). >>> normalise([1, 1, 2]) == [0.25, 0.25, 0.5] 8
19. Here we use a function called randint(x, y) from the random module which returns a random integer between x and y (inclusive) to implement a simple guessing game: import random r = random.randint(1, 10) print("guess a number between 1 and 10 (you have three guesses).") for i in range(1, 4) : guess = int(input("guess " + str(i) + ": ")) if guess == r : print("correct!") break else : print("wrong.") print("the number was " + str(r)) Write a new version of this program, but where the computer attempts to guess the number you are thinking of. 9