title

Tasks

  1. Complete reading this lesson, which involves the following:
    1. Introduction
    2. Loops for list manipulation
    3. Slicing
    4. Copying and passing lists
    5. Built-in methods
  2. Complete quiz 7 to verify your reading and understanding.
  3. Read and complete the activities at Zybook, Z8: Lists.

Learning Outcomes

By the end of this lesson, you should be able to:

  1. Explain the use of lists in programming.
  2. Discuss the implementation of lists in Python programming.
  3. Modify lists using loops.
  4. Use slicing to retrieve data from lists.
  5. Design programs that can pass lists between functions.

Key Terms/Concepts

Introduction

A list object is a container that groups together data. Up until now, you have assigned a single value to a variable. A single container on the other hand can be used to store multiple values. For example, consider a customer's address that we need to store. The house number, street name, city, and postal code belong together. Rather than using four separate variables, we can use a single list to store it. Values with different datatypes can be combined in one list.

Similarly, we can use lists where we have a lot of data. If we are designing a program to store marks of 100 students and find the average and maximum score in a class, it is much more efficient and easier to work with a single list rather than 100 variables.

A list is a sequence as well. This means that each data element has a unique position (called index) in the list, and it can be accessed using its index. Two lists are shown below. The first list is named got_address and contains a home address, whereas the second list contains student marks and is called final_marks.

got_address:

0 1 2 3 4
13 “Univ Avenue” “Kings Landing” 44000 “Westeros”

final_marks:

0 1 2 3 4 5 6 7 8
70 40 30.5 22.5 80 90 90 99 67

The top row in each list shows the index of each data element, whereas the bottom row has the actual data values. An index is always an integer. got_address combines two integers and three strings in the same list. final_marks has a combination of integers and floats. The first element of a list is always at index number 0.

Index positions always start from 0, so the nth element of the list will be at index position (n-1).

Technical Note:

The counting starts at one (NOT zero) when determining the length of a list. A list with 100 (length) elements will have its first element at index 0 and the last element is at index 99 (length -1). A list whose last element is at index 43 will have a length of 44 (index of last item + 1).

Index numbers cannot be skipped. They will always start from 0 and increment by 1 from one element to the next.

Technical Note:

Lists are similar to Arrays in other programming languages like C and Java.

Reverse Indexing

Every list has forward indexing as well as reverse indexing. The last example depicted forward indexing, which started from zero. Reverse indexing uses negative integers to specify element position. The last element of a list is at index -1, and the first element is at index -length. As we will see later, reverse indexing is useful to access the last element of the list or the last n elements of the list.

Technical Note:

Reverse indexing does not start from zero but rather from - It is understandable that only one of the indexing schemes can have zero as an index position or otherwise it might result in confusion.

The following example shows forward and reverse indexing for a list. The first row shows reverse indexing and the second row shows forward indexing. The length of the list final_marks remains 9.

final_marks:

-9 -8 -7 -6 -5 -4 -3 -2 -1
0 1 2 3 4 5 6 7 8
70 40 30.5 22.5 80 90 90 99 67

8.2.1 Creating and Accessing lists

Lists are mutable. Mutable objects can be changed without changing the identity. They can grow and shrink as the elements are modified, added, and deleted. Python uses square brackets for accessing elements through indexes. Prog 8-01 in Console Listing 1 shows a demo of creating lists and accessing and modifying the elements through forward and reverse indexing.

Technical Note:

Strings, integers, floats etc are immutable objects. For example, if you change the value of an integer in a program, Python generates a new integer internally with the same name. The first line of code below creates a variable called temp and assigns an integer to it. The second line is apparently changing the value of the same variable, but Python is actually creating a new variable with the same name as the first variable and assigns it a new value.

temp = 30

temp = 50


 # Program Name: Prog 8-01
 # This program is part of Lesson 08 of the course 
  
 def main ():
        final_marks = [70, 40, 30, 22, 80, 90, 90, 99, 67]
    
        got_address = [13, 'Univ Avenue', 'Kings Landing', 44000, 'Westeros']
  
        print(f"Number of students: {len(final_marks)}")
        length_got = len(got_address)
        print(f"Lenth of address: {length_got}")
  
        final_marks[2] = 30.5
    final_marks[3] = 22.5

    got_address[2] = "White Harbour"
    got_address[length_got - 1] = "North"
    got_address[-1] = "The North"
    got_address[-length_got] = 100
 
    print(f"Final marks: {final_marks}")
    print("\nAddress:")
    print(f'{got_address[-length_got]} {got_address[1]},')
    print(f'{got_address[2]}, {got_address[3]},')
    print(f'{got_address[-1]}')

