Python's Data Structures: List
CSCI 1470

by K. Yue

1. List

2. List assignments and copying

Example:

list_assign_1.py:

#
#   list assignment
print("""
list_a = [10, [20,30], 'a', ['k',9]]
list_b = list_a[:]
""")
list_a = [10, [20,30], 'a', ['k',9]]
list_b = list_a[:]
print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_a[0]: {list_a[0]}")
print(f"list_a[1][1]: {list_a[1][1]}")
print(f"list_a[3][0]: {list_a[3][0]}")

print("""
list_a[0] = 22
list_a[1][1] = 77
""")
list_a[0] = 22
list_a[1][1] = 77

print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_a[0]: {list_a[0]}")
print(f"list_a[1][1]: {list_a[1][1]}")
print(f"list_b[0]: {list_b[0]}")
print(f"list_b[1][1]: {list_b[1][1]}")

print("list_b[3][0] = 'hello'")
list_b[3][0] = 'hello'

print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_b[3][0]: {list_b[3][0]}")
print(f"list_a[3][0]: {list_a[3][0]}")


2.1 Shallow copy

Example:

list_shallow_copy_1.py

#
#   list shallow copy
#
list_a = [10, 20, 'a', 9]

print("""
list_b = list_a[:]
#   Will also work: list_b = list(list_a)
#   list_b = list_a.copy()
""")

list_b = list_a[:]

print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_a[0]: {list_a[0]}")
print(f"list_a[3]: {list_a[3]}")

print("""
list_a[0] = 44
list_a[3] = 88
""")
list_a[0] = 44
list_a[3] = 88

print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_a[0]: {list_a[0]}")
print(f"list_a[3]: {list_a[3]}")
print(f"list_b[0]: {list_b[0]}")
print(f"list_b[3]: {list_b[3]}")

print("list_b[1] = 66")
list_b[1] = 66
print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_a[1]: {list_a[1]}")
print(f"list_b[1]: {list_b[1]}")

#   shallow copy.
#   If an item is a list itself, it copies a reference.

print("""
list_a = [10, [20,30], 'a', ['k',9]]
list_b = list_a[:]
""")
list_a = [10, [20,30], 'a', ['k',9]]
list_b = list_a[:]

print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_a[0]: {list_a[0]}")
print(f"list_a[1][1]: {list_a[1][1]}")
print(f"list_a[3][0]: {list_a[3][0]}")

print("""
list_a[0] = 22
list_a[1][1] = 77
""")
list_a[0] = 22
list_a[1][1] = 77

print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_a[0]: {list_a[0]}")
print(f"list_a[1][1]: {list_a[1][1]}")
print(f"list_b[0]: {list_b[0]}")
print(f"list_b[1][1]: {list_b[1][1]}")

print("list_b[3][0] = 'hello'")
list_b[3][0] = 'hello'
print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_b[3][0]: {list_b[3][0]}")
print(f"list_a[3][0]: {list_a[3][0]}")

2.2 Deep copy (advanced)

Example:

list_deep_copy_1.py:

#   deep copy
import copy

print("""
list_a = [10, [20,30], 'a', ['k',9]]
list_b = list_a[:]
""")
list_a = [10, [20,30], 'a', ['k',9]]
list_b = copy.deepcopy(list_a)

print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_a[0]: {list_a[0]}")
print(f"list_a[1][1]: {list_a[1][1]}")
print(f"list_a[3][0]: {list_a[3][0]}")

print("""
list_a[0] = 22
list_a[1][1] = 77
""")
list_a[0] = 22
list_a[1][1] = 77

print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_a[0]: {list_a[0]}")
print(f"list_a[1][1]: {list_a[1][1]}")
print(f"list_b[0]: {list_b[0]}")
print(f"list_b[1][1]: {list_b[1][1]}")

print("list_b[3][0] = 'hello'")
list_b[3][0] = 'hello'
print(f"list_a: {list_a}")
print(f"list_b: {list_b}")
print(f"list_b[3][0]: {list_b[3][0]}")
print(f"list_a[3][0]: {list_a[3][0]}")

3 List Comprehensions

[operation_on_iteration_variable for iteration_variable in iterable_object]

or

[operation_on_iteration_variable for iteration_variable in iterable_object if condition_for_inclusion]

Example:

list_comp_1.py:

#
#   list comprehension.
#
list_1 = [3,4,2,9,-5]
print(f"list_1: {list_1}")

#   create list_2 with elements that is 2 times each element in list_1

item = 22
print(f"item: {item}")
list_2 = []
for item in list_1:
   list_2.append(2 * item)
print(f"list_2: {list_2}")
print(f"item: {item}")

#   using list comprehension.
#   better:
#       (1) more concise.
#       (2) local scope of the iteration variable, item.

item = 37
print(f"item: {item}")
list_3 = [2 * item for item in list_1]
print(f"list_3: {list_3}")
print(f"item: {item}")

