Python
Logical operators
What is acceptable in what cases
is vs == and so on.
Exception handling
frozenset
try except finally
Namespaces
Python has several types of namespaces:
Built-in namespace: Contains built-in functions and exceptions like print(), len(), ValueError, etc. This is created when Python starts and exists until the interpreter quits.
Global namespace: Created when a module is loaded. Each module has its own global namespace containing all the names defined at the module level.
Local namespace: Created when a function is called and contains the function's parameters and local variables. It's deleted when the function returns.
Enclosing namespace: Relevant for nested functions - it's the namespace of the enclosing function.
Python follows the LEGB rule when looking up names: Local → Enclosing → Global → Built-in. When you reference a variable, Python searches in that order until it finds the name.
Function signature
LRU cache
lru_cache from the functools module is an example of a decorator and an example of memoization.
lru_cache memoizes the inputs and outputs of the decorated function in a size-restricted dictionary. It speeds up repeated calls to a slow function with the same inputs. For instance, if the function reads from disk, makes network requests, or requires a lot of computation AND it is used repeatedly with the same inputs.
Here's an example from the Python documentation that perfectly illustrates how and why to use the lru_cache decorator:
Since the factorial function is recursive and the inputs are sequential numbers, it's called repeatedly with the same inputs. Without the cache, the function would be called 30 times. With lru_cache, the function is only called 13 times. While you don't often need to compute factorials, this example ties together how to use a decorator and memoization and recursion.
Shallow vs Deep copies of Python data structures
f-strings
f-string tricks: https://www.youtube.com/watch?v=9saytqA0J9A
What is a __pycache__ directory?
Last updated