main()

Code Listing 1: Prog 8-01 shows the creation of lists and modification of elements through forward and reverse indexing.

Let's go through the source code line by line.

Lines 5, 7 Two lists are created in each of the lines. The syntax for creating a list begins with an identifier (list name) followed by an assignment operator. Square brackets [ ] are used to denote a list on the right of the assignment operator. All the elements of a list are inside the square brackets, and commas are used to separate elements. An empty list can be created using the following line of code:
my_list = []
Line 9 The built-in len function can be used to get the length of a list. The length of final_marks is printed as 9.
Lines 10, 11 The length of got_address is returned by the len function, and it is assigned to the variable length_got. The length is printed on the console.
Lines 13, 14 Two elements for final_marks are being updated. The value of the third element of final_marks, which is at index 2, is 30. This value needs to be updated to 30.5. Line 13 shows the syntax to update an element. List name is followed by two square brackets, and the index number of the element that needs to be updated between the brackets are required. The element at index 3 (fourth element) is updated to 22.5 in the next line.
Lines 16, 17 Two elements of got_address are updated using forward indexing. The third element is updated to White Harbour and the last element is changed to North. In forward indexing, the last element of a list is always one less than the total length of the list.
Lines 18, 19 Two elements of got_address are updated using reverse indexing. Indexing starts from right to left in reverse indexing and the last element of the list (right most) is always -1. The first element in reverse indexing is always minus length (- length). The last element is set to The North and the first one is changed to 100.
Line 21 The entire final_marks list is printed on a single line in the console. Square brackets are displayed in the output to show that it is a list.
Line 22 An empty line and Address: is printed.

Repetition and Concatenation

A list can be repeated, and multiple lists can be concatenated using asterisk (*) and plus (+) symbols respectively. Python executes differently if the operands are numbers compared to when they are lists. Prog 8-02 in Code Listing 2 shows list repetition and concatenation.


 # Program Name: Prog 8-02
 # This program is part of Lesson 08 of the course 
  
 def main ():
        group1_marks_q1 = [151, 140, 130]
        bonus_marks = [2] * 3
  
        group1_marks_q1[0] = group1_marks_q1[0] + bonus_marks[0]
        group1_marks_q1[1] = group1_marks_q1[1] + bonus_marks[1]
        group1_marks_q1[2] = group1_marks_q1[2] + bonus_marks[2]
  
        print("Course CP999 data:")
        print(f"Group 1 marks in Quiz 1: {group1_marks_q1}")

    group1_marks_q2 = [190, 190, 30.5]
    group1_marks = group1_marks_q1 + group1_marks_q2

    group1_student_id = [123, 124, 125]
    group1_student_id = group1_student_id * 2
 
    print()
    print(f"Student ID:\t\t{group1_student_id}")
    print(f"Quiz 1 and 2 marks:\t{group1_marks}")

main()

Code Listing 2: Prog 8-02 shows the use of plus and asterisk symbols on lists.

Prog 8-02 displays the marks of two quizzes for the three students enrolled in CP999. Each of the three students is given two bonus marks in quiz 1 as well.

Line 5 A list is created which contains the quiz 1 marks of the three students enrolled in a course.
Line 6 All students deserve two bonus marks for their performance. Two marks can be added easily using loops, but for demonstration purposes we will create a list of 2's and add it to the marks in group1_marks_q1. Creating a list with a single element and multiplying it by 3 will repeat the list thrice.
The output of line 6 looks like:
[2, 2, 2]
Line 8 We add the first element of group1_marks_q1 (marks of the first student in quiz 1) with the first element of bonus_marks.
Lines 9, 10 Adding 2 marks to the quiz1 scores of the second and the third student.
Line 12 Printing Course CP999 data:
Line 13 The updated marks of quiz 1 are displayed on the console.
Line 15 Marks scored by the three students in quiz 2 are stored in a list named group1_marks_q2.
Line 16 A plus symbol is used to concatenate (not add) the two lists into one and store the new list. group1_marks looks like:
[153, 142, 132, 190, 190, 30.5]
The marks at index 0 and index 3 store the quiz 1 and quiz 2 scores of the first student and so on.
Lines 18, 19 Student ids are stored in a list named group1_student_id. Asterisk is used to repeat the list once so that student ids exist twice.
Lines 21 - 23 Student Ids and marks in the quizzes are printed on the console.

The output of the program is shown in Console 2. The last two lines of the output show student Ids and below the Id are the marks of the respective pupils.


Course CP999 data:
Group 1 marks in Quiz 1: [153, 142, 132]

