Ch2

flat versus container sequences

  • container sequences - can hold nested bjects of any type including their own
  • flat sequences - only hold atomic types like integers floats or characters

flat sequences are fast, compact and easier to use. Containers are flexible but may sneak in mutable objects.

Note

stdlib has a class called Container it has a __contains__ method which is how the in operator works. This is how strings can use in because they implement __contains__ method, althought they’re flat.

Augmented Assignment with Imutable sequences

Augmented assignment is an operator like += or *= that combines an operation with assignment.

Repeated concatenation of immutable sequences is inefficient, because instead of just appending new items, the interpreter has to copy the whole target sequence to create a new one with the new items concatenated.

str is an exception to this description. Because string building with += in loops is so common in real codebases, CPython is optimized for this use case.
Instances of str are allocated in memory with extra room, so that concatenation does not require copying the whole string every time. Note that removing -= creates a copy even for strings.

When list is Not the answer

Try to use the stlib implementations when it makes sense as they’re typically optimized with CPython.

array

when: if a list only contains numbers

Python array is as lean as a C array. It can only contain one type, defined by the type code parameter, in the example I used i for signed integer.

from array import array
from random import randint

numbers = array('i', (randint(0,100) for _ in range(10**5)))
print(numbers[-1])

# Super fast to save to files
fp = open('numbers.log', as 'wb')
numbers.tofile(fp)
fp.close()

https://docs.python.org/3/library/array.html

deque

when: you want FIFO, O(1)

from collections import deque

dq = deque(range(10), maxlen=10) 
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
dq.rotate(-2)
# [2, 3, 4, 5, 6, 7, 8, 9, 0, 1]
dq.appendleft(88)
# [88, 2, 3, 4, 5, 6, 7, 8, 9, 0]
dq.extend([89,99,101])
# [4, 5, 6, 7, 8, 9, 0, 89, 99, 101]

heapq

when: priority queue