Fluent Python
My notes when reading Luciano Ramalho's Fluent Python.
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.- 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)
andb
is[1, 2, 3]
. Only one*
prefix variable is allowed.
- Named Tuples
collections.namedtuple
- Construction: 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:...]
. Ifa
is 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] = 100Traceback (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 = [[]] * 3
will 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.sort
andsorted
list.sort
sorts inplace and returnsNone
.sorted
library function accepts any iterable object.- Both accept two parameters:
reverse
bool andkey
for the name of a function that produces sorting keys.
Last modified 2yr ago