Student ID:     [123, 124, 125, 123, 124, 125]
Quiz 1 and 2 marks: [153, 142, 132, 190, 190, 30.5]

Console 2: Output for Prog 8-02.

Loops and Lists

Loops are ideally suited to process and manipulate the data in lists. Consider a list containing sales data for a thousand days. We have a list of a thousand floats, and we want to find out how many days the sales were below a given threshold. A Python program can perform this efficiently using loops. A loop will iterate over the list, element by element, and count the number of values which are below the threshold.

8.4.1 While Loops

We have worked with while loops before, so we will jump to a code example right away. Prog 8-03 has a list containing students' data. Each student has the following information recorded in the list:

  1. Name
  2. Score in course 1
  3. Score in course 2

Data for all the students is concatenated in a single list like below. Cathy scored 84 in course 1 and 77 in course 2.

Harris 80 90 Maria 90 99 Cathy 84 77
An image of Principal Skinner from The Simpsons
Figure 1. A school principal.  Retrieved from https://pixabay.com/. Free for commercial use.

The School principal is interested to know the average marks in each of the two courses. Code Listing 3 shows the source code of the program.

There are two loops in the program.

The first loop displays the full raw data. Data is displayed on the console, with each student in a separate row.

The second loop calculates the average score in each of the two subjects. A single loop is used to calculate averages for both the courses.

The program will function properly only if the following requirements are met:

  1. Students marks are integers or floats.
  2. Each student has name and marks in two subjects listed, i.e. three elements per student.
  3. Marks for course 1 are mentioned before marks for course 2.
  4. Student data is concatenated together one after the other without interleaving.

 # Program Name: Prog 8-03
 # This program is part of Lesson 08 of the course 
  
 def main ():
        st_data = ["Harris", 80, 90, "Maria", 90, 99, "Cathy", 84, 77]
        no_students = len(st_data)  / 3
  
        count = 0
        print("Raw Data: ")
        while count < len(st_data):
            print (f"{st_data[count]}", end = ' ')
            if ((count + 1) % 3 == 0):
                print()
            count += 1

    print()

    count = 1
    total_course_1 = 0
        total_course_2 = 0

    while (count < len(st_data)):
        total_course_1 += st_data[count]
        total_course_2 += st_data[count + 1]
        count += 3

    av_course_1 = total_course_1 / no_students
    av_course_2 = total_course_2 / no_students

30.         print(f"Course 1 Average: {av_course_1:.2f}")
3       print(f"Course 2 Average: {av_course_2:.2f}")
3  
3 main()

Code Listing 3: Processing student data.
Line 5 Student data is stored in st_data. Data is structured as described previously.
Line 6 As the data for each student consists of three elements, the total number of students in the list can be calculated by dividing the length of st_data by 3.
Line 8 The Loop variable is set to 0, as the list indexing begins with zero.
Line 9 Raw Data: is printed on the console.
Lines 10, 14 A simple while loop starts iterating with count = 0 and continues until the value of count is less than the length of the list. The index of the last element of a list is one less than the length of the list.
The value of count is incremented by 1 inside the loop body.
Line 11 Prints one element of the list pointed by the value of the count. A new line is not started, as we want to display all the data of a student in a single line.
Lines 12, 13 A new line is started on the console only when we have displayed three elements from the list. The count points to index position and therefore to evaluate if three elements have been processed, count + 1 is used in line 12.
Lines 16 - 20 An empty line is printed on the console, and three variables are initialized. As student name is not important for calculating course averages, the loop variable is initialized to 1.
Lines 22, 25 The while loop begins execution and iterates as long as the value of count is less than the length of st_data. The value of count is incremented by three in each iteration of the loop. It seems like the right thing to do, as the value of count will always point to the index position that contains score for course 1 in the list st_data. The values of the count will be:
1, 4, 7, …
Line 23 The value at the index pointed by the variable count is added to the total_course_1.
Line 24 We know from the structure of the data that score of course 2 is always stored right after the marks of course 1. count + 1 is used to access the marks of course 2 and add it to total_course_2.
Lines 27 - 31 Average for both the courses is computed by dividing the total in each course with the number of students. Both the averages are then printed on the console.

The output of the program is shown in Console 3.


Raw Data: 
Harris 80 90 
Maria 90 99 
Cathy 84 77 

Course 1 Average: 84.67
Course 2 Average: 88.67

Console 3: Output for Prog 8-03.

8.4.2 For Loops

For loops are designed for iterating over containers. In comparison to while loops, you will see the iterations are simpler to manage using for loops, but on the other hand the control over the iterations is limited as well. Prog 8-04 in Code Listing 4 shows a program with four for loops. The first and the fourth loops iterate over the indexes of the list, whereas the second and the third loops iterate over the values in the list.

