Comprehensive Python Cheatsheet
===============================
[Download text file](https://raw.githubusercontent.com/gto76/python-cheatsheet/master/README.md)
or [Fork me on GitHub](https://github.com/gto76/python-cheatsheet).
![Monty Python](web/image_888.jpeg)
Main
----
```python
if __name__ == '__main__':
main()
```
List
----
```python
= [from_inclusive : to_exclusive : step_size]
.append()
.extend()
+= []
+=
```
```python
.sort()
.reverse()
= sorted()
= reversed()
```
```python
sum_of_elements = sum()
elementwise_sum = [sum(pair) for pair in zip(list_a, list_b)]
sorted_by_second = sorted(, key=lambda el: el[1])
sorted_by_both = sorted(, key=lambda el: (el[1], el[0]))
flattened_list = list(itertools.chain.from_iterable())
list_of_chars = list()
product_of_elems = functools.reduce(lambda out, x: out * x, )
no_duplicates = list(dict.fromkeys())
```
```python
index = .index() # Returns first index of item.
.insert(index, ) # Inserts item at index and moves the rest to the right.
= .pop([index]) # Removes and returns item at index or from the end.
.remove() # Removes first occurrence of item.
.clear() # Removes all items.
```
Dictionary
----------
```python
= .keys()
= .values()
= .items()
```
```python
value = .get(key, default) # Returns default if key does not exist.
value = .setdefault(key, default) # Same, but also adds default to dict.
= collections.defaultdict() # Creates a dictionary with default value of type.
= collections.defaultdict(lambda: 1) # Creates a dictionary with default value 1.
```
```python
.update() # Or: dict_a = {**dict_a, **dict_b}.
= dict() # Initiates a dict from list of key-value pairs.
= dict(zip(keys, values)) # Initiates a dict from two lists.
= dict.fromkeys(keys [, value]) # Initiates a dict from list of keys.
```
```python
value = .pop(key) # Removes item from dictionary.
{k: v for k, v in .items() if k in keys} # Filters dictionary by keys.
```
### Counter
```python
>>> from collections import Counter
>>> colors = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
>>> counter = Counter(colors)
Counter({'blue': 3, 'red': 2, 'yellow': 1})
>>> counter.most_common()[0][0]
'blue'
```
Set
---
```python
= set()
.add()
.update()
|= {}
|=
```
```python
= .union() # Or: | = .intersection() # Or: & = .difference() # Or: - = .symmetric_difference() # Or: ^ = .issubset() # Or: <= = .issuperset() # Or: >=
```
```python
.remove() # Throws error.
.discard() # Doesn't throw error.
```
### Frozenset
#### Is hashable and can be used as a key in dictionary.
```python
= frozenset()
```
Range
-----
```python
range(to_exclusive)
range(from_inclusive, to_exclusive)
range(from_inclusive, to_exclusive, step_size)
range(from_inclusive, to_exclusive, -step_size)
```
```python
from_inclusive = .start
to_exclusive = .stop
```
Enumerate
---------
```python
for i, el in enumerate( [, i_start]):
...
```
Named Tuple
-----------
```python
>>> Point = collections.namedtuple('Point', 'x y')
>>> p = Point(1, y=2)
Point(x=1, y=2)
>>> p[0]
1
>>> p.x
1
>>> getattr(p, 'y')
2
>>> p._fields # Or: Point._fields
('x', 'y')
```
Iterator
--------
```python
= iter()
= iter(, to_exclusive)
```
#### Skips first element:
```python
next()
for element in :
...
```
#### Reads input until it reaches an empty line:
```python
for line in iter(input, ''):
...
```
#### Same, but prints a message every time:
```python
from functools import partial
for line in iter(partial(input, 'Please enter value: '), ''):
...
```
Generator
---------
**Convenient way to implement the iterator protocol.**
```python
def step(start, step_size):
while True:
yield start
start += step_size
```
```python
>>> stepper = step(10, 2)
>>> next(stepper), next(stepper), next(stepper)
(10, 12, 14)
```
Type
----
```python
= type() # / / ...
```
```python
from numbers import Number, Integral, Real, Rational, Complex
= isinstance(, Number)
```
```python
= callable()
```
String
------
```python
= .strip() # Strips all whitespace characters.
= .strip('') # Strips all passed characters.
```
```python
= .split() # Splits on any whitespace character.
= .split(sep=None, maxsplit=-1) # Splits on 'sep' str at most 'maxsplit' times.
= .join() # Joins elements using string as separator.
```
```python
= .replace(old_str, new_str)
= .startswith() # Pass tuple of strings for multiple options.
= .endswith() # Pass tuple of strings for multiple options.
= .index() # Returns first index of a substring.
= .isnumeric() # True if str contains only numeric characters.
= textwrap.wrap(, width) # Nicely breaks string into lines.
```
### Char
```python
= chr() # Converts int to unicode char.
= ord() # Converts unicode char to int.
```
```python
>>> ord('0'), ord('9')
(48, 57)
>>> ord('A'), ord('Z')
(65, 90)
>>> ord('a'), ord('z')
(97, 122)
```
Regex
-----
```python
import re
= re.sub(, new, text, count=0) # Substitutes all occurrences.
= re.findall(, text) # Returns all occurrences.
= re.split(, text, maxsplit=0) # Use brackets in regex to keep the matches.
= re.search(, text) # Searches for first occurrence of pattern.
= re.match(, text) # Searches only at the beginning of the text.
= re.finditer(, text) # Returns all occurrences as match objects.
```
* **Parameter `'flags=re.IGNORECASE'` can be used with all functions.**
* **Parameter `'flags=re.DOTALL'` makes dot also accept newline.**
* **Use `r'\1'` or `'\\\\1'` for backreference.**
* **Use `'?'` to make operators non-greedy.**
### Match Object
```python
= .group() # Whole match.
= .group(1) # Part in first bracket.
= .groups() # All bracketed parts.
= .start() # Start index of a match.
= .end() # Exclusive end index of a match.
```
### Special Sequences
**Use capital letter for negation.**
```python
'\d' == '[0-9]' # Digit
'\s' == '[ \t\n\r\f\v]' # Whitespace
'\w' == '[a-zA-Z0-9_]' # Alphanumeric
```
Format
------
```python
= f'{}, {}'
= '{}, {}'.format(, )
```
```python
>>> Person = namedtuple('Person', 'name height')
>>> person = Person('Jean-Luc', 187)
>>> f'{person.height:10}'
' 187'
>>> '{p.height:10}'.format(p=person)
' 187'
```
### General Options
```python
{:<10} # ' '
{:>10} # ' '
{:^10} # ' '
{:->10} # '------'
{:>0} # ''
```
### String Options
**`'!r'` calls object's repr() method, instead of format(), to get a string.**
```python
{'abcde'!r:<10} # "'abcde' "
```
```python
{'abcde':.3} # 'abc'
{'abcde':10.3} # 'abc '
```
### Number Options
```python
{1.23456:.3f} # '1.235'
{1.23456:10.3f} # ' 1.235'
```
```python
{ 123456:10,} # ' 123,456'
{ 123456:10_} # ' 123_456'
{ 123456:+10} # ' +123456'
{-123456:=10} # '- 123456'
{ 123456: } # ' 123456'
{-123456: } # '-123456'
```
```python
{65:c} # 'A'
{3:08b} # '00000011' -> Binary with leading zeros.
{3:0<8b} # '11000000' -> Binary with trailing zeros.
```
#### Float presentation types:
* **`'f'` - Fixed point: `.f`**
* **`'%'` - Percent: `.%`**
* **`'e'` - Exponent**
#### Integer presentation types:
* **`'c'` - character**
* **`'b'` - binary**
* **`'x'` - hex**
* **`'X'` - HEX**
Numbers
-------
### Basic Functions
```python
= pow(, ) # Or: ** = abs()
= round( [, ndigits])
```
### Constants
```python
from math import e, pi
```
### Trigonometry
```python
from math import cos, acos, sin, asin, tan, atan, degrees, radians
```
### Logarithm
```python
from math import log, log10, log2
= log( [, base]) # Base e, if not specified.
```
### Infinity, nan
```python
from math import inf, nan, isinf, isnan
```
#### Or:
```python
float('inf'), float('nan')
```
### Random
```python
from random import random, randint, choice, shuffle
= random()
= randint(from_inclusive, to_inclusive)
= choice()
shuffle()
```
Datetime
--------
```python
from datetime import datetime, strptime
now = datetime.now()
now.month # 3
now.strftime('%Y%m%d') # '20180315'
now.strftime('%Y%m%d%H%M%S') # '20180315002834'
= strptime('2015-05-12 00:39', '%Y-%m-%d %H:%M')
```
Arguments
---------
**`'*'` is the splat operator, that takes a list as input, and expands it into actual positional arguments in the function call.**
```python
args = (1, 2)
kwargs = {'x': 3, 'y': 4, 'z': 5}
func(*args, **kwargs)
```
#### Is the same as:
```python
func(1, 2, x=3, y=4, z=5)
```
#### Splat operator can also be used in function declarations:
```python
def add(*a):
return sum(a)
```
```python
>>> add(1, 2, 3)
6
```
#### And in few other places:
```python
>>> a = (1, 2, 3)
>>> [*a]
[1, 2, 3]
```
```python
>>> head, *body, tail = [1, 2, 3, 4]
>>> body
[2, 3]
```
Inline
------
### Lambda
```python
lambda:
lambda , :
```
### Comprehension
```python
= [i+1 for i in range(10)] # [1, 2, ..., 10]
= {i for i in range(10) if i > 5} # {6, 7, 8, 9}
= {i: i*2 for i in range(10)} # {0: 0, 1: 2, ..., 9: 18}
= (i+5 for i in range(10)) # (5, 6, ..., 14)
```
```python
out = [i+j for i in range(10) for j in range(10)]
```
#### Is the same as:
```python
out = []
for i in range(10):
for j in range(10):
out.append(i+j)
```
### Map, Filter, Reduce
```python
from functools import reduce
= map(lambda x: x + 1, range(10)) # (1, 2, ..., 10)
= filter(lambda x: x > 5, range(10)) # (6, 7, 8, 9)
= reduce(lambda out, x: out + x, range(10)) # 45
```
### Any, All
```python
= any() # False if empty.
= all(el[1] for el in ) # True if empty.
```
### If - Else
```python
if else
```
```python
>>> [a if a else 'zero' for a in (0, 1, 0, 3)]
['zero', 1, 'zero', 3]
```
### Namedtuple, Enum, Class
```python
from collections import namedtuple
Point = namedtuple('Point', 'x y')
point = Point(0, 0)
```
```python
from enum import Enum
Direction = Enum('Direction', 'n e s w')
Cutlery = Enum('Cutlery', {'fork': 1, 'knife': 2, 'spoon': 3})
```
```python
# Warning: Objects will share the objects that are initialized in the dictionary!
Creature = type('Creature', (), {'p': Point(0, 0), 'd': Direction.n})
creature = Creature()
```
Closure
-------
**We have a closure in Python when:**
* **A nested function references a value of its enclosing function and then**
* **the enclosing function returns the nested function.**
```python
def get_multiplier(a):
def out(b):
return a * b
return out
```
```python
>>> multiply_by_3 = get_multiplier(3)
>>> multiply_by_3(10)
30
```
* **If multiple nested functions within enclosing function reference the same value, that value gets shared.**
* **To dynamicaly acces functions first free variable use `'.__closure__[0].cell_contents'`.**
#### Or:
```python
from functools import partial
= partial(, [, , ...])
```
```python
>>> multiply_by_3 = partial(operator.mul, 3)
>>> multiply_by_3(10)
30
```
### Nonlocal
**If variable is assigned to anywhere in the scope, it is regarded as a local variable, unless it is declared as global or nonlocal.**
```python
def get_counter():
a = 0
def out():
nonlocal a
a += 1
return a
return out
```
```python
>>> counter = get_counter()
>>> counter(), counter(), counter()
(1, 2, 3)
```
Decorator
---------
**A decorator takes a function, adds some functionality and returns it.**
```python
@decorator_name
def function_that_gets_passed_to_decorator():
...
```
### Debugger Example
**Decorator that prints function's name every time it gets called.**
```python
from functools import wraps
def debug(func):
@wraps(func)
def out(*args, **kwargs):
print(func.__name__)
return func(*args, **kwargs)
return out
@debug
def add(x, y):
return x + y
```
* **Wraps is a helper decorator that copies metadata of function add() to function out().**
* **Without it `'add.__name__'` would return `'out'`.**
### LRU Cache
**Decorator that caches function's return values. All function's arguments must be hashable.**
```python
from functools import lru_cache
@lru_cache(maxsize=None)
def fib(n):
return n if n < 2 else fib(n-1) + fib(n-2)
```
```python
>>> [fib(n) for n in range(10)]
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
>>> fib.cache_info()
CacheInfo(hits=16, misses=10, maxsize=None, currsize=10)
```
### Parametrized Decorator
```python
from functools import wraps
def debug(print_result=False):
def decorator(func):
@wraps(func)
def out(*args, **kwargs):
result = func(*args, **kwargs)
print(func.__name__, result if print_result else '')
return result
return out
return decorator
@debug(print_result=True)
def add(x, y):
return x + y
```
Class
-----
```python
class :
def __init__(self, a):
self.a = a
def __repr__(self):
class_name = type(self).__name__
return f'{class_name}({self.a!r})'
def __str__(self):
return str(self.a)
@classmethod
def get_class_name(cls):
return cls.__name__
```
### Constructor Overloading
```python
class :
def __init__(self, a=None):
self.a = a
```
### Inheritance
```python
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Employee(Person):
def __init__(self, name, age, staff_num):
super().__init__(name, age)
self.staff_num = staff_num
```
### Comparable
* **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`.**
* **That means all objects compare not equal by default.**
```python
class MyComparable:
def __init__(self, a):
self.a = a
def __eq__(self, other):
if isinstance(other, type(self)):
return self.a == other.a
return False
```
### Hashable
* **Hashable object needs both hash() and eq() methods and it's hash value should never change.**
* **Hashable objects that compare equal must have the same hash value, meaning default hash() that returns `'id(self)'` will not do.**
* **That is why Python automatically makes classes unhashable if you only implement eq().**
```python
class MyHashable:
def __init__(self, a):
self.__a = copy.deepcopy(a)
@property
def a(self):
return self.__a
def __eq__(self, other):
if isinstance(other, type(self)):
return self.a == other.a
return False
def __hash__(self):
return hash(self.a)
```
### Sequence
* **Methods do not depend on each other, so they can be skipped if not needed.**
* **Any object with defined getitem() is considered iterable, even if it lacks iter().**
```python
class MySequence:
def __init__(self, a):
self.a = a
def __len__(self):
return len(self.a)
def __getitem__(self, i):
return self.a[i]
def __iter__(self):
for el in self.a:
yield el
```
### Callable
```python
class Counter:
def __init__(self):
self.a = 0
def __call__(self):
self.a += 1
return self.a
```
### Copy
```python
from copy import copy, deepcopy