Skip to main content

Section 11.17 Worked Example: List Parameters

Subgoals for Evaluating Lists.

  1. Declaring and initializing a list
    1. Set up a one dimensional table (i.e., one row) with 0 to size - 1 elements.
    2. Upon instantiation of a list, all elements contain values from the initializer list (i.e., the list of values inside the square brackets). If no initializer list is provided, the list is empty.
  2. Determining access, slicing, changing, adding, or whole list actions.
    1. Determine the list name and the action to be performed.
    2. If the list is on the left hand side of an assignment statement WITHOUT square brackets, it is a Whole List Action for List Assignment.
    3. If the list is on the left hand side of an assignment statement WITH square brackets, it is a Changing value of a List Element.
    4. If the append or insert method is being used on an instance of a list, it is an Adding a Value to a List Element.
    5. If the list is an expression WITHOUT square brackets, it is a Whole List Action for Passing a List as an Argument.
    6. If the list is an expression WITH square brackets, then check if there is a colon in the square brackets. If there is a colon inside of the square brackets, it is a Slicing Multiple Values from a List. Otherwise, it is an Accessing List Element.
  3. Accessing list element
    1. Determine value of index for element to be accessed; a positive value if counting from the beginning, or a negative value if counting from the end.
    2. listName[index] returns value stored at that index.
    3. Index must be between 0 and len(listName)-1, inclusive, or a negative value; otherwise an IndexError exception occurs at runtime.
  4. Slicing multiple values from a list
    1. Determine the range of indexes for the elements to be sliced
    2. listName[startIndex:endIndex] returns a new list containing the elements from startIndex to endIndex-1 (inclusive)
    3. Negative numbers can be used for startIndex and endIndex to count from the end of the list
    4. Omitting startIndex starts from the beginning of the list, and omitting endIndex goes to the end of the list
  5. Changing value of a list element
    1. Evaluate expression within [] brackets to determine the index of the element to be changed, and the list to change.
      Determine value of index for element to be changed; a positive value if counting from the beginning, or a negative value if counting from the end.
    2. Determine the expression of RHS (right-hand side) of the assignment statement.
    3. The lists’ value is now changed to match the value calculated from the RHS of the assignment statement.
  6. Adding a value to a list element
    1. Check whether the append or insert method is being used. Note that either way you do not use an assignment statement, it is just a method call.
    2. If append is used, the new value is added to the end of the list.
    3. If adding a value elsewhere in the list, use the insert method to add the new value at the specified index. Existing values starting from that index are shifted to the right.
  7. Traversing a List
    1. Determine the list that is being iterated over. If the expression also involves a range(len(list_name)), then the list is being traversed by index. The range function can either take one argument (the length of the list) or 3 arguments (the starting index, ending index, and step size). If the range function takes one argument, it will start at 0 and go to the length of the list - 1. If the range function takes 3 arguments, it will start at the first argument and go to the second argument - 1, incrementing by the third argument. Otherwise, if range is not used, then the list is being traversed by value.
    2. Determine the loop control variable that is being used to iterate over the list. The loop control variable will take on each value or index in the list, one at a time, depending on whether we are iterating by value or by index.
    3. The loop control variable is used to access the list element in the body of the loop. If iterating by index, the loop control variable is used as an index to access or update the list element. If iterating by value, the loop control variable is used directly to access the list element (no updates are possible).
    4. The list can also be added to with the append or insert methods. The append method adds a new value to the end of the list, while the insert method adds a new value at the specified index. Existing values starting from that index are shifted to the right.
  8. Whole list actions
    1. Passing a list as an argument
      1. Determine that the entire list must be passed as an argument to a method by consulting documentation.
      2. When calling a function, put variable name that represents the list as an argument in the method call. Remember that when passing a list as an argument that changes made by the function to the list are persistent. The list itself is not copied, so the function does not have its own copy of the list. However, the one exception to this is if you assign the argument to reference a different list in memory; then you will no longer be modifying the original list.
    2. List Assignment
      1. Determine that the reference to the list needs to be changed, not just its contents.
      2. The LHS of the assignment is the list reference needing to be changed.
      3. The RHS of the assignment is the new list reference.

Subsection 11.17.1

Problem: Evaluate the following code - what is the output?
def list_method(list_one, list_obj):
    temp = [6, 7, 8, 9, 10]
    print("Inside function list_method:")
    print("list_one is", print_int_list(list_one))
    print("temp is", print_int_list(temp))
    print("list_obj is", print_obj_list(list_obj))

    # change values
    for i in range(len(list_one)):
        list_one[i] = list_one[i] + 1
    
    list_obj[0].set_name("Juan Valdez")
    list_obj[0].set_id(362)
    list_obj[2] = Person("Mary Smith", 548)

    print("At end of function list_method:")
    print("list_one is", print_int_list(list_one))
    print("temp is", print_int_list(temp))
    print("list_obj is", print_obj_list(list_obj))
    return temp

def main():
    one = [0, 1, 2, 3, 4, 5]
    two = [0, 0]
    gamma = [Person("Maria Santos", 156), Person("Caiji Zheng", 742), None]
    
    print("Before function call:")
    print("one is", print_int_list(one))
    print("two is", print_int_list(two))
    print("gamma is", print_obj_list(gamma))
    
    two = list_method(one, gamma)
    
    print("After function call:")
    print("one is", print_int_list(one))
    print("two is", print_int_list(two))
    print("gamma is", print_obj_list(gamma))

def print_int_list(arr_list):
    result = ""
    for o in arr_list:
        result += str(o)
        result += "  "
    return result

def print_obj_list(arr_list):
    result = ""
    for o in arr_list:
        result += str(o)
        result += "  "
    return result

if __name__ == "__main__":
    main()
