Fluent Python, 2nd Edition by Luciano Ramalho
1.91%, 11 Jan 2025, 20:24 UTC
The first thing to know about special methods is that they are meant to be called by the Python interpreter, and not by you.
You don’t write my_object.__len__().
You write len(my_object) and, if my_object is an instance of a user-defined class, then Python calls the __len__ method you implemented.
1.92%, 11 Jan 2025, 20:24 UTC
the interpreter takes a shortcut when dealing for built-in types like list, str, bytearray, or extensions like the NumPy arrays.
Python variable-sized collections written in C include a struct2
called PyVarObject, which has an ob_size field holding the number of items in the collection.
1.95%, 11 Jan 2025, 20:24 UTC
and this is much faster than calling a method.
1.98%, 11 Jan 2025, 20:24 UTC
If you need to invoke a special method,
it is usually better to call the related built-in function (e.g., len, iter, str, etc.).
These built-ins call the corresponding special method,
but often provide other services and—for built-in types—are faster than method calls
2.71%, 14 Apr 2025, 17:58 UTC
len(x) runs very fast when x is an instance of a built-in type.
No method is called for the built-in objects of CPython: the length is simply read from a field in a C struct.
2.73%, 08 Apr 2025, 13:14 UTC
In other words, len is not called as a method because it gets special treatment as part of the Python Data Model, just like abs.
2.99%, 08 Apr 2025, 13:18 UTC
In contrast, consider Go. Some objects in that language have features that are magic,
in the sense that we cannot emulate them in our own user-defined types.
For example, Go arrays, strings, and maps support the use brackets for item access, as in a[i].
But there’s no way to make the [] notation work with a new collection type that you define.
3.04%, 08 Apr 2025, 13:17 UTC
The metaobject part refers to the objects that are the building blocks of the language itself.
In this context, protocol is a synonym of interface. So a metaobject protocol is a fancy synonym for object model: an API for core language constructs.
3.27%, 22 Jan 2025, 16:37 UTC
A container sequence holds references to the objects it contains, which may be of any type,
while a flat sequence stores the value of its contents in its own memory space,
not as distinct Python objects
5.61%, 22 Jan 2025, 16:41 UTC
A common feature of list, tuple, str, and all sequence types in Python is the support of slicing operations, which are more powerful than most people realize.
5.72%, 22 Jan 2025, 16:46 UTC
The notation a:b:c is only valid within [] when used as the indexing or subscript operator,
and it produces a slice object: slice(a, b, c)
5.74%, 22 Jan 2025, 16:46 UTC
knowing about slice objects is useful because it lets you assign names to slices, just like spreadsheets allow naming of cell ranges.
5.95%, 22 Jan 2025, 16:39 UTC
When the target of the assignment is a slice, the righthand side must be an iterable object,
even if it has just one item.
6.46%, 21 Apr 2025, 22:39 UTC
In contrast, the built-in function sorted creates a new list and returns it.
It accepts any iterable object as an argument, including immutable sequences and generators (
6.49%, 21 Apr 2025, 22:41 UTC
key
A one-argument function that will be applied to each item to produce its sorting key.
For example, when sorting a list of strings, key=str.lower can be used
to perform a case-insensitive sort, and key=len will sort the strings by character length.
7.02%, 12 Mar 2025, 20:28 UTC
The built-in memoryview class is a shared-memory sequence type that lets you handle slices of arrays without copying bytes
7.04%, 19 Apr 2025, 06:39 UTC
A memoryview is essentially a generalized NumPy array structure in Python itself (without the math).
It allows you to share memory between data-structures (things like PIL images, SQLite databases,
NumPy arrays, etc.) without first copying.
This is very important for large data sets.
7.20%, 19 Apr 2025, 06:40 UTC
For advanced array and matrix operations, NumPy is the reason why Python became mainstream in scientific computing applications.
NumPy implements multi-dimensional, homogeneous arrays and matrix types that hold not only numbers but also user-defined records, and provides efficient element-wise operations.
9.34%, 19 Apr 2025, 06:22 UTC
The hash code of a correctly implemented object is guaranteed to be constant only within one Python process.
9.36%, 19 Apr 2025, 06:23 UTC
If an object implements a custom __eq__() that takes into account its internal state, it will be hashable only if its __hash__() always returns the same hash code. In practice, this requires that __eq__() and __hash__() only take into account instance attributes that never change during the life of the object.
10.37%, 08 Apr 2025, 12:41 UTC
A ChainMap instance holds a list of mappings that can be searched as one.
The lookup is performed on each input mapping in the order it appears in the constructor call,
and succeeds as soon as the key is found in one of those mappings.
30.49%, 22 Apr 2025, 13:28 UTC
Function decorators let us “mark” functions in the source code to enhance their behavior in some way.
This is powerful stuff, but mastering it requires understanding closures—which is what we get when functions capture variables defined outside of their bodies.
30.61%, 22 Apr 2025, 13:29 UTC
A decorator is a callable that takes another function as an argument (the decorated function).
A decorator may perform some processing with the decorated function,
and returns it or replaces it with another function or callable object.2
31.24%, 08 Apr 2025, 12:40 UTC
Actually, a closure is a function—let’s call it f—with an extended scope that encompasses variables referenced in the body of f
that are not global variables or local variables of f.
Such variables must come from the local scope of an outer function that encompasses f.
It does not matter whether the function is anonymous or not;
what matters is that it can access nonglobal variables that are defined outside of its body.
31.58%, 22 Apr 2025, 13:31 UTC
the nonlocal keyword was introduced in Python 3. It lets you declare a variable as a free variable even when it is assigned within the function. If a new value is assigned to a nonlocal variable, the binding stored in the closure is changed
31.62%, 23 Apr 2025, 09:18 UTC
Variable Lookup Logic
When a function is defined, the Python bytecode compiler determines how to fetch a variable x that appears in it, based on these rules:3
-
If there is a global x declaration, x comes from and is assigned to the x global variable module.4
-
If there is a nonlocal x declaration, x comes from and is assigned to the x local variable of the nearest surrounding function where x is defined.
-
If x is a parameter or is assigned a value in the function body, then x is the local
variable.
-
If x is referenced but is not assigned and is not a parameter:
-
x will be looked up in the local scopes of the surrounding function bodies (nonlocal scopes).
-
If not found in surrounding scopes, it will be read from the module global scope.
-
If not found in the global scope, it will be read from __builtins__.__dict__.
33.53%, 01 Feb 2025, 16:41 UTC
Dynamic Scope Versus Lexical Scope
The designer of any language with first-class functions faces this issue:
being a first-class object, a function is defined in a certain scope but may be invoked in other scopes.
The question is: how to evaluate the free variables?
The first and simplest answer is “dynamic scope.
39.06%, 07 Apr 2025, 10:42 UTC
Don’t check whether it is-a duck: check whether it quacks-like-a duck, walks-like-a duck, etc., etc.,
depending on exactly what subset of duck-like behavior you need to play your language-games with. (comp.lang.python, Jul. 26, 2000)
Alex Martelli
39.54%, 07 Apr 2025, 10:38 UTC
In the context of object-oriented programming, a protocol is an informal interface, defined only in documentation and not in code.
42.75%, 07 Apr 2025, 10:37 UTC
In addition to static protocols, Python provides another way of defining an explicit interface in code: an abstract base class (ABC).
42.77%, 07 Apr 2025, 10:36 UTC
two of the most important in Python: the sequence and iterable protocols.
The interpreter goes out of its way to handle objects that provide even a
minimal implementation of those protocols,
42.94%, 07 Apr 2025, 10:35 UTC
the special treatment
Python gives to anything vaguely resembling a sequence.
The iterable protocol in Python represents an extreme form of duck typing:
the interpreter tries two different methods to iterate over objects.
91.54%, 19 Apr 2025, 06:44 UTC
the leading _ reduces the chance of naming conflicts with user-defined attributes and methods of the decorated class.
91.69%, 08 Apr 2025, 07:44 UTC
At import time, the interpreter:
-
Parses the source code of a .py module in one pass from top to bottom. This is when a SyntaxError may occur.
-
Compiles the bytecode to be executed.
-
Executes the top-level code of the compiled module.
91.72%, 08 Apr 2025, 07:43 UTC
In particular, the import statement is not merely a
declaration,11
but it actually runs all the top-level code of a module when it is imported
for the first time in the process.