Finals Python Documents PDF

Summary

This document is a set of Python programming notes, possibly lecture notes or a set of practice exercises, covering variables, types, and help functionalities in Jupyter Notebooks. The file is from July 26, 2024.

Full Transcript

variables_strings_print_long_version_solutions July 26, 2024 1 Lesson 1 in Python Programming. Aim of this notebook: Practice Jupyter notebooks and learn on the following topics in Python coding: > variables, type and help. 1.1 Va...

variables_strings_print_long_version_solutions July 26, 2024 1 Lesson 1 in Python Programming. Aim of this notebook: Practice Jupyter notebooks and learn on the following topics in Python coding: > variables, type and help. 1.1 Variables Variable is a named place in the memory where a programmer can store data and later retrieve the data using the variable “name”. : a = 10 It doesn’t look as if anything has happened, but when you did Shift-Enter in the cell above, the Jupyter Notebook sent the code off to be executed by Python. The code cell above takes the number 10, and puts it into a variable called a. Now, when we use the variable a, it will carry the value 10. We say that the variable a has the value 10. We often want to see the values of variables, and the Notebook makes it easy to do that. Here we display the value of the variable a: : a : 10 : # change the content of a variable. a = 12 a : 12 Our code cells can have lines that do some work, followed by a variable on its own, so we can see its value. Like this: : b = 5 b : 5 1 Warning: There are reserved words that cannot be used as variables or function names because there are already used by python to process things. The list of reserved words in python may be found here. Idea: It is better to use my_var (or my_funct) to define a variable (or a function) than var (or funct) alone, because var/funct may be used by Python or one of its library. Idea: It is good to choose a variable’s name that means something related to the aim of the variable. : guyguyg = 35 ukgvuv = 12.5 fytfyt = guyguyg * ukgvuv print(fytfyt) 437.5 : a = 35 b = 12.5 c = a * b print(c) 437.5 : # Now, with the right variables names, we understand what we are doing. hours = 35 rate = 12.5 pay = hours * rate print(pay) 437.5 For python all of the three cells above do exactly the same. However, for us, the last one is much easier to understand. Take home message: choose the name of your variables and function as explicit as you can even if the name looks long. : x = 2 # Assignement statement x = x + 2 # Assignement with expression print(x) # print statement 4 Exercises: How many seconds does it have in a non-leap year and in a leap year? (hint: construct 4 variables with the right names) : nb_of_days = 365 nb_of_hours = 24 nb_of_second = 60 total_nb_of_second = nb_of_days*nb_of_hours*nb_of_second print('The number of days in a non-leap year is:') print(total_nb_of_second) 2 nb_of_days = nb_of_days + 1 total_nb_of_second = nb_of_days*nb_of_hours*nb_of_second print('The number of days in a leap year is:') print(total_nb_of_second) The number of days in a non-leap year is: 525600 The number of days in a leap year is: 527040 Exercise: Guess the value of ‘a’ in the code: a = 2 a = a**2+a+2 print(a-2) Exercise: Guess the value of ‘a’ in the code below: a, b, c = 1, 2, 3 a, b, c = b, c, a a, b, c = c, a, b 1.2 The Notebook as a calculator To get output from the cell, we don’t actually need to have a variable on its own. We can put any expression on the last line. An expression is anything that returns a value. So b on its own returns a value, which is the value of b - in this case 5. But we can also do something like this: : (10 + 5 + 1) / 4 : 4.0 Notice, we didn’t use any variables. (10 + 5 + 1) / 4 is an expression - some code that returns a value. This means that we can use the Notebook as a simple calculator. You’ve already seen + and / and the parentheses. You also have * for multiply, and - for subtract, and ** for to-the-power-of. For example, here’s 104 : : 10 ** 4 : 10000 Order of evaluation: : # What is the result? 1 + 2**3/4*5 : 11.0 3 Exercice: Compute 6(23 )/4 (it should equal 12): : 6*(2**3)/4 : 12.0 Exercice: Compute 10242 /216 (it should be 16) : 1024**2/2**16 : 16.0 We can also use variables in our calculations. For example, we might be interested in the result of 2𝑥2 + 3𝑥 + 10. We want to calculate what answer we get for 𝑥 = 2. : # Set the variable x to 2 x = 2 #Compute the expression 2 * x ** 2 + 3 * x + 10 : 24 Now we can simply get the answer for 𝑥 = 7, or any other value of 𝑥: : x = 7 2 * x ** 2 + 3 * x + 10 : 129 Exercise: How much is 𝑥2 + 3𝑥 when 𝑥 = −11? 4 : x = -11 x**2+3*x : 88 To get the rest of an integer division (for instance to check if a number is even or odd) we use ‘%’ : 10 % 2 : 0 Exercise: Can you tell if 𝑥3 + 10𝑥2 + 𝑥 is even for 𝑥 = 13? : x = 13 y = x**3 + 10*x**2 + x y % 2 == 0 : True To get the quotient of an integer division, we use // : 10//3 : 3 1.2.1 Tab completion One of the very cool things about Jupyter notebooks is that they provide tab completion, similar to many IDEs. If you enter an expression in a cell, the Tab key will search the namespace for any vairable that match the characters you’ve typed: [ ]: the_answer_to_life_the_unverse_and_everything = 42 the_beatles = ['john', 'paul', 'george', 'ringo'] [ ]: # tab complete the_beatles ['john', 'paul', 'george', 'ringo'] 2 Comments in code cells begin with a hash (#) Idea: There are two ways to add comments in a notebook: 1. in a markdown cell 2. in a code cell using # If you want to add a ‘quick’ comment you can do it in a code cell but if you want to provide a longer explanation, it is better to use a markdown cell. : # This is a comment. It doesn't do anything. # This is another comment. It is just for your reading pleasure. 5 # The line below sets the variable c to have value 10. c = 10 # The last line is an expression, and so we see an output of this expression # after the cell. c : 10 3 Print Idea: If you want to force the display of the value of a variable, use the print function. : a = 1 a b=2 b : 2 : a = 1 print(a) b=2 b 1 : 2 Print(f’….’) is used to interpret variables in print : a = 5 print('the value of a is {a}') # variable a is just a string print(f'the value of a is {a}') # variable a is recognized as a variable with a␣ ↪value the value of a is {a} the value of a is 5 : #Use the print(f'.....') to interpret variables in a print name = 'Matthew' age = 23 print(f'Your name is {name} and your age is {age}') name, age = 'marc', 20 print(f'Your name is {name} and your age is {age}') Your name is Matthew and your age is 23 Your name is marc and your age is 20 6 Exercise: Print a sentence that gives the value of 𝑥2 + 𝑥 + 1 when 𝑥 = 1 : x = 1 y = x**2 + x + 1 print(f'The value of x**2+x*1 is {y} when x is {1}') The value of x**2+x*1 is 3 when x is 1 3.0.1 Numbers types Integers and floats work as you’d expect from other programming languages. Let’s create two variables: : some_integer = 73 some_float = 3.14159 We can print out these variables and their types as follows: : print(type(some_integer)) print(type(some_float)) What if you want to print some text and then some numbers? One way to do this is to cast the number as a string and then print it: : print('My integer was ' + str(some_integer)) #str() changes a variable into a␣ ↪string variable print('My float was ' + str(some_float)) My integer was 73 My float was 3.14159 However I often find it more convenient to use the print statement with comma separated values: : print('My integer was', some_integer) print('My float was', some_float) My integer was 73 My float was 3.14159 A natural thing to want to do with numbers is perform arithmetic. We’ve seen the + operator for addition, and the * operator for multiplication (of a sort). Python also has us covered for the rest of the basic binary operations we might be interested in: Operator Name Description a + b Addition Sum of a and b a - b Subtraction Difference of a and b a * b Multiplication Product of a and b a / b True division Quotient of a and b 7 Operator Name Description a // b Floor division Quotient of a and b, removing fractional parts a % b Modulus Integer remainder after division of a by b a ** b Exponentiation a raised to the power of b -a Negation The negative of a : print('Sum:', some_integer + some_float) print('Multiplication:', some_integer * some_float) print('Division:', some_integer / some_float) print('Power:', 10 ** some_integer) Sum: 76.14159 Multiplication: 229.33606999999998 Division: 23.236641318567987 Power: 10000000000000000000000000000000000000000000000000000000000000000000000000 Warning! A common bug that can creep into your code is a lack of care between integer division and floor division. For example, integer division not resulting in a whole number will yield a float : 3 / 2 : 1.5 while the floor division operator drops the fractional part : 3 // 2 : 1 3.0.2 Booleans Python implements all of the usual operators for Boolean logic, but uses English words rather than symbols like &&, ||, etc that are found in other languages: : t = True f = False print(type(t), type(f)) # logical AND print(t and f) # logical OR print(t or f) # logical NOT print(not t) # logical XOR print(t != f) 8 False True False True Exercise: Guess the value of the following expression: t = True f = False not((t or f) and f) != f : not((t or f) and f) != f : True 3.0.3 Strings Python has powerful and flexible string processing capabilities. You can write string literals using either single quote ' of double quotes ": [ ]: a = 'one way of writing a string' b = "another way" type(a) We can also get the number of elements in a string sequence as follows [ ]: hello = 'hello' len(hello) 5 We can also access each character in a string and print it’s value: [ ]: for letter in hello: print(letter) h e l l o Adding two strings together concatenates them and produces a new string [ ]: world = 'world' hello + ' ' + world 'hello world' 9 String objects also come with a range of built-in functions to convert them into various forms: [ ]: hello.capitalize() 'Hello' [ ]: hello.upper() 'HELLO' [ ]: # replace all instances of one substring with another s = 'hitchhiker' s.replace('hi', 'ma') 'matchmaker' Exercise: In the string ‘one plus one equals two!’, replace ‘one’ and ‘two’ so that you get the final sentence ’two plus two equals four. Try to make it in one line. : 'one plus one equals two!'.replace('two','four').replace('one', 'two') : 'two plus two equals four!' Exercise: Guess the type of the variable ‘a’ when 1. a = 1 2. a = ‘james’ 3. a = 1.1 4. a = ‘1’ Idea: The last example show that we must be careful with variables’ type. We can force a variable to be of a certain type. : a = '1' a = int(a) type(a) : int Idea: It is possible to retreive a sub-part of a string. We can look at strings as a sequence of caracters. : third_name = "Alphonse" third_name #python enumeration starts at 0! : 'A' : third_name[0:4] : 'Alph' Exercise: Try the following list of slicings and guess what they do: 1. third_name[-1] 2. third_name[3:] 3. third_name[:5] 2. third_name[::2] 3. third_name[::-1] 4. third_name[::-2] 5. third_name[1:5:2] 10 : print(third_name[-1]) #It provides the last element print(third_name[3:]) #It provides all the elements from the 3rd one up to the␣ ↪end print(third_name[:5]) #It provides all the elements up to the 5th one print(third_name[::2]) #It provides all the elements with a step 2 print(third_name[::-1]) #It provides all the elements with a step -1, e.g. this␣ ↪inverse the word print(third_name[::-2])#It provides all the elements with a step -2 print(third_name[1:5:2]) #It provides all the elements from index 1 to index 5␣ ↪with a step 2. e honse Alpho Apos esnohplA enhl lh It is possible to break the line with ‘slash n’ or add some tabulation with ‘slash t’ : string = 'This is a string!\n(But not a very interesting one)\n\n\tEnd.' print(string) This is a string! (But not a very interesting one) End. Check if they contain certain elements like lists: : string = 'Hello! Everyone.' '!' in string : True : '?' not in string : True We can also check if a substring is present in a string: : 'very' in string : True Splitting strings: Often we need to split sentences into words or file paths into components. For this task we can use the split() function. By default a string is split wherever a whitespace is (this could be normal 11 space, a tab \t or a newline \n). : string.split() : ['Hello!', 'Everyone.'] : 'path/to/file/image.jpg'.split('/') : ['path', 'to', 'file', 'image.jpg'] Stripping strings: Sometimes strings contain leading or trailing characters that we want to get rid of, such as whites- paces or unnecessary characters. We can remove them with the strip() function. Like the split() function it removes whitespaces by default but we can set any characters we want: : '_path/to/file/image.jpg_'.strip('_') : 'path/to/file/image.jpg' : '_-_path/to/file/image.jpg,_,'.strip(',_-') : 'path/to/file/image.jpg' Joining strings Sometimes we split strings into a list of words for processing (like stemming or stop word removal) and then want to join them back to a single string. To to this we can use the join() function: [ ]: ' '.join(['this', 'is', 'a', 'list', 'of', 'words']) 'this is a list of words' [ ]: '-'.join(['this', 'is', 'a', 'list', 'of', 'words']) 'this-is-a-list-of-words' Exercise 2: Write a function that performs the following on string_1 - split the string into words - then strip the special characters /, ‘(’ and ‘)’ from each word - join the words back together with single spaces (' ') - remove the word ’ End’ - make the whole string lower-case : string_1 = 'This is a string! /(But not a very interesting one)/ End.' print(string_1) This is a string! /(But not a very interesting one)/ End. : my_list = [] for ele in string_1.split(' '): my_list.append(ele.strip('/()')) print(my_list) 12 ' '.join(my_list).replace(' End', '').lower() ['This', 'is', 'a', 'string!', 'But', 'not', 'a', 'very', 'interesting', 'one', 'End.'] : 'this is a string! but not a very interesting one.' Exercise: Count the number of time the letter ‘a’ is in the string ‘aaaabbbbaaaa’ [ ]: my_str = 'aaaabbbbaaaa' my_str.count('a') 8 Exercise: We can also use the ‘+’ for concatenation of strings. Concatenate the two strings ‘aaaaa’ and ‘babab’ and count the number of ‘a’ in the result. [ ]: my_str_1, my_str_2 = 'aaaaa', 'babab' new_str = my_str_1 + my_str_2 new_str.count('a') 7 4 Input Python can read data from the user thanks to the input command. : name_var = input('What is your name') print(f'Welcome {name_var} to the BBA python course!') Welcome Guillaume to the BBA python course! Warning: By default the type of input given to python is a string. If we expect a number we first need to convert it into a number. : age_var = int(input('What is a your age?')) dob = 2025 - age_var print(f'You are {age_var} years old. You were born in {dob}.') You are 23 years old. You were born in 2002. Exercise: Write a program that prompt the user for the number of hours and rate to compute the gross pay. : hours = int(input('How many hours have you worked?')) rate = int(input('What is the rate per hour?')) pay = hours * rate print(f'You will get {pay} euros.') You will get 552 euros. 13 lists_long_version_with_solutions July 26, 2024 1 Lesson 3 in Python Programming. Aim of this notebook: learn on the following topics: > lists 2 Lists Lists are the first examples of Python data containers. Here is a list of two numbers: : my_list = [10, 4, 20] my_list : [10, 4, 20] Notice the square brackets around the list items, and a comma between the items. : my_list, my_list, my_list[-1] : (10, 4, 20) Warning: Python indexed elements in a list starting from 0. : #We access to the number of elements in a list via the 'len()' function: len(my_list) : 3 Exercise: What are the lengths of the following lists? Fill in the variable lengths with your predictions. (Try to make a prediction for each list without just calling len() on it.) : a = [1, 2, 3] b = [1, [2, 3]] c = [] d = [1, 2, 3][1:] # Put your predictions in the list below. Lengths should contain 4 numbers, the # first being the length of a, the second being the length of b and so on. lengths = [3, 2, 0, 2] 1 Slicing In addition to accessing list elements one at a time, Python provides concise syntax to access sublists; this is known as slicing. Let’s begin by using Python’s built-in range function to create a list of integers: : L = list(range(10)) L : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] To get a slice from [2, 4) we run : L[2:4] : [2, 3] while to get a slice from index 2 to the end of the list we run : L[2:]#get all elements starting from the one indexed by 2 (ie the third one in␣ ↪the list) : [2, 3, 4, 5, 6, 7, 8, 9] To get a slice from the start to index 5 (exclusive) we run : L[:5]#get the first 5 elements : [0, 1, 2, 3, 4] To get a slice of the whole list: : L[:] : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] : L[-1]#get the last element : 9 : L[::2]#slice with a step of size 2 : [3, 6, 9] [ ]: L[3::3]#slice with a step of size 3 starting at 3 Exercise: - get the list of all even numbers from 0 to 30 - get the list of all odd numbers from 10 to 30 : my_list = list(range(0,31)) print(my_list[::2]) 2 my_list[1::2] [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30] : [1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29] Slices can also be negative : L[:-1] : [0, 1, 2, 3, 4, 5, 6, 7, 8] [ ]: L[2:4] = ['a', 'b'] L [0, 1, 'a', 'b', 4, 5, 6, 7, 8, 9] : my_list = [1, 2, 3, 8, 9, 10, 20] my_list[4::-2] : [9, 3, 1] Exercise: 1. Construct a list of all the numbers from 0 to 10 2. Retreive all the even numbers with a carefully chosen slicing : my_list = list(range(0,11)) my_list[2::2] : [2, 4, 6, 8, 10] You can make an empty list by putting nothing between the brackets: : my_empty_list = [] my_empty_list : [] Exercise: You are analyzing sports teams. Members of each team are stored in a list. The Coach is the first name in the list, the captain is the second name in the list, and other players are listed after that. These lists are stored in another list, which starts with the best team and proceeds through the list to the worst team last. 1. Complete the function below to select the captain of the worst team. 2. construct examples to check your function : def losing_team_captain(teams): """Given a list of teams, where each team is a list of names, return the␣ ↪captain (2nd name in the list) from the last listed team 3 """ return teams[-1] : team_1 = ['Peter', 'Jack', 'player_1', 'player_2', 'player_3'] team_2 = ['Mac', 'Jane', 'player_11', 'player_21', 'player_31'] teams = [team_1, team_2] losing_team_captain(teams) : 'Jane' Exercise: Complete the function below according to its docstring. [ ]: def select_second(L): """Return the second element of the given list. If the list has no second element, return None. """ if len(L) >= 2: return L else: None [ ]: L = [1,2] select_second(L) 2 Exercise: The next iteration of Mario Kart will feature an extra-infuriating new item, the Purple Shell. When used, it warps the last place racer into first place and the first place racer into last place. 1. Complete the function below to implement the Purple Shell’s effect. 2. Try it on the list ‘[“Mario”, “Bowser”, “Luigi”]’ (you should get [“Luigi”, “Bowser”, “Mario”]) : def purple_shell(racers): """Given a list of racers, set the first place racer (at the front of the␣ ↪list) to last place and vice versa. """ first_racer = racers last_racer = racers[-1] racers = last_racer racers[-1] = first_racer return racers : racers = ["Mario", "Bowser", "Luigi"] purple_shell(racers) : ['Luigi', 'Bowser', 'Mario'] 4 Another thing we might want to do to a list is append a value. We can do this using the append method of the list. A method is a function attached to a value. : my_list.append(7) my_list : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 7] : my_list.append(1) my_list : [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 7, 1] : my_list = [3, 5, 1, 3] my_list.count(3), my_list.count(1) : (2, 1) Notice that we call the method using the name of the list - here my_list, followed by a dot, followed by the name of the method, here append and count. append and count are methods attached to my_list. We can also use some functions on a list like the sum()function. : my_list = [3, 5, 1, 3] sum(my_list) : 12 Concatenation of two lists. : list1 = [1, 2] list2 = [3, 4] list1 + list2 : [1, 2, 3, 4] Careful of the brackets: You need square brackets - [ and ] to make a list. If you use parentheses () or curly brackets {} - you’ll get something other than a list. Exercise: We’re using lists to record people who attended our party and what order they arrived in. For example, the following list represents a party with 7 guests, in which Adela showed up first and Ford was the last to arrive: party_attendees = ['Adela', 'Fleda', 'Owen', 'May', 'Mona', 'Gilbert', 'Ford'] A guest is considered ‘fashionably late’ if they arrived after at least half of the party’s guests. However, they must not be the very last guest (that’s taking it too far). In the above example, Mona and Gilbert are the only guests who were fashionably late. Complete the function below which takes a list of party attendees as well as a person, and tells us whether that person is fashionably late. 5 [ ]: #You can check if en element is in a list with 'in' my_list = [1, 2, 3] 2 in my_list True [ ]: def fashionably_late(arrivals, name): """Given an ordered list of arrivals to the party and a name, return␣ ↪whether the guest with that name was fashionably late. """ nb_of_guest = len(arrivals) if name in arrivals[int(nb_of_guest/2)+1:-1]: print(f'{name} is fashionably late') else: print(f'{name} is not fashionably late') [ ]: party_attendees = ['Adela', 'Fleda', 'Owen', 'May', 'Mona', 'Gilbert', 'Ford'] fashionably_late(party_attendees, 'Gilbert') Gilbert is fashionably late 2.0.1 Two other useful methods for lists: del and remove : my_list = ['stat', 'python', 'marketting'] #We know how to append in a list my_list.append('micro') #We know how to count the number of times a given item appears in a list print(my_list.count('python')) my_list 1 : ['stat', 'python', 'marketting', 'micro'] : # Next, we can remove items from a list: either by giving the index del my_list my_list : ['python', 'marketting', 'micro'] : # Or by remving the item via its name my_list.remove('micro') my_list : ['python', 'marketting'] 6 : list1 = [1, 1, 2, 3, 1] list1.remove(1) #it only removes the first $1$ list1 : [1, 2, 3, 1] Warning: There are two ways to copy a list: either by making copy identical to the original one or by making an independent copy. : my_list = ['a', 'b', 'c'] my_list_2 = my_list # This is a copy identical to the original one my_list_2.append('d') # When the copy is modified this will make the same␣ ↪modification to the original one my_list : ['a', 'b', 'c', 'd'] : my_list_3 = my_list.copy() # This is a copy independent to the original one my_list_3.append('e') # When the copy is modified this will NOT make the␣ ↪modification to the original one my_list : ['a', 'b', 'c', 'd'] Loops on lists [ ]: animals = ['cat', 'dog', 'monkey'] for animal in animals: print(animal) cat dog monkey List comprehension [ ]: # fill a list using a for loop nums = [0, 1, 2, 3, 4] squares = [] for x in nums: squares.append(x ** 2) squares [0, 1, 4, 9, 16] : # fill a list using list comprehension nums = [0, 1, 2, 3, 4] 7 squares = [x ** 2 for x in nums] squares : [0, 1, 4, 9, 16] : nums = [0, 1, 2, 3, 4] even_squares = [x ** 2 for x in nums if x % 2 == 0] even_squares : [0, 4, 16] Exercise: If we list all the natural numbers below 10 that are multiples of 5 or 3, we get 3, 5, 6 and 9. The sum of these multiples is 23. Find the sum of all the multiples of 3 or 5 below 1000. : nb_multi_3_or_5 = [x for x in range(1, 1000) if x % 3 == 0 or x % 5 == 0] sum(nb_multi_3_or_5) : 233168 enumerate It’s common when iterating to want to keep track of the index when iterating over a sequence. Python has a built-in function called enumerate just for this: [ ]: for idx, animal in enumerate(animals): print(f'#{idx + 1}: {animal}') #1: cat #2: dog #3: monkey zip zip is a useful function to pair elements of a lists, tuples or other sequences to create a list of tuples: [ ]: seq1 = ['foo', 'bar', 'baz'] seq2 = ['one', 'two', 'three'] zipped = zip(seq1, seq2) list(zipped) [('foo', 'one'), ('bar', 'two'), ('baz', 'three')] 8 functions_long_version_with_solutions July 26, 2024 1 Lesson 4 in Python Programming. Aim of this notebook: learn on the following topics: > functions, methods, packages 1.1 Defining functions : def greetings(name): print("Welcome, "+ name) : greetings('John') Welcome, John To define a function, we use the def keyword. The name of the function is what comes after the keyword. After the name, we have the parameters of the function which are written between parenthe- ses. After the colon, we have the body of the function with the correct indentation. That’s where we state what we want our function to do. : def greetings(name, department): print("Welcome, "+ name) print("You are part of the "+ department) : greetings('John', 'IDS') Welcome, John You are part of the IDS Sometimes we don’t want a function to simply run and finish. We may want a function to manip- ulate data we passed it and then return the result to us: : def area_triangle(height,base): return base*height/2 : area_triangle(10, 20) : 100.0 1 We can use return to return more than one value. Let’s say you have a duration of time in seconds and you want to convert that to the equivalent number of hours, minutes, and seconds: : def convert_seconds(seconds): hours=seconds//3600 minutes=(seconds-hours*3600)//60 remaining_seconds=seconds-hours*3600-minutes*60 return hours, minutes, remaining_seconds : convert_seconds(5000) : (1, 23, 20) : num_seconds = 5000 hours, minutes, remaining_seconds = convert_seconds(num_seconds) print(f'There are {hours} hours, {minutes} minutes and {remaining_seconds}␣ ↪seconds in {num_seconds} seconds') There are 1 hours, 23 minutes and 20 seconds in 5000 seconds Docstring It is a very recommended practice to add in the preambule of a function what it is supposed to do: it is called the docstring of a function. It starts and finishes with “ “ “. : def my_funct(a, b): """Takes two numbers a and b and return the sum""" return a+b Exercise: Add a docstring to all three previous functions that were constructed : ‘con- vert_seconds’, ‘area_triangle’ and ‘greetings’. Getting Help: We can get help on built-in functions or on our own function (thanks to the docstring) [ ]: help(round) Help on built-in function round in module builtins: round(number, ndigits=None) Round a number to a given precision in decimal digits. The return value is an integer if ndigits is omitted or None. Otherwise the return value has the same type as the number. ndigits may be negative. [ ]: help(my_funct) Help on function my_funct in module __main__: my_funct(a, b) 2 Takes two numbers a and b and return the sum help() displays two things: 1. the header of that function round(number, ndigits=None). In this case, this tells us that round() takes an argument we can describe as number. Additionally, we can optionally give a separate argument which could be described as ndigits. 2. A brief English description of what the function does. : #Docstring with an example: def least_difference(a, b, c): """Return the smallest difference between any two numbers among a, b and c. >>> least_difference(1, 5, -5) 4 """ diff1 = abs(a - b) diff2 = abs(b - c) diff3 = abs(a - c) return min(diff1, diff2, diff3) : help(least_difference) Help on function least_difference in module __main__: least_difference(a, b, c) Return the smallest difference between any two numbers among a, b and c. >>> least_difference(1, 5, -5) 4 Aside: The last two lines of the docstring are an example function call and result. (The >>> is a reference to the command prompt used in Python interactive shells.) Python doesn’t run the example call - it’s just there for the benefit of the reader. The convention of including 1 or more example calls in a function’s docstring is far from universally observed, but it can be very effective at helping someone understand your function. For a real-world example, see this docstring for the numpy function np.eye. Good programmers use docstrings unless they expect to throw away the code soon after it’s used (which is rare). So, you should start writing docstrings, too! Exercise: Construct a function that takes three arguments (hours, minutes, second)and com- pute the totale number of seconds. : def my_fct(hours, minutes, second): return hours*3600 + minutes*60 + second 3 : my_fct(1, 30, 30) : 5430 Exercise: Create a function that compares two numbers and returns them in increasing order. : def my_fct_2(a, b): if a>b: return b, a else: return a, b : my_fct_2(10, 20) : (10, 20) : #other solution def my_fct_2(a, b): return min(a,b), max(a, b) : my_fct_2(10, 20) : (10, 20) Exercise: Complete the body of the following function according to its docstring. HINT: Python has a built-in function round. [ ]: def round_to_two_places(num): """Return the given number rounded to two decimal places. >>> round_to_two_places(3.14159) 3.14 """ return round(num, 2) [ ]: round_to_two_places(3.14159) 3.14 1.2 Default arguments When we called help(print), we saw that the print function has several optional arguments. For example, we can specify a value for sep to put some special string in between our printed arguments: : print(1, 2, 3, sep=' < ') 1 < 2 < 3 4 But if we don’t specify a value, sep is treated as having a default value of ' ' (a single space). : print(1, 2, 3) 1 2 3 Adding optional arguments with default values to the functions we define turns out to be pretty easy: [ ]: def greet(who="Colin"): print("Hello,", who) greet() greet(who="Kaggle") # (In this case, we don't need to specify the name of the argument, because␣ ↪it's unambiguous.) greet("world") Exercise: Friends Alice, Bob and Carol want to share evenly candies. For the sake of their friendship, any candies left over would be smashed. For example, if they collectively bring home 91 candies, they’ll take 30 each and smash 1. Below is a simple function that will calculate the number of candies to smash for any number of total candies. Modify it so that it optionally takes a second argument representing the number of friends the candies are being split between. If no second argument is provided, it should assume 3 friends, as before. Update the docstring to reflect this new behaviour. [ ]: def to_smash(total_candies, nb_of_friends = 3): """Return the number of leftover candies that must be smashed after␣ ↪distributing the given number of candies evenly between nb_of_friends friends. >>> to_smash(91) 1 """ return total_candies % nb_of_friends [ ]: to_smash(91, 4) 3 Exercise: Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first terms will be: 1, 2, 3, 5, 8, 13, 21, 34, 55, 89. By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms. 5 : def sum_even_nb_Fibonacci(n): sum_even_nb = 0 Fib_seq_1 = 1 Fib_seq_2 = 2 while Fib_seq_1 0: return 'positive' elif x < 0: return 'negative' else: return 'zero' for x in [-1, 0, 1]: print(sign(x)) negative zero positive In addition to positional arguments, functions can have keyword arguments that are typically used to specify default values: [ ]: def hello(name, loud=False): if loud: print('G\'day, %s!' % name.upper()) else: print('G\'day, %s' % name) hello('Bob') hello('Fred', loud=True) G'day, Bob G'day, FRED! Finally, it is quite common to write functions that return multiple objects as a tuple. For example we can write something like 7 [ ]: def is_number_positive(number): if number > 0: return True, number else: return False, number [ ]: is_number_positive(-1) (False, -1) [ ]: is_number_positive(42) (True, 42) One cool aspect of such functions is that the returned objects can be unpacked in two different ways: [ ]: tup = is_number_positive(3); tup (True, 3) [ ]: is_positive, number = is_number_positive(-10) print(is_positive) print(number) False -10 1.5 Problem: construct a coin toss. We want our Python code to do the equivalent of a coin toss. We want to run the code, and get a random answer, that is answer 1 in 50% of the time (representing a Head), and answer 0 for 50% of the time (representing a Tail). Let’s start by getting a random number that can be any value, with equal likelihood, all the way between 0 and 1. We think first of the random module: : # packages (or modules) contain many useful tools such as objects, methods and␣ ↪functions # random is a package that contains tools to simulate randomness # we usually import several packages in data science project because it is very␣ ↪convenient to use tools developped by others. import random We can explore the functions inside the random module by “tab completion” on ‘random.’ or with ‘random?’. We can also look at the documentation for the random module. We discover that the random function in the random module does what we want: : random.random() 8 : 0.7901798214456953 : # Get a random number between 0 and 1 random.random() : 0.948111417906168 : # Get another random number between 0 and 1 random.random() : 0.0867413834966907 To do our coin toss, we can look at the random number. If it is < 0.5, we can decide this is a 0 (for Tails), and if it is >= 0.5, we will say it is a 1 (for Heads). This is a “if, then” type statement, called a conditional. It’s called a conditional because we do something only if a condition is met. The condition here is that the random number is < 0.5. A conditional in Python looks like this: : random_no = random.random() # Next we see the condition that is being tested if random_no < 0.5: # Tails our_result = 0 else: # Heads our_result = 1 : our_result : 0 There are a couple of important things to notice here. The conditional starts with if, followed by the condition, here random_no < 0.5. There must be a colon : at the end of the line, and this signals the start of the statements that should run if the condition is True. The statement to execute if the condition is True, is our_result = 0. Notice that this statement is indented by four spaces. It is this indentation that tells Python that the statement should run only if the condition is True. You can put many statements to run if the condition is True, but they must all be indented in the same way. Luckily the Notebook and other code editors usually guess what we want and do the indentation for us‘ Next we see a line else:. Notice that this line is not indented. That is because we want this line to run if the condition is False. Remember, the indented lines above run only when the condition is True. Notice again that the else: has a colon at the end, to say that more indented lines will follow. These lines only run if the condition is False. To recap, the indented lines after the if and before the else run only if the condition is True. The indented lines after the else: only run if the condition is False. 9 You don’t have to have an else: part of a conditional block - you can just have the if part. For example, this code would do the same as the code above: : random_no = random.random() # Default to Heads our_result = 1 # We have the "if" part, but no "else:" part. if random_no < 0.5: # Tails our_result = 0 : our_result : 0 We’re going to wrap up our logic for the coin toss into a function, and call the function coin_toss. Like random.random our function coin_toss will accept no arguments. It will return a 0 50% of the time and a 1 50% of the time. : def coin_toss():# there is no argument here random_no = random.random() if random_no < 0.5: our_result = 0 else: our_result = 1 return our_result : # Notice, we pass no arguments coin_toss() : 0 : coin_toss() : 1 : coin_toss() : 1 1.5.1 Exercise Construct a function that returns 1 (for girls) or 0 (for boys) when it is assumed that the proportion of boys born in the UK is 0.513. Hint: you can copy the coin_toss function and modify it to return 0 (for a boy) 51.3% of the time, and 1 (for a girl) 48.7%. 10 : def girl_or_boy(): # Return 1 for a girl, 0 for a boy random_no = random.random() if random_no < 0.513: our_result = 0 else: our_result = 1 return our_result You can try your function out a few times with the cell below: : girl_or_boy() : 0 Exercice: return a function that takes an argument ‘p’ and return 1 with probability 𝑝 and 0 with probability 1 − 𝑝. : def my_fct(p): # Return 1 for a girl, 0 for a boy random_no = random.random() if random_no < p: our_result = 1 else: our_result = 0 return our_result Exercice: 1) Write a Python function to find the Max of two numbers. 2) Write a Python function to find the Max of three numbers. : def my_max_fct(a, b): if a>b: return a else: return b : my_max_fct(10, 29) : 29 : def my_max_3_fct(a, b, c): if a > my_max_fct(b, c): return a else: return my_max_fct(b, c) : my_max_3_fct(10, 20, 30) 11 : 30 Exercise: Define a function that compute 𝑥2 + 10𝑥 + 1 : def my_fct(x): return x**2 + 10*x + 1 : my_fct(1) : 12 : #extra: we can plot our function using matplotlib.pyplot from matplotlib import pyplot as plt import numpy as np x = np.linspace(-10, 10, 100) plt.plot(x, my_fct(x), color='red') plt.show() Exercice: Write a Python program to reverse a string. Sample String : “1234abcd” Expected Output : “dcba4321” 12 : def my_reverse(my_str): if len(my_str) == 0: return '' else: return my_str[-1] + my_reverse(my_str[:-1]) : my_reverse("1234abcd") : 'dcba4321' 2 Recursion Recursion lets us tackle complex problems by reducing them to simpler ones. A recursive function is a function defined in terms of itself via self-referential expressions. This means that the function will continue to call itself and repeat its behavior until some condition is met to return a result. Let us write a recursive function for calculating n!. First, decompose the original problem into simpler instances of the same problem: 𝑛! = 𝑛 ∗ (𝑛 − 1)! The large problem is broken down into successively less complex ones: 𝑛! = 𝑛 ∗ (𝑛 − 1)! = 𝑛 ∗ (𝑛 − 1) ∗ (𝑛 − 2)! = ⋯ = 𝑛 ∗ (𝑛 − 1) ∗ (𝑛 − 2) ∗ ⋯ ∗ 1! Here, 1! is our base case, and it is equal to 1. : def factorial_recursive(n): # Base case: 1! = 1 if n == 1: return 1 # Recursive case: n! = n * (n-1)! else: return n * factorial_recursive(n-1) 2.0.1 Exercice The is_power_of function below takes two arguments (num, base) and returns True when numis a power of baseand Falseotherwise. The indentations are wrong. Add the right indentation so that the is_power_of function works as it should be. Hint: if num 1 - p: nb_girls +=1 counter +=1 prop_of_girls.append(nb_girls/counter) plt.plot(np.arange(len(prop_of_girls)), prop_of_girls) plt.show() : girls_and_boys(1000, 0.1) 2.1 The For loops After the whileloop from the last notebook (as homework), we have a look at the for loop. To start, let us redefine the function to do a coin toss: : def coin_toss(): random_no = np.random.rand() if random_no < 0.5: our_result = 0 4 else: our_result = 1 return our_result Using a for loop, we write a function that collects 4 coin tosses. : coin_tosses = [] for i in range(4): result = coin_toss() coin_tosses.append(result) coin_tosses : [0, 0, 0, 1] 2.1.1 The take-home message: If you want to repeat something N times in Python, then use a for loop, that starts with something like for i in range(N):. That’s the quick version. If you want to understand more about the range and the i in that statement, read on. 2.1.2 More detail Notice the use of range. The range function here gives us a sequence of numbers, starting at 0, and going up to, but not including 4. Therefore, the range function is giving us 4 numbers, 0, 1, 2, 3: : list(range(4)) # range(4) is not the list [0,1,2,3]. To make it a list we need to use the␣ ↪function list() : [0, 1, 2, 3] Now notice the line for i in range(4). The for loop will take each of the numbers 0 through 3, and put it into the variable we’ve named i. This is the loop variable. You can see better what is going on if we collect the loop variable value in the for loop, instead of doing the coin toss: : variable_values = [] for i in range(4): variable_values.append(i) variable_values : [0, 1, 2, 3] We can see the same thing, if we call the print function at each iteration of the loop, to show the value of i. print displays the value as text. 5 : for i in range(4): # Show the value of i at each iteration of the loop print('Value of i is', i) Value of i is 0 Value of i is 1 Value of i is 2 Value of i is 3 Exercise: Use a for loop that releases all the even number from 0 to 10. : even_number = [] for i in range(0,11): if i%2 == 0: even_number.append(i) even_number : [0, 2, 4, 6, 8, 10] 2.2 The break and continue statements 1) The break statement gets us out of a loop. : number = 0 for number in range(10): if number == 5: break # break here print('Number is ' + str(number)) print('Out of loop') Number is 0 Number is 1 Number is 2 Number is 3 Number is 4 Out of loop 2) The continue statement gives you the option to skip over the part of a loop where an external condition is triggered, but to go on to complete the rest of the loop. That is, the current iteration of the loop will be disrupted, but the program will return to the top of the loop. : for number in range(10): if number == 5 or number == 8: continue # continue here print('Number is ' + str(number)) 6 print('Out of loop') Number is 0 Number is 1 Number is 2 Number is 3 Number is 4 Number is 6 Number is 7 Number is 9 Out of loop Exercise: Use the break and continue statements in the for loop above so that it prints 0,1,3,4,6,7. : for number in range(10): if number == 2 or number == 5: continue elif number == 8: break print('Number is ' + str(number)) print('Out of loop') Number is 0 Number is 1 Number is 3 Number is 4 Number is 6 Number is 7 Out of loop Exercise: Use a for loop together with an if and a continue statements so that it skips when iterator equals “sun” in the list weather=[“snow”, “rain”, “sun”, “clouds”]. : weather = ["snow", "rain", "sun", "clouds"] for i in weather: if i == "sun": continue print(i) snow rain clouds 7 2.3 Exercises Exercise: Construct a function that takes as input a list of numbers and return a list of the square of the numbers. : def square(list1): final_list = [] for i in list1: final_list.append(i**2) return final_list : list1 = [1, 2, 3] square(list1) : [1, 4, 9] Exercise: Display numbers from -10 to -1 using for loop : for i in range(-10, 0): print(i) -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 Exercise: What is doing the next code? : start = 25 end = 50 for num in range(start, end + 1): if num > 1: for i in range(2, num): if (num % i) == 0: break else: print(num) 29 31 37 41 8 43 47 Solution: This for loop finds all the prime numbers in the interval [star, end]. Exercise: Write a Python program to find numbers which are divisible by 7 and multiple of 5, between 1500 and 2700 (both included). How many of them did you find? Give the first five ones. : my_list = [] for x in range(1500, 2701): if x%7 == 0 and x%5 == 0: my_list.append(x) print(f'There are {len(my_list)} such numbers. Here are the first 5 ones') my_list[:5] There are 35 such numbers. Here are the first 5 ones : [1505, 1540, 1575, 1610, 1645] 2.4 Nested for Loops A nested loop has one loop inside of another. Imagine we wanted to write a program that prints each Domino Tile in a set: : for left in range(7): for right in range (left,7): print("["+ str(left)+"|"+str(right)+"]",end="\n") [0|0] [0|1] [0|2] [0|3] [0|4] [0|5] [0|6] [1|1] [1|2] [1|3] [1|4] [1|5] [1|6] [2|2] [2|3] [2|4] [2|5] [2|6] [3|3] [3|4] [3|5] 9 [3|6] [4|4] [4|5] [4|6] [5|5] [5|6] [6|6] Exercise: You are given three integers 𝑥, 𝑦 and 𝑧. Print all the pairs (𝑖, 𝑗) , such that (𝑖 + 𝑗) is equal to 𝑧 for all 𝑖 less than 𝑥 and 𝑗 less than 𝑦. [ ]: # initialise input variables x = 5 y = 4 z = 3 # initialise array for ordered pairs and counter arr = [] for i in range(x + 1): for j in range(y + 1): if i + j == z: arr.append([i, j]) print(arr) [[0, 3], [1, 2], [2, 1], [3, 0]] Exercise: Write a nested for loop program to print the multiplication table from 1 to 10. : for i in range(1, 11): for j in range(1, 11): if j != 10: print(i*j, end = ' ') # This write a space instead of a line break␣ ↪at the end of the print else: print(i*j) 1 2 3 4 5 6 7 8 9 10 2 4 6 8 10 12 14 16 18 20 3 6 9 12 15 18 21 24 27 30 4 8 12 16 20 24 28 32 36 40 5 10 15 20 25 30 35 40 45 50 6 12 18 24 30 36 42 48 54 60 7 14 21 28 35 42 49 56 63 70 8 16 24 32 40 48 56 64 72 80 9 18 27 36 45 54 63 72 81 90 10 20 30 40 50 60 70 80 90 100 10 2.4.1 List comprehension List comprehension offers a shorter syntax when you want to create a new list based on the values of an existing list. It mays also be used to save memory space. Example: Given a list of fruits, find all the fruits with an ‘a’ in its name. : fruits = ["apple", "banana", "cherry", "kiwi", "mango"] : #Without list comprehension newlist = [] for x in fruits: if "a" in x: newlist.append(x) print(newlist) ['apple', 'banana', 'mango'] : #With list comprehension you can do all that with only one line of code: newlist = [x for x in fruits if "a" in x ] print(newlist) ['apple', 'banana', 'mango'] : #Example: find all fruits except for 'apple' newlist = [x for x in fruits if x != "apple"] print(newlist) ['banana', 'cherry', 'kiwi', 'mango'] : #Example: write all fruits in upper case letters newlist = [x.upper() for x in fruits] print(newlist) ['APPLE', 'BANANA', 'CHERRY', 'KIWI', 'MANGO'] : #Example: replace "banana" by "orange" newlist = [x if x != "banana" else "orange" for x in fruits] print(newlist) ['apple', 'orange', 'cherry', 'kiwi', 'mango'] : #without list comprehension newlist = [] for x in fruits: if x == "banana": newlist.append("orange") 11 else: newlist.append(x) : print(newlist) ['apple', 'orange', 'cherry', 'kiwi', 'mango'] Construct a list which is the intersection of two lists : lis1, lis2 = list(range(2,8)), [2,6,7] : lis1, lis2 : ([2, 3, 4, 5, 6, 7], [2, 6, 7]) : lis3 = [x for x in lis1 for y in lis2 if x == y] lis3 : [2, 6, 7] An exercice on list comprehension: 1) Construct a list of all the letters in the string ‘myessec’ with and without list comprehension 2) Construct a list with all the letters in the string ‘myessec’ except for the letter ‘s’ 3) Construct a list with all the letters in the string ‘myessec’ where the letter ‘s’ is replaced by ‘S’ : #without list comprehension my_list = [] for x in 'myessec': my_list.append(x) #with list comprehension [x for x in 'myessec'] : ['m', 'y', 'e', 's', 's', 'e', 'c'] : [x for x in 'myessec' if x != 's'] : ['m', 'y', 'e', 'e', 'c'] : [x if x!='s' else 'S' for x in 'myessec'] : ['m', 'y', 'e', 'S', 'S', 'e', 'c'] 12

Use Quizgecko on...
Browser
Browser