In this program we have three lists:

  1. A list with the names of the weekdays in a short form.
  2. A list with high temperatures for each day of the week.
  3. A list with low temperatures for each day of the week.

The name of a weekday and its corresponding high and low temperatures are all stored at the same index position in every list. The program calculates and prints the following information on the console:

  1. A table with the weekdays, high and low temperatures for each day. This is achieved in the first for loop, which iterates over the index positions.
  2. Average high temperature of the week. It is calculated using a for loop (second loop in the program). The for loop iterates over the values of high_temperatures.
  3. Average low temperature of the week. It is calculated using a for loop (third loop in the program) and it iterates over the values of low_temperatures.
  4. A table with weekdays and an approximate average temperature of each day is computed and printed. A for loop is used, which iterates over the indexes of the three lists.

 # Program Name: Prog 8-04
 # This program is part of Lesson 08 of the course 
  
 def main ():
        days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
        high_temperatures = [35, 30, 32, 40, 28, 29, 29]
        low_temperatures = [8, 7, 7, 0, 1, -1, 5]
  
        print("Daily High and Low Temperatures")
        print (f"{'Day'}\t{'High'}\t{'Low'}")
        for idx in range(len(days)):
            print(f"{days[idx]}\t{high_temperatures[idx]}\t{low_temperatures[idx]}")
        print()

    total_high = 0
    for val in high_temperatures:
        total_high += val
    print(f"Average High:\t{total_high / 7:.1f}")

        total_low = 0
    for val in low_temperatures:
        total_low += val
    print(f"Average Low:\t{total_low / 7:.1f}")

    print("\nDaily Averages")
    print (f"{'Day'}\t{'Average'}")
    for idx in range(len(days)):
        avg = (high_temperatures[idx] + low_temperatures[idx]) / 2
        print(f"{days[idx]}\t{avg}")
30.  
3 main()


Code Listing 4: Prog 8-04

First, let's go over the code in lines 5 to 7 and lines 15 to 23.

Line 5 Initializes a list with names of the weekdays.
Line 6 Initializes a list containing the high temperature for each day.
Line 7 Initializes a list containing the low temperature for each day.
Line 15 A variable named high_total is initialized with zero. This variable will be used to calculate the sum of all the high temperatures in the week.
Line 16 A for loop starts execution. val is the target variable. high_temperatures is the name of the list being processed in this for loop.
  • The loop will iterate as many times as the number of elements in the list (high_temperatures).
  • One value from the list will be assigned to val in each iteration.
For the first iteration, value of val will be 35, in the second iteration it will be 30, then 32 and so on.
Line 17 The current value of val is added to the high_total. All the values in the loop will be assigned to val in sequence, and at the end of the loop high_total will contain the sum of all the elements.
Line 18 The average of the high_temperatures is calculated and displayed to the user.
Lines 20 - 23 The third loop is similar in functionality to the second loop. But rather than iterating over the values of the high_temperatures, it iterates over the elements of the low_temperature and calculates the average low temperature for the entire week.

The syntax and loop formation was simplest in the second and third loop, but we had very little control. If we want to print multiple lists together (like in the first loop) or perform computations using data from multiple lists (like in fourth loop), we need to iterate over a list using index positions. It gives relatively more control to the programmer. Next, we will go through the code in lines 9 to 13 and 25 to 29 to demonstrate iteration over the index positions.

Line 9, 10 Prints Daily High and Low Temperatures and the column headings for the table (Day, High, Low).
Line 11 The for loop starts processing. The target variable is idx. idx will get a value in each iteration from the sequence generated by the range function. The range function is given the length of the list as an argument. The range will generate a sequence from 0 to one less than the length of the list. Therefore, for the first iteration, idx will be 0, for the second it will be 1 and so. The value of idx will be 6 in the last iteration of the loop.
Line 12 Value of idx is used as an index to retrieve values from three separate lists. It is something that was not possible when iterating using values from a list.
Line 13 An empty line is printed on the console.
Line 25, 26 Two strings are printed. The second line contains the heading for the two columns that will be printed by the for loop.
Line 27 The for loop iterates seven times (length of the list) and the target variable is assigned values from 0 to 6 in each iteration.
Line 28 Idx is used to retrieve one value from each of the two lists. (high_temperatures and low_temperatures) and then the average is calculated.
Line 29 Weekdays and corresponding averages are printed on the console.

The output of the program is shown in Console 4.


