An ordered collection you can change
A list keeps values in order between square brackets: [184.0, 185.5, 183.2]. It can hold any values, and len(prices) tells you how many. Each item has a position called an index, counted from 0. A negative index counts from the end, so -1 is the last item. Asking for a position that does not exist raises an IndexError.
prices = [184.0, 185.5, 183.2, 186.1]
# Reading by position
print(prices[0]) # 184.0
print(prices[-1]) # 186.1
print(len(prices)) # 4
# A list is changeable: assign to a position
prices[1] = 185.0
print(prices) # [184.0, 185.0, 183.2, 186.1]Slicing: a part of a list
prices[start:stop] gives a new list from start up to, but not including, stop. Leave one out and it runs to that end: prices[:3] is the first three, prices[-3:] the last three. A slice never raises an error for going too far, it just stops at the end. One trap: -0 is the same as 0, so prices[-0:] is the whole list, not an empty one.
prices = [184.0, 185.0, 183.2, 186.1, 187.4]
# Slices are new lists
print(prices[1:3]) # [185.0, 183.2]
print(prices[:2]) # [184.0, 185.0]
print(prices[-2:]) # [186.1, 187.4]
# Going past the end is fine, but -0 is not "none"
print(prices[3:99]) # [186.1, 187.4]
print(prices[-0:]) # the whole listAdding and removing
append(x) adds one item at the end, extend(items) adds several, and insert(i, x) puts one at position i. pop() removes and returns the last item (pop(i) the one at i), and remove(x) deletes the first item equal to x. These methods change the list in place and return None, so prices = prices.append(1) leaves prices as None. Adding with + builds a new list instead.
# Changing a list in place
fills = [100, 250]
fills.append(75)
fills.extend([40, 60])
print(fills) # [100, 250, 75, 40, 60]
last = fills.pop()
fills.remove(250)
print(last, fills) # 60 [100, 75, 40]
# + builds a new list and leaves the old ones alone
both = fills + [10]
print(both, fills) # [100, 75, 40, 10] [100, 75, 40]Sorting
There are two ways to sort. prices.sort() reorders the list in place and returns None. sorted(prices) leaves the original alone and returns a new sorted list; it also accepts any iterable. Both take reverse=True for largest first and key=... to sort by something else, such as key=len. Prefer sorted when other code may still be using the original order.
# sorted() returns a new list, sort() changes the old one
prices = [185.0, 183.2, 187.4, 184.0]
ranked = sorted(prices, reverse=True)
print(ranked) # [187.4, 185.0, 184.0, 183.2]
print(prices) # [185.0, 183.2, 187.4, 184.0] (unchanged)
prices.sort()
print(prices) # [183.2, 184.0, 185.0, 187.4]Two names, one list
backup = prices does not copy the list: both names point to the same object, so changing one changes the other. Make a real (shallow) copy with prices.copy(), list(prices) or the slice prices[:]. The same applies to functions: a function that calls .append, .sort or .pop on its argument changes the caller's list too, which is rarely what the caller expects.
# A second name is not a copy
prices = [184.0, 185.0]
alias = prices
alias.append(186.0)
print(prices) # [184.0, 185.0, 186.0]
# A real copy is independent
backup = list(prices)
backup.append(187.0)
print(prices) # [184.0, 185.0, 186.0]
print(backup) # [184.0, 185.0, 186.0, 187.0]sorted(...), slices and comprehensions, which all build new lists. The labs check that the list you were given is unchanged afterwards.items[i],items[-1]: one item;items[a:b]: a new list.append,extend,insert,pop,removechange the list and return nothing useful.sorted(items)builds a new sorted list;items.sort()reorders in place.
Next up: tuples and unpacking, the fixed-size sibling of the list, and a tidy way to pull values apart.
Lab · what's graded
- Pick the largest prices with
top_n25 pts - Take the most recent values with
last_n25 pts - Average each window of prices with
moving_average25 pts - Move values around the ends with
rotate25 pts