Lists & Strings Brandon Krakowsky Lists Property of Penn Engineering | Lists - Review • If you recall, lists are a type of data structure in Python - Lists are the most common sequence - Lists are mutable, which means, once defined, the individual elements can be changed Property of Penn Engineering | 3 Lists - Review • If you recall, lists are a type of data structure in Python - Lists are the most common sequence - Lists are mutable, which means, once defined, the individual elements can be changed • To create a list, specify comma separated values, in between square brackets [] Property of Penn Engineering | 4 Lists - Review • If you recall, lists are a type of data structure in Python - Lists are the most common sequence - Lists are mutable, which means, once defined, the individual elements can be changed • To create a list, specify comma separated values, in between square brackets [] • Values included do not need to be all of the same type Property of Penn Engineering | 5 Lists - Review • If you recall, lists are a type of data structure in Python - Lists are the most common sequence - Lists are mutable, which means, once defined, the individual elements can be changed • To create a list, specify comma separated values, in between square brackets [] • Values included do not need to be all of the same type • Each list item is assigned an index value, starting at 0 list1 = [‘1’, ‘dog’, ‘cat’, 789] print(list1) print(len(list1)) #get the length of a list print(list1[1]) #get the 2nd item in the list print(list1[4]) #get the 5th item in the list – doesn’t exist! Property of Penn Engineering | 6 Lists - Review • If you recall, lists are a type of data structure in Python - Lists are the most common sequence - Lists are mutable, which means, once defined, the individual elements can be changed • To create a list, specify comma separated values, in between square brackets [] • Values included do not need to be all of the same type • Each list item is assigned an index value, starting at 0 list1 = [‘1’, ‘dog’, ‘cat’, 789] print(list1) print(len(list1)) #get the length of a list print(list1[1]) #get the 2nd item in the list print(list1[4]) #get the 5th item in the list – doesn’t exist! • You can look up the index of a value using the built-in list index method print(list1.index('dog’)) Property of Penn Engineering | 7 Lists - Review • You can add items to a list list1.append(“hello”) Property of Penn Engineering | 8 Lists - Review • You can add items to a list list1.append(“hello”) • Get the length of a list print(len(list1)) Property of Penn Engineering | 9 Lists - Review • You can add items to a list list1.append(“hello”) • Get the length of a list print(len(list1)) • Remove items from a list list1.pop() #removes the last item in the list print(list1) list1.pop(1) #removes the 2nd item in the list print(list1) Property of Penn Engineering | 10 Lists - Review • You can add items to a list list1.append(“hello”) • Get the length of a list print(len(list1)) • Remove items from a list list1.pop() #removes the last item in the list print(list1) list1.pop(1) #removes the 2nd item in the list print(list1) • Insert an item at a specific location in a list list1.insert(2, 'inserted item’) #insert at 3rd location print(list1) Property of Penn Engineering | 11 Lists - Review • You can add items to a list list1.append(“hello”) • Get the length of a list print(len(list1)) • Remove items from a list list1.pop() #removes the last item in the list print(list1) list1.pop(1) #removes the 2nd item in the list print(list1) • Insert an item at a specific location in a list list1.insert(2, 'inserted item’) #insert at 3rd location print(list1) • Check if an item is in a list print(‘dog’ in list1) Property of Penn Engineering | 12 Lists - More Operations • You can add lists ls1 = [2, 3, 4] ls2 = [7, 8, 9] ls3 = ls1 + ls2 print(ls3) - This creates a new list ls3 with the values of ls2 appended to the end of ls1, i.e. [2, 3, 4, 7, 8, 9] Property of Penn Engineering | 13 Lists - More Operations • You can add lists ls1 = [2, 3, 4] ls2 = [7, 8, 9] ls3 = ls1 + ls2 print(ls3) - This creates a new list ls3 with the values of ls2 appended to the end of ls1, i.e. [2, 3, 4, 7, 8, 9] • And multiply lists ls4 = ls3 * 3 print(ls4) - This creates a new list ls4 with the values of ls3 repeated three times, i.e. [2, 3, 4, 7, 8, 9, 2, 3, 4, 7, 8, 9, 2, 3, 4, 7, 8, 9] Property of Penn Engineering | 14 Lists - More Functions • You can extend lists using the extend function ls1.extend(ls2) - This is similar to adding lists, except it will actually update ls1 and append the values of ls2 to the end of ls1 Property of Penn Engineering | 15 Lists - More Functions • You can extend lists using the extend function ls1.extend(ls2) - This is similar to adding lists, except it will actually update ls1 and append the values of ls2 to the end of ls1 • Iterate over the elements of updated ls1 to see it’s been updated for i in ls1: print(i) #prints each element of the list Property of Penn Engineering | 16 Assignment by Value • How are variables assigned in Python? • For simple values (e.g. integers, floats, booleans, etc.), variables are assigned by value a=5 b = a #copies the value a=a+1 print(a) #6 print(b) #5 - a stores the value 6 - b stores the value 5 Property of Penn Engineering | 17 Assignment by Reference • For more complex types (e.g. lists, strings, etc.), variables are assigned by reference - This is equivalent to the concept of pointers in C a = [1, 2, 3] b = a #copies the reference a[1] = 5 print(a) #[1, 5, 3] print(b) #[1, 5, 3] - a stores a reference to object [1, 5, 3] - b stores a reference to the same object [1, 5, 3] Property of Penn Engineering | 18 Assignment by Reference • How do you make a true copy of a list? lst1 = [1, 2, -1] Property of Penn Engineering | 19 Assignment by Reference • How do you make a true copy of a list? lst1 = [1, 2, -1] • This DOES NOT COPY lst1 to lst2 lst2 = lst1 #lst1 and lst2 store references to the same list [1, 2, -1] Property of Penn Engineering | 20 Assignment by Reference • How do you make a true copy of a list? lst1 = [1, 2, -1] • This DOES NOT COPY lst1 to lst2 lst2 = lst1 #lst1 and lst2 store references to the same list [1, 2, -1] • This DOES COPY lst1 to lst3 using the copy method lst3 = lst1.copy() #lst1 and lst3 store references to different lists Property of Penn Engineering | 21 Assignment by Reference • How do you make a true copy of a list? lst1 = [1, 2, -1] • This DOES NOT COPY lst1 to lst2 lst2 = lst1 #lst1 and lst2 store references to the same list [1, 2, -1] • This DOES COPY lst1 to lst3 using the copy method lst3 = lst1.copy() #lst1 and lst3 store references to different lists • How do we know? lst1[0] = 2 #update original list print(lst1) #print original list print(lst2) #print new reference to same list print(lst3) #print new reference to different list Property of Penn Engineering | 22 Assignment by Reference • You can also iterate over a list and copy the values to a new list this way lst4 = [] for i in lst1: lst4.append(i) Property of Penn Engineering | 23 Assignment by Reference • You can also iterate over a list and copy the values to a new list this way lst4 = [] for i in lst1: lst4.append(i) • Or more concisely using a list comprehension lst5 = [i for i in lst1] Property of Penn Engineering | 24 Assignment by Reference • You can also iterate over a list and copy the values to a new list this way lst4 = [] for i in lst1: lst4.append(i) • Or more concisely using a list comprehension lst5 = [i for i in lst1] • How do we know? print(lst4) #print new reference to different list print(lst5) #print new reference to different list Property of Penn Engineering | 25 Assignment by Reference • What if our list is more complex? complex_lst = [1, [2, 3], -1] • Perform a deep copy import copy complex_lst2 = copy.deepcopy(complex_lst) Property of Penn Engineering | 26 Assignment by Reference • What if our list is more complex? complex_lst = [1, [2, 3], -1] • Perform a deep copy import copy complex_lst2 = copy.deepcopy(complex_lst) • Update the original list complex_lst[1][1] = 4 Property of Penn Engineering | 27 Assignment by Reference • What if our list is more complex? complex_lst = [1, [2, 3], -1] • Perform a deep copy import copy complex_lst2 = copy.deepcopy(complex_lst) • Update the original list complex_lst[1][1] = 4 • Print results print(complex_lst) #print original list print(complex_lst2) #print new reference to different list Property of Penn Engineering | 28 Call by Value • When we call a function, simple values (e.g. integers, floats, booleans, etc.) are passed by value • When you pass variables with simple values as arguments to a function, the values themselves are put into the function parameters • If the parameters are changed within the function (which isn’t good style), new local variables are created • The changes are not put back into the original arguments def alter(x): x = x + 1 #does not affect a a=5 print(a) #5 alter(a) print(a) #still 5 - a stores value 5 and x stores value 6 Property of Penn Engineering | 29 Call by Reference • When we call a function, complex types (e.g. lists, strings, etc.) are passed by reference • When you pass variables with more complex types as arguments to a function, the arguments become references to the objects def alter(x): x[1] = 99 #changes contents of b x = [4, 5, 6] #BUT, you can’t change the original reference, so this creates new local variable x and does not affect b b = [1, 2, 3] print(b) #[1, 2, 3] alter(b) print(b) #[1, 99, 3] - b stores a reference to [1, 99, 3] and x stores the same reference to [1, 99, 3] Property of Penn Engineering | 30 Identity vs. Equality • How can we compare two variables? • Use the identity testing operator “is” if you want to ensure that two variables hold references to the same object a = [1, 2, 3] b=a print(a is b) #True Property of Penn Engineering | 31 Identity vs. Equality • How can we compare two variables? • Use the identity testing operator “is” if you want to ensure that two variables hold references to the same object a = [1, 2, 3] b=a print(a is b) #True • Use the “==“ operator if you want to ensure that two variables have the same value (even if they are not the same object) print(a == b) #True Property of Penn Engineering | 32 Identity vs. Equality • How can we compare two variables? • Use the identity testing operator “is” if you want to ensure that two variables hold references to the same object a = [1, 2, 3] b=a print(a is b) #True • Use the “==“ operator if you want to ensure that two variables have the same value (even if they are not the same object) print(a == b) #True • a is b implies a == b, but not necessarily the other way around! Property of Penn Engineering | 33 Identity vs. Equality • How can we compare two variables? • Use the identity testing operator “is” if you want to ensure that two variables hold references to the same object a = [1, 2, 3] b=a print(a is b) #True • Use the “==“ operator if you want to ensure that two variables have the same value (even if they are not the same object) print(a == b) #True • a is b implies a == b, but not necessarily the other way around! • What happens if we update a? a[2] = 5 print(a is b) print(a == b) Property of Penn Engineering | 34 Lists – Exercise • Here’s a sneaky_list function that accepts 2 list parameters. The function does some very “sneaky” things with those lists. def sneaky_list(lst1, lst2): lst1 = lst2 #creates new local variable lst1 and points to value of lst2 lst1.append(7) #appends to new local lst1 lst2.append(5) #appends to lst2 print(lst1 is lst2) #do they hold references to same list? print(lst1 == lst2) #do they have the same value? Property of Penn Engineering | 35 Lists – Exercise • Calling the sneaky_list function shows interesting results. Let’s see what happens! def main(): lst_one = [1, 2, -1] lst_two = [7, 8, -4] sneaky_list(lst_one, lst_two) print(lst_one) #what does lst_one contain now? print(lst_two) #and lst_two? #program entry point if __name__ == '__main__’: main() Property of Penn Engineering | 36 Lists - Slice • You can get a slice of a list by using a colon (:) • Format: [start_index:end_index] • start_index and end_index are both optional • start_index is the index of the first value (included in slice) • end_index is the index of the last value (not included in slice) my_list = [‘b’, ‘a’, ’n’, ‘a’, ’n’, ‘a’, ’s’] Property of Penn Engineering | 37 Lists - Slice • You can get a slice of a list by using a colon (:) • Format: [start_index:end_index] • start_index and end_index are both optional • start_index is the index of the first value (included in slice) • end_index is the index of the last value (not included in slice) my_list = [‘b’, ‘a’, ’n’, ‘a’, ’n’, ‘a’, ’s’] • Get elements from index 2 to 4 print(my_list[2:5]) #returns slice with elements 3 to 5 Property of Penn Engineering | 38 Lists - Slice • You can get a slice of a list by using a colon (:) • Format: [start_index:end_index] • start_index and end_index are both optional • start_index is the index of the first value (included in slice) • end_index is the index of the last value (not included in slice) my_list = [‘b’, ‘a’, ’n’, ‘a’, ’n’, ‘a’, ’s’] • Get elements from index 2 to 4 print(my_list[2:5]) #returns slice with elements 3 to 5 • Get elements from index 4 to end print(my_list[4:]) #returns slice with elements 5 to end Property of Penn Engineering | 39 Lists - Slice • Get elements from index 0 to end (entire list!) print(my_list[:]) #returns slice with elements 1 to end Property of Penn Engineering | 40 Lists - Slice • Get elements from index 0 to end (entire list!) print(my_list[:]) #returns slice with elements 1 to end • Get elements from index 0 to -4 (counts from right to left) print(my_list[:-4]) #returns slice with elements from 1 to 3 Property of Penn Engineering | 41 Lists - Slice • Get elements from index 0 to end (entire list!) print(my_list[:]) #returns slice with elements 1 to end • Get elements from index 0 to -4 (counts from right to left) print(my_list[:-4]) #returns slice with elements from 1 to 3 • Another way to copy a list copy_my_list = my_list[:] #creates new list from slice with elements 1 to end print(copy_my_list) Property of Penn Engineering | 42 Lists - Slice • Get elements from index 0 to end (entire list!) print(my_list[:]) #returns slice with elements 1 to end • Get elements from index 0 to -4 (counts from right to left) print(my_list[:-4]) #returns slice with elements from 1 to 3 • Another way to copy a list copy_my_list = my_list[:] #creates new list from slice with elements 1 to end print(copy_my_list) • Let’s test it print(copy_my_list is my_list) #same references? print(copy_my_list == my_list) #same values? Property of Penn Engineering | 43 Lists – Slice • You can also update list elements by specifying an index or slice • Here we have a list of odd numbers odd_numbers = [2, 4, 6, 8] • wait … what? Let’s make some changes! Property of Penn Engineering | 44 Lists – Slice • You can also update list elements by specifying an index or slice • Here we have a list of odd numbers odd_numbers = [2, 4, 6, 8] • wait … what? Let’s make some changes! • Of course, we can update (a single) element at index 0 odd_numbers[0] = 1 print(odd_numbers) #should output [1, 4, 6, 8] Property of Penn Engineering | 45 Lists – Slice • You can also update list elements by specifying an index or slice • Here we have a list of odd numbers odd_numbers = [2, 4, 6, 8] • wait … what? Let’s make some changes! • Of course, we can update (a single) element at index 0 odd_numbers[0] = 1 print(odd_numbers) #should output [1, 4, 6, 8] • We can also update (multiple) elements from index 1 to 3 odd_numbers[1:4] = [3, 5, 7] print(odd_numbers) #should output [1, 3, 5, 7] • Note: index 4 doesn’t exist in the list. Python doesn’t care! Property of Penn Engineering | 46 Strings Property of Penn Engineering | 47 Strings • A string is a sequence of characters Property of Penn Engineering | 48 Strings • A string is a sequence of characters • A string is kind of like a list – just imagine a string as a list of characters! Property of Penn Engineering | 49 Strings • A string is a sequence of characters • A string is kind of like a list – just imagine a string as a list of characters! • Unlike lists, strings are immutable, which means, once defined, you cannot change the individual elements (characters) of a string Property of Penn Engineering | 50 Strings • A string is a sequence of characters • A string is kind of like a list – just imagine a string as a list of characters! • Unlike lists, strings are immutable, which means, once defined, you cannot change the individual elements (characters) of a string • For example, if we have a list: my_menu_choices = [‘burger’, ‘fries’, ‘coke’] Property of Penn Engineering | 51 Strings • A string is a sequence of characters • A string is kind of like a list – just imagine a string as a list of characters! • Unlike lists, strings are immutable, which means, once defined, you cannot change the individual elements (characters) of a string • For example, if we have a list: my_menu_choices = [‘burger’, ‘fries’, ‘coke’] • We can get a single value: main_course = my_menu_choices[0] Property of Penn Engineering | 52 Strings • A string is a sequence of characters • A string is kind of like a list – just imagine a string as a list of characters! • Unlike lists, strings are immutable, which means, once defined, you cannot change the individual elements (characters) of a string • For example, if we have a list: my_menu_choices = [‘burger’, ‘fries’, ‘coke’] • We can get a single value: main_course = my_menu_choices[0] • We can also update a single value: my_menu_choices[0] = ‘cheese burger’ Property of Penn Engineering | 53 Strings • However, if we have a string: my_restaurant_choice = ‘Mcdonalds’ Property of Penn Engineering | 54 Strings • However, if we have a string: my_restaurant_choice = ‘Mcdonalds’ • We CAN get a single value (character): my_restaurant_choice_third_letter = my_restaurant_choice[2] Property of Penn Engineering | 55 Strings • However, if we have a string: my_restaurant_choice = ‘Mcdonalds’ • We CAN get a single value (character): my_restaurant_choice_third_letter = my_restaurant_choice[2] • But we CAN’T directly update a single value (character) – this won’t work: my_restaurant_choice[2] = ‘D’ - You will get an error because strings are immutable Property of Penn Engineering | 56 Slicing Strings • Like a list, we can get a slice from a string! • This is called a substring • Use the same colon (:) syntax Property of Penn Engineering | 57 Slicing Strings • Like a list, we can get a slice from a string! • This is called a substring • Use the same colon (:) syntax • Format: [start_index:end_index] • start_index is the index of the first value (included in slice) • end_index is the index of the last value (not included in slice) s = ‘Hello world!’ • Get characters from index 0 to 5 print(s[:5]) #returns substring with characters 1 to 5 Property of Penn Engineering | 58 Slicing Strings - Exercise • Set a variable name to the value of your first and last name • Print the substring containing just your first name, without counting the letters in your first name • Hint: Use the built-in string index method to locate the space name = 'Brandon Krakowsky’ first_space = name.index(' ') #get the index of the first space in the string print(name[0:first_space]) #use the first_space index when getting the substring Property of Penn Engineering | 59 Slicing Strings - Exercise • Write code to print the 3rd to the 16th letters of the alphabet Property of Penn Engineering | 60 Slicing Strings - Exercise • Write code to print the 3rd to the 16th letters of the alphabet • First, import the string module, to gain access to additional useful string methods import string • Then you can use the following variable to get all lowercase letters alphabet = string.ascii_lowercase Property of Penn Engineering | 61 Slicing Strings - Exercise • Write code to print the 3rd to the 16th letters of the alphabet • First, import the string module, to gain access to additional useful string methods import string • Then you can use the following variable to get all lowercase letters alphabet = string.ascii_lowercase • alphabet is a string print(type(alphabet)) • Print the new string by slicing the 3rd to the 16th letters print(alphabet[2:16]) Property of Penn Engineering | 62 Some String Functions • Here are some useful built-in string methods: • string.capitalize() – capitalizes first letter of string • string.startswith(prefix) – determines if string starts with prefix • string.endswith(suffix) – determines if string ends with suffix • string.isupper() – determines if all characters in the string are uppercase • string.islower() – determines if all characters in the string are lowercase • string.find(str) – determines if str occurs in string • string.index(str) – determines index of str in string • string.replace(old, new) – replaces all occurrences of old in string with new • string.strip() – trims whitespace from beginning and end of string • string.upper() - returns uppercased string from given string • string.lower() - returns lowercased string from given string • All strings have these built-in methods! For reference: https://docs.python.org/3/library/stdtypes.html#string-methods Property of Penn Engineering | 63 Some String Functions • split is a useful string method used to split a single string into a list of multiple strings colors = 'blue,red,green’ colors_list = colors.split(‘,’) #splits string into list of strings using comma separator print(colors_list) print(colors_list[2]) Property of Penn Engineering | 64 Some String Functions • split is a useful string method used to split a single string into a list of multiple strings colors = 'blue,red,green’ colors_list = colors.split(‘,’) #splits string into list of strings using comma separator print(colors_list) print(colors_list[2]) • Conversely, join creates a single string from a list of multiple strings separator = ‘,’ new_colors = separator.join(colors_list) #joins list of strings using separator value print(new_colors) Property of Penn Engineering | 65 Some String Functions • In a previous example, we tried to update a character in a string – this wouldn’t work: my_restaurant_choice = ‘Mcdonalds’ my_restaurant_choice[2] = ‘D’ Property of Penn Engineering | 66 Some String Functions • In a previous example, we tried to update a character in a string – this wouldn’t work: my_restaurant_choice = ‘Mcdonalds’ my_restaurant_choice[2] = ‘D’ • We CAN first convert the string to an actual list - Note: Calling the split function with an empty string (‘’) will throw an error – so this won’t work my_restaurant_choice_list = my_restaurant_choice.split(‘’) - Instead, use Python’s built-in list function to convert the string to a list my_restaurant_choice_list = list(my_restaurant_choice) Property of Penn Engineering | 67 Some String Functions • In a previous example, we tried to update a character in a string – this wouldn’t work: my_restaurant_choice = ‘Mcdonalds’ my_restaurant_choice[2] = ‘D’ • We CAN first convert the string to an actual list - Note: Calling the split function with an empty string (‘’) will throw an error – so this won’t work: my_restaurant_choice_list = my_restaurant_choice.split(‘’) - Instead, use Python’s built-in list function to convert the string to a list my_restaurant_choice_list = list(my_restaurant_choice) • Now we can update the third letter my_restaurant_choice_list[2] = ‘D’ Property of Penn Engineering | 68 Some String Functions • In a previous example, we tried to update a character in a string – this wouldn’t work: my_restaurant_choice = ‘Mcdonalds’ my_restaurant_choice[2] = ‘D’ • We CAN first convert the string to an actual list - Note: Calling the split function with an empty string (‘’) will throw an error – so this won’t work: my_restaurant_choice_list = my_restaurant_choice.split(‘’) - Instead, use Python’s built-in list function to convert the string to a list my_restaurant_choice_list = list(my_restaurant_choice) • Now we can update the third letter my_restaurant_choice_list[2] = ‘D’ • Then convert back to a string using join my_restaurant_choice = ‘’.join(my_restaurant_choice_list) Property of Penn Engineering | 69