This code also makes use of a Person class, which is defined here:
class Person:
    def __init__(self, name="", person_id=0):
        self.set_name(name)
        self.set_id(person_id)

    # Accessors and Mutators
    def get_name(self):
        return self.name
    
    def set_name(self, name):
        if len(name) != 0:  # name must not be empty
            self.name = name
    
    def get_id(self):
        return self.person_id
    
    def set_id(self, person_id):
        self.person_id = person_id
    
    # __str__ to allow conversion to String
    def __str__(self):
        return f"Person{{name='{self.name}', id={self.person_id}}}"

Subsection 11.17.2 SG1: Declaring and initialization of list

The first several lines of the main() function are declaring and initializing lists:
one = [0, 1, 2, 3, 4, 5]
two = [0, 0]
gamma = [Person("Maria Santos", 156), Person("Caiji Zheng", 742), None]
Here is a memory representation:
Figure 11.17.1.

Subsection 11.17.3 SG2: Determine access or action

The list gamma is initialized with two new Person instances and a None value:
gamma = [Person("Maria Santos", 156), Person("Caiji Zheng", 742), None]
We are creating and instantiating two new Person instances with the parameters in the constructor call, and adding them to the list. Once these statements are completed, here is a memory representation:
Figure 11.17.2.
So these next statements:
print("Before function call:")
print("one is", print_int_list(one))
print("two is", print_int_list(two))
print("gamma is", print_obj_list(gamma))
Will generate this output:
Before function call:
one is 0  1  2  3  4  5  
two is 0  0  
gamma is Person{name='Maria Santos', id=156}  Person{name='Caiji Zheng', id=742}  None
Notice there are two helper functions, print_int_list and print_obj_list that simply concatenate the str() results for each list element into a string that is returned. These functions are used to print out the contents of the lists.

Subsection 11.17.4 SG2: Determine access or action

For the next line of code:
two = list_method(one, gamma)
We are passing entire lists as parameters and assigning the return value of the function to a list, so we go to SG8. Let’s break this function call down into two separate pieces: passing the parameter and then returning a list.

Subsection 11.17.5 SG8: Whole list actions, parameter passing

When we call the function list_method, the references in the parameters one and gamma are passed to list_one and list_obj respectively. In Python, lists are passed by reference, so the function parameters point to the same list objects in memory.
The first line in list_method is declaring and initializing a new list:
temp = [6, 7, 8, 9, 10]
Here is a memory representation of the parameter passing and new local list temp:
Figure 11.17.3.
Now we are just printing the values:
print("Inside function list_method:")
print("list_one is", print_int_list(list_one))
print("temp is", print_int_list(temp))
print("list_obj is", print_obj_list(list_obj))
Which generates this output:
Inside function list_method:
list_one is 0  1  2  3  4  5  
temp is 6  7  8  9  10  
list_obj is Person{name='Maria Santos', id=156}  Person{name='Caiji Zheng', id=742}  None

Subsection 11.17.6 Evaluate code

# change values
for i in range(len(list_one)):
    list_one[i] = list_one[i] + 1

list_obj[0].set_name("Juan Valdez")
list_obj[0].set_id(362)
list_obj[2] = Person("Mary Smith", 548)
Next we have the loop that changes the values in the parameter list_one. Notice that list_one references the same list in memory as the argument one in the function call.
We then change values of the first element of the list_obj list and replace the third element - which references the same list in memory as the argument gamma in the function call.
After these changes, our memory representation would be:
Figure 11.17.4.
Before we exit the function, we print the values again:
print("At end of function list_method:")
print("list_one is", print_int_list(list_one))
print("temp is", print_int_list(temp))
print("list_obj is", print_obj_list(list_obj))
Which generates this output:
At end of function list_method:
list_one is 1  2  3  4  5  6  
temp is 6  7  8  9  10  
list_obj is Person{name='Juan Valdez', id=362}  Person{name='Caiji Zheng', id=742}  Person{name='Mary Smith', id=548}
The last line of the function:
return temp
brings us to our next subgoal.

Subsection 11.17.7 SG8: Whole list actions, list assignment

Recall the function call statement:
two = list_method(one, gamma)
which will take the returned value from the function and assign it to the left hand side variable. Notice that this has the effect of assigning the reference to list temp to the variable two.
Here is a memory representation:
Figure 11.17.5.
Afterwards, we print the values using:
print("After function call:")
print("one is", print_int_list(one))
print("two is", print_int_list(two))
print("gamma is", print_obj_list(gamma))
Which generates this output:
After function call:
one is 1  2  3  4  5  6  
two is 6  7  8  9  10  
gamma is Person{name='Juan Valdez', id=362}  Person{name='Caiji Zheng', id=742}  Person{name='Mary Smith', id=548}

Subsection 11.17.8

Answer.
Before function call:
one is 0  1  2  3  4  5  
two is 0  0  
gamma is Person{name='Maria Santos', id=156}  Person{name='Caiji Zheng', id=742}  None  
Inside function list_method:
list_one is 0  1  2  3  4  5  
temp is 6  7  8  9  10  
list_obj is Person{name='Maria Santos', id=156}  Person{name='Caiji Zheng', id=742}  None  
At end of function list_method:
list_one is 1  2  3  4  5  6  
temp is 6  7  8  9  10  
list_obj is Person{name='Juan Valdez', id=362}  Person{name='Caiji Zheng', id=742}  Person{name='Mary Smith', id=548}  
After function call:
one is 1  2  3  4  5  6  
two is 6  7  8  9  10  
gamma is Person{name='Juan Valdez', id=362}  Person{name='Caiji Zheng', id=742}  Person{name='Mary Smith', id=548}
You have attempted 1 of 1 activities on this page.