Daily High and Low Temperatures
Day High    Low
Mon 35  8
Tue 30  7
Wed 32  7
Thu 40  0
Fri 28  1
Sat 29  -1
Sun 29  5

Average High:   31.9
Average Low:    3.9

Daily Averages
Day Average
Mon 21.5
Tue 18.5
Wed 19.5
Thu 20.0
Fri 14.5
Sat 14.0

Console 4: Output of Prog 8-04.

Slicing

List slicing is a powerful method to read a subset of elements. We have used the following syntax for extracting a single element from a list:


element = my_list[2]

Rather than just specifying an index position in the square brackets, we can specify multiple indexes separated by colons. Prog 8-05 in Code Listing 5 shows code that creates a list of noble gasses and then uses slicing to retrieve data from the list. The print statements in the program output an element or a subset of elements in each line of code. Along with the output, the code is also included as a string to assist in understanding.


 # Program Name: Prog 8-05
 # This program is part of Lesson 08 of the course 
  
 def main ():
        nobles = ['helium', 'neon', 'argon', 'krypton', 'xenon', 'radon']
        print(f"nobles[1]\t{nobles[1]}")
        print(f"nobles[len - 1]\t{nobles[len(nobles) - 1]}")
  
        print("***slicing***")
  
        print(f"nobles[1:3]\t{nobles[1:3]}")
        print(f"nobles[1:2]\t{nobles[1:2]}")
        print(f"nobles[1:13]\t{nobles[1:13]}")
    print(f"nobles[1:5:2]\t{nobles[1:5:2]}")
    print(f"nobles[:]\t{nobles[:]}")
    print(f"nobles[1:]\t{nobles[1:]}")
    print(f"nobles[:3]\t{nobles[:3]}")
    print(f"nobles[-3:-1]\t{nobles[-3:-1]}")
    print(f"nobles[5:1:-1]\t{nobles[5:1:-1]}")
        print(f"nobles[0:len]\t{nobles[0: len(nobles)]}")

main()

Code Listing 5: Prog 8-05 .

Line by line code description is given below:

Line 5 A list (nobles) of length 6 is created, and it contains the names of the noble gasses.
Line 6 The second element of the list (index = 1) is printed.
Line 7 The last element of the list (index = length of the list – 1) is printed.
Line 9 ***slicing*** is printed to denote the start of slicing statements below.
Line 11 nobles[1:3] is used to output data.
  • nobles is the name of list.
  • 1 is the starting index of the slice. It is included in the slice.
  • 3 is the ending index of the slice. It is not included in the slice.
  • : is used to separate starting index and ending index.
  • [] Square brackets enclose all the indexes used in slicing.
It will return elements at index 1 and index 2, thus printing:
[‘neon’, ‘argon’]
Square brackets are used in the output above. Square brackets are used as slicing returns a list.
Line 12 nobles[1:2] is used to output data. The starting index is 1, and the ending index is 2. We know that the value at the ending index is not included in the output, so this slicing statement will return just one element, which exists at index 1. As slicing always returns a list, the output will not be a single string, but a list with a single element in it. Square brackets will be used to denote that the output is a list.
Line 13 nobles[1:13] returns all the elements from 1 to But we have only 6 elements. This will not generate an error. All the elements excluding the one at the index 0 are displayed on the console.
Line 14 nobles[1:5:2]
  • is the starting index.
  • 5 is the ending index (not included in the slice).
  • is the step size.
The output will be the values at index 1 and 3. Index 2 and 3 will be skipped.
Line 15 nobles[:]
  • The starting index is missing, so 0 will be considered.
  • The ending index is missing, so the all the values will be part of the slice.
  • A colon is used to denote that it is a slice, and therefore a list will be returned.
Line 16 nobles[1:]
  • The starting index is 1.
  • The ending index is missing, so all the elements after the starting index will be included.
Line 17 The starting index is not mentioned, so it will be considered 0. The ending index is 3, so the output will be a list containing the first three elements.
Line 18 nobles[-3:-1]: The indexes are mentioned using reverse indexing.
Line 19 nobles[5:1:-1]
  • The starting index is 5, which is the last element in the list.
  • The ending index is 1.
  • The step is -1, so the elements will be printed in reverse.
Line 20 nobles[0: len(nobles)]: The slice will include all the elements of the list.

The output of Prog 8-05 is given in Console 5.


