Chapter 2: Data Structures Flashcards
What are container sequences? Provide examples.
Container sequences hold references to the objects they contain.
e.g list, tuple, collections.deque
What are flat sequences? Provide examples.
Flat sequences store the value of its contents in its own memory space, not as distinct python objects
e.g str, bytes, array.array
The Python array is a single object, holding a C language array
What are mutable sequences? Provide examples
Mutable sequences have methods that allow them to be mutated. Mutable sequences (virtually) inherit from MutableSequence, which in turn inherits from Sequences.
e.g list, bytearray, array.array, collections.deque
These methods include insert, append, reverse
What are immutable sequences? Provide examples
Immutable sequences do not have methods that allow them to be mutated. Mutable sequences (virtually) inherit from Sequence.
e.g tuple, str, bytes
What is the Walrus operator?
Assigns values to variables as part of a larger expression.
Can also be used during list comprehension to kep the variable in scope with the last value when the comprehension is finished
Why may one use a generator expression in the place of a list comprehension?
A generator expression saves memory because it yields items one by one instead of building the whole list just to then feed another constructor
What are the two key benefits of tuples?
Clarity - When a tuple is seen in code the programmer knows its length will never change.
Performance - A tuple uses less memory than a list of the same length. A list is allocated with room to spare to amortize the cost of future appends.
Also a tuple stores an array of references in the tuple struct, a list holds a pointer to the array of references stored elsewhere – this indirection is inefficient.
Why is an array of floats more compact than a tuple of floats?
An array of floats is a single array object holding the raw value of the floats
A tuple of floats (a container sequence) is a tuple object with references to the float objects contained in it. Each float object has a value field and metadata fields.
How could we mutate the contents of a tuple?
The contents of a tuple are immutable but that just means the references held by a tuple will always point to the same objects
We can mutate the referenced objects if they are mutable
Why do slices and ranges exclude the last item?
- It’s easy to see the length of the slice or range when only the stop position is given
- It’s easy to compute the length of a slice or range when start and stop are given (stop - start)
- Easy to split a sequence in two parts at any index x
my_list[:x] and my_list[x:]
How can a string or list be reversed using slicing notation?
my_string[::-1]
Remember my_string[a:b:c]
a is start
b is stop
c is stride or step
How is multidimensional slicing handling in python?
The __getitem__ and __setitem__ special methods recieve the indices in my_list[a, b] as a tuple.
my_list[a, b] calls my_list.__getitem__((a, b))
What is the ellipsis (…) in Python?
It is a token recognised by the Python parser
It is not used in the Python standard library
Numpy uses it as a shortcut when slicing arrays of multiple dimensions
How do the + and * operators work with sequences?
e.g a = [10, 20] + [30, 40]
Neither operand is modified
A new sequence of the same type is created as a result of the concatenation
How does the += operator work with sequences?
+= works by calling the __iadd__ special method and fallback to __add__ if this is not implemented
In the case of mutable sequences, the sequence will be changed in place as __iadd__ effectively calls the extend method
If __iadd__ is not implemented a += b is the same as a = a + b
However a + b is evaluated first, producing a new object, which is bound to a