Fluent Python
My notes when reading Luciano Ramalho's Fluent Python.
The Python Data Model
By implementing special methods (A.K.A. magic methods, like __len__, __getitem__, __repr__ etc.. Often pronounced dunder xx), your objects can utilize built-in functions and syntax like len(), [], for ... in ... and thus be considered Pythonic.
Understanding the Pythonic len(xx) over xx.len(): Think of these functions as unary operators.
An Array of Sequences
List Comprehension vs Generator Expression
List Comprehension:
list_a = [i + j for i in ... for j in ...]
This is a cartesian products example.
for i in ...part is the outer loop.Generator Expression:
xx(i + j for i in ... for j in ...)
The syntactic difference is
()vs[]. But under the hood it saves space by yielding item one by one so a full list is never constructed. Also it can be used to build many other containers.Tuples
Tuples (Iterable) Unpacking
Use case: parallel assignment (can be nested), swap,
%string formattingprint('%s %s' % tup), passing function parameterf(*tup).Works for any iterable as long as the iterable yields exactly one item per variable in the receiving end. The only exception is using
*dicussed below.a, *b, c = range(5)andbis[1, 2, 3]. Only one*prefix variable is allowed.
Named Tuples
collections.namedtupleConstruction: Passing construct parameters by name or position.
NamedTup._make(iterable).NamedTup(*iterable).Accessing field by name or position.
._asdict()return acollections.OrderedDict
Methods and attributes as an "immutable list": No appending/poping/inserting nor any inplace ops.
Slicing
[:3]exclude the last item.Slice object.
s = slice(begin, end, stride) line[s]Under the hood:
# v[a] v.__getitem__(a) # v[a, b]. Multidimensional. Used in Numpy. v.__getitem__((a, b))Ellipsis object: function parameters
f(a, ..., z)and slicea[i:...]. Ifais four dimentional, this is a shortcut fora[i, :, :, :]. It is mostly used in Numpy.Assignment using slices. Some interesting example from the book:
>>> l = list(range(10)) >>> l [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] >>> l[2:5] = [20, 30] >>> l [0, 1, 20, 30, 5, 6, 7, 8, 9] >>> del l[5:7] >>> l [0, 1, 20, 30, 5, 8, 9] >>> l[3::2] = [11, 22] >>> l [0, 1, 20, 11, 5, 22, 9] >>> l[2:5] = 100 Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: can only assign an iterable >>> l[2:5] = [100] >>> l [0, 1, 100, 22, 9]
+and*and augmented assignment on sequencesmy_list = [[]] * 3will result in a list with three references to the same inner list. List comprehension avoids this problem.[[] for i in range(3)].+=and*=will first try to use__iadd__and fall back to__add__and create a new object.
list.sortandsortedlist.sortsorts inplace and returnsNone.sortedlibrary function accepts any iterable object.Both accept two parameters:
reversebool andkeyfor the name of a function that produces sorting keys.
Misc
Last updated
Was this helpful?