nobles[1]   neon
nobles[len-1] radon
***slicing***
nobles[1:3] ['neon', 'argon']
nobles[1:2] ['neon']
nobles[1:13]    ['neon', 'argon', 'krypton', 'xenon', 'radon']
nobles[1:5:2]   ['neon', 'krypton']
nobles[:]   ['helium', 'neon', 'argon', 'krypton', 'xenon', 'radon']
nobles[1:]  ['neon', 'argon', 'krypton', 'xenon', 'radon']
nobles[:3]  ['helium', 'neon', 'argon']
nobles[-3:-1]   ['krypton', 'xenon']
nobles[5:1:-1]  ['radon', 'xenon', 'krypton', 'argon']
nobles[0:len]   ['helium', 'neon', 'argon', 'krypton', 'xenon', 'radon']

Console 5: Output of Prog 8-05. 'len' is used to denote the length of the list.

Lists in Functions

There are two methods of passing data. One is pass by value, and the second is pass by reference. When we pass parameters to a function, the data is passed by value for strings, integers, and floats, but in case of lists, it is passed by reference.

Image of young man and woman looking at a laptop computer screen. They could be writing a collaborative essay.
Figure 2. Man and woman collaborating on a computer. Retrieved from https://pixabay.com/. Free for commercial use.

Let's take a real world example. Suppose you are working with your friend on an essay. You complete a few sections of the essay, and now you friend needs to write a few sections. You have two options:

  1. You make a copy of the essay you wrote and mail it to your friend to work on it. In this case, you keep the original copy separately. Any changes that your friend makes will not be reflected in the original. This is pass by value.
  2. You send the address of the original copy that you were working on. Your friend gets the original and works on it. In this case any changes your friend makes will be made in the original copy. On the other hand, you saved a few papers. This is pass by reference.

8.6.1 Copying lists

Prog 8-06 has two lists containing names of domestic and wild animals. It shows three methods to copy data from a list. The first method is copying by reference, whereas the other two are copying by value. The source code is shown in Code Listing 6.


 # Program Name: Prog 8-06
 # This program is part of Lesson 08 of the course 
  
 def main ():
        domestic = ["cat", "dog", "parrot"]
        wild = ["tiger", "lion", "cheetah"]
  
        domestic_copy = domestic
        domestic_copy[0] = "goat"
        print(f"domestic\t{domestic}")
        print(f"domestic_copy\t{domestic_copy}")
  
        wild_copy_1 = wild.copy()
    wild_copy_1[0] = "elephant"
    print(f"wild\t\t{wild}")
    print(f"wild_copy_1\t{wild_copy_1}")

    wild_copy_2 = wild[:]
    wild_copy_2[0] = "giraffe"
        print(f"wild\t\t{wild}")
    print(f"wild_copy_2\t{wild_copy_2}")    

main()

Code Listing 6: Prog 8-06 .

Line by line discussion of the source code is given below:

Line 5, 6 Two lists are created. domestic contains names of three domestic animals. wild has names of three wild animals.
Line 8 A reference to domestic is created and stored in domestic_copy.
The data is not being copied. domestic_copy points to the same list that domestic points to. Any change made to either domestic or domestic_copy will be reflected in both of them. See figure 1 below.
Line 9 The value of the first element of domestic_copy is changed from cat to goat.
Line 10, 11 domestic and domestic_copy are printed on the console. The first element is goat in both of them.
Line 13 A copy of wild is created using the copy method. This method of copying, copies the entire data by value. It does not share the reference like in the previous case.
Line 14 The first element of wild_copy_1 is changed from tiger to elephant. This change in not reflected in the original (wild). See figure 2 below.
Line 15, 16 wild and wild_copy_1 are printed on the console.
Line 18 Another copy of wild is created using slicing. Slicing also copies by value rather than copying by reference.
Line 19 The first element of wild_copy_2 is changed from tiger to giraffe.
Line 20, 21 wild and wild_copy_2 are printed on the console.

The output of the program is shown in Console 6. The change made in domestic_copy is also reflected in domestic, whereas changes made to wild_copy_1 and wild_copy_2 did not alter wild.


domestic        ['goat', 'dog', 'parrot']
domestic_copy   ['goat', 'dog', 'parrot']
wild            ['tiger', 'lion', 'cheetah']
wild_copy_1     ['elephant', 'lion', 'cheetah']
wild            ['tiger', 'lion', 'cheetah']
wild_copy_2     ['giraffe', 'lion', 'cheetah']

Console 6: Output of Prog 8-06.
Domestic is the variable name which points to a list containing names of three animals. Domestic_copy is another variable but it also points to the same list.
Figure 3. Copying data by reference. Created by Muhammad Muddassir Malik. Used with permission.
Wild contains names of three wild animals. wild_copy_1 is the copy of the list pointed by wild. The value of the first element of wild_copy_1 is changed from “tiger” to “elephant”.
Figure 4. Copying data by value. Created by Muhammad Muddassir Malik. Used with permission.

