1. a. |----| | | V | values ----> [0, | , 2] The second entry in values is a reference to the list itself b. [0, [...], 2] c. [0, [...], 2] d. [0, [...], 2] e. This list is called "recursive" in that the list is defined with respect to itself. Each time we ask for the entry at index 1, we get the list itself. We could do this indefintely if we wanted, e.g.: >>> values[1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1][1] etc. 2. a. Say we type the following: >>> x = [1, 2, 3] >>> y = [4, 5, 6] >>> list_swap1(x, y) If we look at what's going on in memory when the function is first called: x ----> [1, 2, 3] y --------------> [4, 5, 6] ^ ^ list_swap1: | | a ----------| | b -------------------| There are two list objects and x and y reference them. When the function is called, a and b then also reference the same lists respectively. In the program, changing the values of a and b will NOT change what the outer variables x and y reference. b. This is another attempt at it, but when the function is called the picture above will be the same. This time, we do full copies of a and b using the slicing operation, however, this still will NOT change the outer variables. c. This is almost there. Now, instead of changing the values of a and b, we are mutating/changing the list themselves. This will swap SOME of the values, however, if a and b have different lengths then either an exception will occur or only some of the data will get swapped.