#   may add a condition for inclusion in the result.
list_4 = [2 * item for item in list_1 if item >= 0]
print(f"list_4: {list_4}")

#   Advanced examples (beyond CSCI 1470)
list_a = ['Bun', 'Jane', 'Joe']
list_b = [{'name': item, 'member': 'Yes'} for item in list_a]
list_c = [{'name': item, 'member': 'Yes', 'pos':i+1} for i, item in enumerate(list_a)]

4. Modifying Lists

Example:

list_modify_1.py:

#
#   modifying list.
#
list_1 = [0,10,20,30,40,50,60,70,80,90]
print(f"list_1: {list_1}")

# Modify elements and slices.
list_1[3]=5
print(f"list_1 after 'list_1[3]=5': {list_1}")
list_1[0]=2
print(f"list_1 after 'list_1[3]=2': {list_1}")

list_1[5:8]=[15,16,17]
print(f"list_1 after 'list_1[5:8]=[15,16,17]': {list_1}")
list_1[3:1:-1]=[61,62]
print(f"list_1 after 'list_1[3:1:-1]=[61,62]': {list_1}")

list_1 = [0,10,20,30,40,50,60,70,80,90]
print(f"list_1: {list_1}")
print("""\nTry to execute: list_1[10]=3
list_1[10]=3
Traceback (most recent call last):
  File "....", line 12, in <module>
    list_1[10]=3
IndexError: list assignment index out of range
""")
list_1.append(100)
print(f"list_1 after 'list_1.append(100)': {list_1}")
print()
print("""append() takes only one argument:
list_1.append(110,100,110,100)
print(f"list_1 after 'list_1.append(110,100,110,100)': {list_1}")
Traceback (most recent call last):
  File "....", line 30, in <module>
    list_1.append(110,100,110,100)
TypeError: list.append() takes exactly one argument (4 given)
""")
print("This also may not be what one has in mind.")
list_1.append([110,100,110,100])
print(f"list_1 after 'list_1.append([110,100,110,100])': {list_1}")
print()
print(f"Instead, use extend()")
list_1.extend([110,100,110,100])
print(f"list_1 after 'list_1.extend([110,100,110,100]))': {list_1}")

list_1.insert(2,79)
print(f"list_1 after 'list_1.insert(2,79))': {list_1}")
del list_1[3]
print(f"list_1 after 'del list_1[3])': {list_1}")
del list_1[0:2]
print(f"list_1 after 'del list_1[0:2])': {list_1}")
list_1.remove(100)
print(f"list_1 after 'list_1.remove(100)': {list_1}")
list_1.remove(100)
print(f"list_1 after 'list_1.remove(100)': {list_1}")
list_1.pop()
print(f"list_1 after 'list_1.pop()': {list_1}")

5. Nested Lists

Examples:

nested_list_1.py:

#
#   Nested data structures.
#

#   Each item in score_1 contains the scores of three homework assignments.
scores_1 = [
   [96, 89, 97],
   [88, 84, 83],
   [64, 57, 72]
]

print(f"scores_1: {scores_1}")
print(f"scores_1[0]: {scores_1[0]}")
print(f"scores_1[2]: {scores_1[2]}")
print(f"scores_1[0:1]: {scores_1[0:1]}")
print(f"scores_1[:1]: {scores_1[:1]}")
print(f"scores_1[::-1]: {scores_1[::-1]}")

print(f"scores_1[2][1]: {scores_1[2][1]}")
print(f"scores_1[2][::-1]: {scores_1[2][::-1]}")
print(f"scores_1[2][1:3]: {scores_1[2][1:3]}")
print(f"scores_1[2][:2]: {scores_1[2][:2]}")
print(f"scores_1[0:2][1]: {scores_1[0:2][1]}")
print(f"scores_1[1:3]: {scores_1[1:3]}")
print(f"scores_1[1:3][1]: {scores_1[1:3][1]}")

print("""
#   Each item in score_1 is the score of three homework assignments.
scores_1 = [
   [96, 89, 97],
   [88, 84, 83],
   [64, 57, 72]
]
""")

#   print the individual scores of each student.
for item in scores_1:
    print(f"student score: ", end="")
    for score in item:
        print(score, end=" ")
    print()

print()   
#   putting a comma between scores.
for item in scores_1:
    print(f"student scores: ", end="")
    for pos, score in enumerate(item):
        if pos == len(item)-1:
            print(score)
        else:
            print(f"{score}, ", end="")

print()            
#   Second version using list comprehensions.
for item in scores_1:
    print(f"student scores: ", end="")
    str_item = [str(score) for score in item]
    print(", ".join(str_item))
   
print()   
#   add student #
for student_num, item in enumerate(scores_1):
    print(f"student #{student_num + 1} scores: ", end="")
    for pos, score in enumerate(item):
        if pos == len(item)-1:
            print(score)
        else:
            print(f"{score}, ", end="")