8.6.2 Passing Lists as Arguments

Strings and numbers are passed to another function by value. Lists are always passed by reference. That means, if a function changes a list that was passed to it, the change will be reflected in the original as well. Passing by reference has a big advantage in terms of memory consumption.

Consider a list containing ages of all the voters for the upcoming federal elections. Understandably, this list will be quite large. We have a function that can calculate statistical measures like total number of voters, voters above the age of 50, and the average age of the voters. If such a long list is passed to the function by value, the copying will take time and also the copied list will consume a lot of additional memory. On the other hand, the changes you make will be permanent. A programmer needs to use copy by value or copy by reference appropriately.

Code Listing 7 shows Prog 8-07. A list named team_exp contains the experience of the team members in years.


 # Program Name: Prog 8-07
 # This program is part of Lesson 08 of the course 
  
 def statistical_measures (li):
        minimum = min(li)
        maximum = max(li)
        total = sum(li)
        average = total / len(li)
  
        print(f"Min: {minimum:d}, Max: {maximum:d}")
        print(f"Average: {average:.2f}")
  
 def sort_data (li):
    choice = input("A for ascending, D for decending: ")
    if (choice == "A"):
        li.sort()
    elif (choice == "D"):
        li.sort(reverse = True)
    else:
            print("Sorting Failed")

2 def find_new(li, years):
    li.sort()
    cutoff = 0
    for idx in range(len(li)):
        if (li[idx] > 7):
            cutoff = idx
            break
    return li[0: cutoff]
30.  
3 def main ():
3       team_exp = [10, 4, 5, 7, 8, 8, 3, 2, 1, 10, 10]
3       print("1. team_exp ", team_exp)
3  
3       statistical_measures (team_exp)
3       print("2. team_exp ", team_exp) 
3  
3       sort_data (team_exp)
3       print("3. team_exp ", team_exp)
40.  
4       new_players = find_new(team_exp.copy(), 7)
4       print("4. team_exp ", team_exp)
4       print("5. new_players ", new_players)
4   
4 main()

Code Listing 7: Prog 8-07 .

The program performs the following functionality:

  1. Calculate the minimum, maximum and average experience of the team members. These computations are performed in a function named statistical_measures. The calculations will not change the original data, so we can safely pass the list by reference to such a function without risking any changes.
  2. Sort the data in ascending order or descending order based on user input. This is accomplished in the sort_data function. We want the original data to be sorted, so passing by reference is the right choice in this case too.
  3. Make a list of new players with experience less than or equal to 7 years. find_new function does this job. A new list with a subset of data will be generated in this function, so we do not want the original to be modified. In this case passing by value is a better choice.

There are 5 print statements in the program, and 4 of the print statements display team_exp at different points of execution. The serial numbers are printed to assist in relating output to the appropriate print call. The output of the program is shown in Console 7.

  1. team_exp is passed by reference to statistical_measures, but as the function does not change any data, the list remains the same. See the first and the second print statements.
  2. team_exp is passed by reference to sort_data, and the intention is to modify the original data. The function does not return anything, but the changes are reflected in team_exp inside the main function. See the second and the third print statements.
  3. team_exp is passed by value to find_new by using the copy function. team_exp in the main function and li in the find_new function point to different lists. find_new creates a new list and returns it to the main function. team_exp remains unchanged (see the third and the fourth print statements)

1. team_exp  [10, 4, 5, 7, 8, 8, 3, 2, 1, 10, 10]
Min: 1, Max: 10
Average: 6.18
2. team_exp  [10, 4, 5, 7, 8, 8, 3, 2, 1, 10, 10]
A for ascending, D for decending: D
3. team_exp  [10, 10, 10, 8, 8, 7, 5, 4, 3, 2, 1]
4. team_exp  [10, 10, 10, 8, 8, 7, 5, 4, 3, 2, 1]
5. new_players  [1, 2, 3, 4, 5, 7]

Console 7: Output of Prog 8-07.

Built-in Methods

We have seen build-in methods in previous lessons. Lists have some methods which are specifically designed for processing data stored in lists. The description of these methods is given on the official Python website.

Prog 8-08 shown in Code Listing 8 demonstrates the use of some of the common methods. The program has a list named schools. Serial numbers are included in the print statements to make it easier to correlate the output with the code.


 # Program Name: Prog 8-08
 # This program is part of Lesson 08 of the course 
  
 def main ():
        schools = ["WLU", "CalgaryU", "McGill", "TUWien"]
        schools.insert(3, "NU")
        print("1. ", schools)
        schools.append("uToronto")
        print("2. ", schools)
  
        schools.append("WLU")
        occ_of_WLU = schools.count("WLU")
        print("3. ", occ_of_WLU)
    del schools[len(schools) - 1]
    print("4. ", schools)
    print("5. ", schools.count("CalgaryU"))

    schools.extend(["KU", "NUS", "BU"])
    print("6. ", schools)
 
    print("7. ", schools.index("TUWien", 2))

    schools.insert(1, "MIT")
    print("8. ", schools)

    print("9. ", schools.pop())
    print(" ", schools)

    print(" ", schools.pop(0))
30.         schools.append("WLU")
3       print(" ", schools)
3  
3       schools.reverse()
3       print(" ", schools)
3  
3       schools.sort()
3       print(" ", schools)
3  
3       schools.sort(reverse = True)
40.         print(" ", schools)
4  
4       schools.clear()
4       print(" ", schools) 
4  
4 main()

Code Listing 8: Prog 8-08 .

The table below lists the methods used in the above program and the description of their functionality.

Statement Description
schools.insert(3, "NU") The value NU is inserted in the list named schools at index 3. Element at index 3 and beyond will be shifted to the right to make space for NU.
schools.append("uToronto") An append method inserts the given value (uToronto) to the end of the schools.
occ_of_WLU = schools.count("WLU") A count method counts the number of times an element (WLU) exists in schools. The number is returned and is assigned to the variable occ_of_WLU.
del schools[len(schools) - 1] A del keyword is used to delete an element from a list. The index position of the element is specified in square brackets.
schools.extend(["KU", "NUS", "BU"]) An extend is similar to append in functionality. An append inserts a single element at the end of the list, whereas extend inserts elements of a list (passed as an argument to extend) in schools.
The list is not inserted as a whole, rather each element of the list is extracted and inserted at the end of the schools.
schools.index("TUWien", 2)) An index method returns the index position of the second (2) occurrence of the string TUWien in schools.
schools.pop() A pop method removes the last element of schools and returns the element.
schools.pop(0) This variant of pop is passed an index position as an argument. It removes the element at that index from the list and returns it.
schools.reverse() A reverse method inverts the sequence of elements in the list. The changes are made to the original list.
schools.sort() The elements of the list are sorted. The original list is changed.
schools.sort(reverse = True) The optional argument (reverse = True) is passed to the sort method. This will sort the elements in the reverse order.
schools.clear() A clear method removes all the elements from the list.

The output of the program is shown in Console 8.


 ['WLU', 'CalgaryU', 'McGill', 'NU', 'TUWien']
 ['WLU', 'CalgaryU', 'McGill', 'NU', 'TUWien', 'uToronto']
 2
 ['WLU', 'CalgaryU', 'McGill', 'NU', 'TUWien', 'uToronto']
 1
 ['WLU', 'CalgaryU', 'McGill', 'NU', 'TUWien', 'uToronto', 'KU', 'NUS', 'BU']
 4
 ['WLU', 'MIT', 'CalgaryU', 'McGill', 'NU', 'TUWien', 'uToronto', 'KU', 'NUS', 'BU']
 BU
  ['WLU', 'MIT', 'CalgaryU', 'McGill', 'NU', 'TUWien', 'uToronto', 'KU', 'NUS']
  WLU
  ['MIT', 'CalgaryU', 'McGill', 'NU', 'TUWien', 'uToronto', 'KU', 'NUS', 'WLU']
  ['WLU', 'NUS', 'KU', 'uToronto', 'TUWien', 'NU', 'McGill', 'CalgaryU', 'MIT']
  ['CalgaryU', 'KU', 'MIT', 'McGill', 'NU', 'NUS', 'TUWien', 'WLU', 'uToronto']
  ['uToronto', 'WLU', 'TUWien', 'NUS', 'NU', 'McGill', 'MIT', 'KU', 'CalgaryU']
  []

Console 8: Output of Prog 8-08.

Conclusion

In this lesson, we learnt how we can use lists to put together data and to process them efficiently. for loops are designed to process data in the containers. while loops provide us with more control. Build-in methods of list and slicing help programmers achieve functionality with less code.

The assignment will reinforce the concepts covered in this lesson and in the textbook. In the next lesson you will learn more about strings. The indexing of strings also starts with zero like in the case of lists.

We hope you are ready to attempt this week’s quiz and assignment now. They are available on MyLearningSpace. You are encouraged to consult the syllabus for clarity about the deadlines for the preparation activities, quizzes, and assignments. Please regularly visit MyLearningSpace for announcements, course materials, and discussion boards.