Comprehensive Python Cheatsheet =============================== [Download text file](https://raw.githubusercontent.com/gto76/python-cheatsheet/master/README.md), [Fork me on GitHub](https://github.com/gto76/python-cheatsheet) or [Check out FAQ](https://github.com/gto76/python-cheatsheet/wiki/Frequently-Asked-Questions). ![Monty Python](web/image_888.jpeg) Contents -------- **   ** **1. Collections:** ** ** **[`List`](#list)**__,__ **[`Dict`](#dictionary)**__,__ **[`Set`](#set)**__,__ **[`Range`](#range)**__,__ **[`Enumerate`](#enumerate)**__,__ **[`Namedtuple`](#named-tuple)**__,__ **[`Iterator`](#iterator)**__,__ **[`Generator`](#generator)**__.__ **   ** **2. Types:** **          ** **[`Type`](#type)**__,__ **[`String`](#string)**__,__ **[`Regex`](#regex)**__,__ **[`Format`](#format)**__,__ **[`Numbers`](#numbers)**__,__ **[`Combinatorics`](#combinatorics)**__,__ **[`Datetime`](#datetime)**__.__ **   ** **3. Syntax:** **         ** **[`Args`](#arguments)**__,__ **[`Inline`](#inline)**__,__ **[`Closure`](#closure)**__,__ **[`Decorator`](#decorator)**__,__ **[`Class`](#class)**__,__ **[`Duck_Types`](#duck-types)**__,__ **[`Enum`](#enum)**__,__ **[`Exceptions`](#exceptions)**__.__ **   ** **4. System:** **        ** **[`Print`](#print)**__,__ **[`Input`](#input)**__,__ **[`Command_Line_Arguments`](#command-line-arguments)**__,__ **[`Open`](#open)**__,__ **[`Path`](#path)**__,__ **[`Command_Execution`](#command-execution)**__.__ **   ** **5. Data:** **             ** **[`CSV`](#csv)**__,__ **[`JSON`](#json)**__,__ **[`Pickle`](#pickle)**__,__ **[`SQLite`](#sqlite)**__,__ **[`Bytes`](#bytes)**__,__ **[`Struct`](#struct)**__,__ **[`Array`](#array)**__,__ **[`MemoryView`](#memory-view)**__,__ **[`Deque`](#deque)**__.__ **   ** **6. Advanced:** **   ** **[`Threading`](#threading)**__,__ **[`Introspection`](#introspection)**__,__ **[`Metaprograming`](#metaprograming)**__,__ **[`Operator`](#operator)**__,__ **[`Eval`](#eval)**__,__ **[`Coroutine`](#coroutine)**__.__ **   ** **7. Libraries:** **      ** **[`Progress_Bar`](#progress-bar)**__,__ **[`Plot`](#plot)**__,__ **[`Table`](#table)**__,__ **[`Curses`](#curses)**__,__ **[`Logging`](#logging)**__,__ **[`Scraping`](#scraping)**__,__ **[`Web`](#web)**__,__ **[`Profile`](#profile)**__,__ **                                 ** **[`NumPy`](#numpy)**__,__ **[`Image`](#image)**__,__ **[`Audio`](#audio)**__.__ Main ---- ```python if __name__ == '__main__': # Runs main() if file wasn't imported. main() ``` List ---- ```python = [from_inclusive : to_exclusive : ±step_size] ``` ```python .append() # Or: += [] .extend() # Or: += ``` ```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])) flatter_list = list(itertools.chain.from_iterable()) product_of_elems = functools.reduce(lambda out, x: out * x, ) list_of_chars = list() ``` ```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 or raises ValueError. .clear() # Removes all items. ``` Dictionary ---------- ```python = .keys() # Coll. of keys that reflects changes. = .values() # Coll. of values that reflects changes. = .items() # Coll. of key-value tuples. ``` ```python value = .get(key, default=None) # Returns default if key does not exist. value = .setdefault(key, default=None) # Same, but also adds default to dict. = collections.defaultdict() # Creates a dict with default value of type. = collections.defaultdict(lambda: 1) # Creates a dict with default value 1. ``` ```python .update() = dict() # Creates a dict from coll. of key-value pairs. = dict(zip(keys, values)) # Creates a dict from two collections. = dict.fromkeys(keys [, value]) # Creates a dict from collection 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 = ['red', 'blue', 'yellow', 'blue', 'red', 'blue'] >>> counter = Counter(colors) Counter({'blue': 3, 'red': 2, 'yellow': 1}) >>> counter.most_common()[0] ('blue', 3) ``` Set --- ```python = set() ``` ```python .add() # Or: |= {} .update() # Or: |= ``` ```python = .union() # Or: | = .intersection() # Or: & = .difference() # Or: - = .symmetric_difference() # Or: ^ = .issubset() # Or: <= = .issuperset() # Or: >= ``` ```python .remove() # Raises KeyError. .discard() # Doesn't raise an error. ``` ### Frozenset #### Is hashable, meaning it can be used as a key in a dictionary or as an element in a set. ```python = frozenset() ``` Range ----- ```python = range(to_exclusive) = range(from_inclusive, to_exclusive) = 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 ----------- * **Tuple is an immutable and hashable list.** * **Named tuple is its subclass with named elements.** ```python >>> from collections import namedtuple >>> Point = 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 from itertools import count, repeat, cycle, chain, islice ``` ```python = iter() = iter(, to_exclusive) # Sequence of return values until 'to_exclusive'. = next( [, default]) # Raises StopIteration or returns 'default' on end. ``` ```python = count(start=0, step=1) # Returns incremented value endlessly. = repeat( [, times]) # Returns element endlessly or 'times' times. = cycle() # Repeats the sequence indefinitely. ``` ```python = chain(, [, ...]) # Empties collections in order. = chain.from_iterable() # Empties collections inside a collection in order. ``` ```python = islice(, to_exclusive) = islice(, from_inclusive, to_exclusive) = islice(, from_inclusive, to_exclusive, step_size) ``` Generator --------- **Convenient way to implement the iterator protocol.** ```python def count(start, step): while True: yield start start += step ``` ```python >>> counter = count(10, 2) >>> next(counter), next(counter), next(counter) (10, 12, 14) ``` Type ---- * **Everything is an object.** * **Every object has a type.** * **Type and class are synonymous.** ```python = type() # Or: .__class__ = isinstance(, ) # Or: issubclass(type(), ) ``` ```python >>> type('a'), 'a'.__class__, str (, , ) ``` #### Some types do not have builtin names, so they must be imported: ```python from types import FunctionType, MethodType, LambdaType, GeneratorType ``` ### ABC **An abstract base class introduces virtual subclasses, that don’t inherit from it but are still recognized by isinstance() and issubclass().** ```python from numbers import Integral, Rational, Real, Complex, Number from collections.abc import Sequence, Collection, Iterable ``` ```python >>> isinstance(123, Number) True >>> isinstance([1, 2, 3], Iterable) True ``` String ------ ```python = .strip() # Strips all whitespace characters from both ends. = .strip('') # Strips all passed characters from both ends. ``` ```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, new [, count]) # Replaces 'old' with 'new' at most 'count' times. = .startswith() # Pass tuple of strings for multiple options. = .endswith() # Pass tuple of strings for multiple options. = .index() # Returns start index of first match. ``` ```python = .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 an operator 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 **Expressions below hold true for strings that contain only ASCII characters. Use capital letters for negation.** ```python '\d' == '[0-9]' # Digit '\s' == '[ \t\n\r\f\v]' # Whitespace '\w' == '[a-zA-Z0-9_]' # Alphanumeric ``` Format ------ ```python = f'{}, {}' = '{}, {}'.format(, ) ``` ### Attributes ```python >>> from collections import namedtuple >>> Person = namedtuple('Person', 'name height') >>> person = Person('Jean-Luc', 187) >>> f'{person.height}' '187' >>> '{p.height}'.format(p=person) '187' ``` ### General Options ```python {:<10} # ' ' {:^10} # ' ' {:>10} # ' ' ``` ```python {:.<10} # '......' {:>0} # '' ``` ### String Options **`'!r'` calls object's repr() method, instead of format(), to get a string.** ```python {'abcde'!r:<10} # "'abcde' " {'abcde':.3} # 'abc' {'abcde':10.3} # 'abc ' ``` ### Number Options ```python { 123456:10,} # ' 123,456' { 123456:10_} # ' 123_456' { 123456:+10} # ' +123456' {-123456:=10} # '- 123456' { 123456: } # ' 123456' {-123456: } # '-123456' ``` #### Float types: ```python {1.23456:10.3f} # ' 1.235' {1.23456:10.3e} # ' 1.235e+00' {1.23456:10.3%} # ' 123.456%' ``` #### Int types: ```python {90:c} # 'Z' {90:X} # '5A' {90:b} # '1011010' ``` Numbers ------- ### Basic Functions ```python = pow(, ) # Or: ** = abs() = round() = round(, ±ndigits) ``` ### Math ```python from math import e, pi, inf, nan from math import cos, acos, sin, asin, tan, atan, degrees, radians from math import log, log10, log2 ``` ### Statistics ```python from statistics import mean, median, variance, pvariance, pstdev ``` ### Random ```python from random import random, randint, choice, shuffle = random() = randint(from_inclusive, to_inclusive) = choice() shuffle() ``` Combinatorics ------------- * **Every function returns an iterator.** * **If you want to print the iterator, you need to pass it to the list() function!** ```python from itertools import product, combinations, combinations_with_replacement, permutations ``` ```python >>> product([0, 1], repeat=3) [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1), (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)] ``` ```python >>> product('ab', '12') [('a', '1'), ('a', '2'), ('b', '1'), ('b', '2')] ``` ```python >>> combinations('abc', 2) [('a', 'b'), ('a', 'c'), ('b', 'c')] ``` ```python >>> combinations_with_replacement('abc', 2) [('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'b'), ('b', 'c'), ('c', 'c')] ``` ```python >>> permutations('abc', 2) [('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'c'), ('c', 'a'), ('c', 'b')] ``` Datetime -------- * **Module 'datetime' provides 'date' ``, 'time' ``, 'datetime' `
` and 'timedelta' `` classes. All are immutable and hashable.** * **Time and datetime can be 'aware' ``, meaning they have defined timezone, or 'naive' ``, meaning they don't.** * **If object is naive it is presumed to be in system's timezone.** ```python from datetime import date, time, datetime, timedelta from dateutil.tz import UTC, tzlocal, gettz ``` ### Constructors ```python = date(year, month, day) = time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, fold=0)
= datetime(year, month, day, hour=0, minute=0, second=0, ...) = timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0) ``` * **Use `'.weekday()'` to get the day of the week (Mon == 0).** * **`'fold=1'` means second pass in case of time jumping back for one hour.** ### Now ```python = D/DT.today() # Current local date or naive datetime. = DT.utcnow() # Naive datetime from current UTC time. = DT.now() # Aware datetime from current tz time. ``` ### Timezone ```python = UTC # UTC timezone. London without DST. = tzlocal() # Local timezone. = gettz('/') # Timezone from 'Continent/City_Name' str. ``` ```python =
.astimezone() # Datetime, converted to passed timezone. = .replace(tzinfo=) # Unconverted object with new timezone. ``` ### Encode ```python = D/T/DT.fromisoformat('') # Object from ISO string.
= DT.strptime(, '') # Datetime from str, according to format. = D/DT.fromordinal() # D/DTn from days since Christ. = DT.fromtimestamp(, ) # DTa from seconds since Epoch in tz time. ``` * **ISO strings come in following forms: `'YYYY-MM-DD'`, `'HH:MM:SS.ffffff[±]'`, or both separated by `'T'`. Offset is formatted as: `'HH:MM'`.** * **On Unix systems Epoch is `'1970-01-01 00:00 UTC'`, `'1970-01-01 01:00 CET'`, ...** ### Decode ```python = .isoformat() # ISO string representation. = .strftime('') # Custom string representation. = .toordinal() # Days since Christ, ignoring time and tz. =
.timestamp() # Seconds since Epoch in local time or tz. ``` ### Format ```python >>> from datetime import datetime >>> dt = datetime.strptime('2015-05-14 23:39:00.00 +0200', '%Y-%m-%d %H:%M:%S.%f %z') >>> dt.strftime("%A, %dth of %B '%y, %I:%M%p %Z") "Thursday, 14th of May '15, 11:39PM UTC+02:00" ``` #### Rest of the codes: * **`'a'` - Weekday, abbreviated name.** * **`'b'` - Month, abbreviated name.** Arguments --------- ### Inside Function Call ```python () # f(0, 0) () # f(x=0, y=0) (, ) # f(0, y=0) ``` ### Inside Function Definition ```python def f(): # def f(x, y): def f(): # def f(x=0, y=0): def f(, ): # def f(x, y=0): ``` Splat Operator -------------- ### Inside Function Call **Splat expands a collection into positional arguments, while splatty-splat expands a dictionary into keyword arguments.** ```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) ``` ### Inside Function Definition **Splat combines zero or more positional arguments into a tuple, while splatty-splat combines zero or more keyword arguments into a dictionary.** ```python def add(*a): return sum(a) ``` ```python >>> add(1, 2, 3) 6 ``` #### Legal argument combinations: ```python def f(x, y, z): # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3) | f(1, 2, 3) def f(*, x, y, z): # f(x=1, y=2, z=3) def f(x, *, y, z): # f(x=1, y=2, z=3) | f(1, y=2, z=3) def f(x, y, *, z): # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3) ``` ```python def f(*args): # f(1, 2, 3) def f(x, *args): # f(1, 2, 3) def f(*args, z): # f(1, 2, z=3) def f(x, *args, z): # f(1, 2, z=3) ``` ```python def f(**kwargs): # f(x=1, y=2, z=3) def f(x, **kwargs): # f(x=1, y=2, z=3) | f(1, y=2, z=3) def f(*, x, **kwargs): # f(x=1, y=2, z=3) ``` ```python def f(*args, **kwargs): # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3) | f(1, 2, 3) def f(x, *args, **kwargs): # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3) | f(1, 2, 3) def f(*args, y, **kwargs): # f(x=1, y=2, z=3) | f(1, y=2, z=3) def f(x, *args, z, **kwargs): # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3) ``` ### Other Uses ```python = [* [, ...]] = {* [, ...]} = (*, [...]) = {** [, ...]} ``` ```python head, *body, tail = ``` 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+5 for i in range(10)) # (5, 6, ..., 14) = {i: i*2 for i in range(10)} # {0: 0, 1: 2, ..., 9: 18} ``` ```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, Dataclass ```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') direction = Direction.n ``` ```python from dataclasses import make_dataclass Creature = make_dataclass('Creature', ['location', 'direction']) creature = Creature(Point(0, 0), Direction.n) ``` 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 dynamically access function's first free variable use `'.__closure__[0].cell_contents'`.** ### Partial ```python from functools import partial = partial( [, , , ...]) ``` ```python >>> import operator as op >>> multiply_by_3 = partial(op.mul, 3) >>> multiply_by_3(10) 30 ``` ### Nonlocal **If variable is being assigned to anywhere in the scope, it is regarded as a local variable, unless it is declared as a 'global' or a 'nonlocal'.** ```python def get_counter(): i = 0 def out(): nonlocal i i += 1 return i 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-2) + fib(n-1) ``` * **Recursion depth is limited to 1000 by default. To increase it use `'sys.setrecursionlimit()'`.** ### Parametrized Decorator **A decorator that accepts arguments and returns a normal decorator that accepts a function.** ```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 = self.__class__.__name__ return f'{class_name}({self.a!r})' def __str__(self): return str(self.a) @classmethod def get_class_name(cls): return cls.__name__ ``` * **Return value of repr() should be unambiguous and of str() readable.** * **If only repr() is defined, it will also be used for str().** ### 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 ``` ### Multiple Inheritance ```python class A: pass class B: pass class C(A, B): pass ``` **MRO determines the order in which parent classes are traversed when searching for a method:** ```python >>> C.mro() [, , , ] ``` ### Property ```python class MyClass: @property def a(self): return self._a @a.setter def a(self, value): self._a = value ``` ```python >>> el = MyClass() >>> el.a = 123 >>> el.a 123 ``` ### Dataclass **Decorator that automatically generates init(), repr() and eq() special methods.** ```python from dataclasses import dataclass, field @dataclass(order=False, frozen=False) class : : : = : list/dict/set = field(default_factory=list/dict/set) ``` * **An object can be made sortable with `'order=True'` or immutable with `'frozen=True'`.** * **Function field() is needed because `': list = []'` would make a list that is shared among all instances.** * **Default_factory can be any callable.** ### Copy ```python from copy import copy, deepcopy = copy() = deepcopy() ``` Duck Types ---------- **A duck type is an implicit type that prescribes a set of special methods. Any object that has those methods defined is considered a member of that duck type.** ### 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.** * **Only left side object has eq() method called, unless it returns 'NotImplemented', in which case the right object is consulted.** ```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 NotImplemented ``` ### Hashable * **Hashable object needs both hash() and eq() methods and its 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 NotImplemented def __hash__(self): return hash(self.a) ``` ### Sortable * **With 'total_ordering' decorator you only need to provide one of lt(), gt(), le() or ge() special methods.** ```python from functools import total_ordering @total_ordering class MySortable: def __init__(self, a): self.a = a def __eq__(self, other): if isinstance(other, type(self)): return self.a == other.a return NotImplemented def __lt__(self, other): if isinstance(other, type(self)): return self.a < other.a return NotImplemented ``` ### Collection * **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 MyCollection: def __init__(self, a): self.a = a def __len__(self): return len(self.a) def __getitem__(self, i): return self.a[i] def __setitem__(self, i, el): self.a[i] = el def __contains__(self, el): return el in self.a def __iter__(self): for el in self.a: yield el ``` ### Callable ```python class Counter: def __init__(self): self.i = 0 def __call__(self): self.i += 1 return self.i ``` ```python >>> counter = Counter() >>> counter(), counter(), counter() (1, 2, 3) ``` ### Context Manager ```python class MyOpen(): def __init__(self, filename): self.filename = filename def __enter__(self): self.file = open(self.filename) return self.file def __exit__(self, *args): self.file.close() ``` ```python >>> with open('test.txt', 'w') as file: ... file.write('Hello World!') >>> with MyOpen('test.txt') as file: ... print(file.read()) Hello World! ``` Enum ---- ```python from enum import Enum, auto class (Enum): = = , = auto() @classmethod def get_member_names(cls): return [a.name for a in cls.__members__.values()] ``` ```python = . = [''] = () name = .name value = .value ``` ```python list_of_members = list() member_names = [a.name for a in ] member_values = [a.value for a in ] random_member = random.choice(list()) ``` ### Inline ```python Cutlery = Enum('Cutlery', ['fork', 'knife', 'spoon']) Cutlery = Enum('Cutlery', 'fork knife spoon') Cutlery = Enum('Cutlery', {'fork': 1, 'knife': 2, 'spoon': 3}) ``` #### Functions can not be values, so they must be wrapped: ```python from functools import partial LogicOp = Enum('LogicOp', {'AND': partial(lambda l, r: l and r), 'OR' : partial(lambda l, r: l or r)}) ``` Exceptions ---------- ```python while True: try: x = int(input('Please enter a number: ')) except ValueError: print('Oops! That was no valid number. Try again...') else: print('Thank you.') break ``` ### Raising Exception ```python raise ValueError('A very specific message!') ``` ### Finally ```python >>> try: ... raise KeyboardInterrupt ... finally: ... print('Goodbye, world!') Goodbye, world! Traceback (most recent call last): File "", line 2, in KeyboardInterrupt ``` Print ----- ```python print(, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ``` * **Use `'file=sys.stderr'` for errors.** ### Pretty Print ```python >>> from pprint import pprint >>> pprint(dir()) ['__annotations__', '__builtins__', '__doc__', ...] ``` Input ----- * **Reads a line from user input or pipe if present.** * **Trailing newline gets stripped.** * **Prompt string is printed to the standard output before reading input.** ```python = input(prompt=None) ``` #### Prints lines until EOF: ```python while True: try: print(input()) except EOFError: break ``` Command Line Arguments ---------------------- ```python import sys script_name = sys.argv[0] arguments = sys.argv[1:] ``` ### Argparse ```python from argparse import ArgumentParser, FileType p = ArgumentParser(description=) p.add_argument('-', '--', action='store_true') # Flag p.add_argument('-', '--', type=) # Option p.add_argument('', type=, nargs=1) # Argument p.add_argument('', type=, nargs='+') # Arguments args = p.parse_args() value = args. ``` * **Use `'help='` for argument description.** * **Use `'type=FileType()'` for files.** Open ---- **Opens a file and returns a corresponding file object.** ```python = open('', mode='r', encoding=None) ``` ### Modes * **`'r'` - Read (default).** * **`'w'` - Write (truncate).** * **`'x'` - Write or fail if the file already exists.** * **`'a'` - Append.** * **`'w+'` - Read and write (truncate).** * **`'r+'` - Read and write from the start.** * **`'a+'` - Read and write from the end.** * **`'t'` - Text mode (default).** * **`'b'` - Binary mode.** ### File ```python .seek(0) # Moves to the start of the file. .seek(offset) # Moves 'offset' chars/bytes from the start. .seek(offset, ) # Anchor: 0 start, 1 current pos., 2 end. ``` ```python = .read(size=-1) # Reads 'size' chars/bytes or until EOF. = .readline() # Returns a line. = .readlines() # Returns a list of lines. = next() # Returns a line using buffer. Do not mix. ``` ```python .write() # Writes a string or bytes object. .writelines() # Writes a list of strings or bytes objects. .flush() # Flushes write buffer. ``` * **Methods do not add or strip trailing newlines.** ### Read Text from File ```python def read_file(filename): with open(filename, encoding='utf-8') as file: return file.readlines() ``` ### Write Text to File ```python def write_to_file(filename, text): with open(filename, 'w', encoding='utf-8') as file: file.write(text) ``` Path ---- ```python from os import path, listdir = path.exists('') = path.isfile('') = path.isdir('') = listdir('') ``` ```python >>> from glob import glob >>> glob('../*.gif') ['1.gif', 'card.gif'] ``` ### Pathlib ```python from pathlib import Path cwd = Path() = Path('' [, '', , ...]) = / '' / '' ``` ```python = .exists() = .is_file() = .is_dir() = .iterdir() ``` ```python = .glob('') ``` ```python = str() # Returns path as a string. = .parts # Returns all components as strings. = .resolve() # Returns absolute Path without symlinks. ``` ```python = .name # Final component. = .stem # Final component without extension. = .suffix # Final component's extension. = .parent # Path without final component. ``` Command Execution ----------------- ```python import os = os.popen().read() ``` ### Subprocess ```python >>> import subprocess, shlex >>> a = subprocess.run(shlex.split('ls -a'), stdout=subprocess.PIPE) >>> a.stdout b'.\n..\nfile1.txt\nfile2.txt\n' >>> a.returncode 0 ``` CSV --- ```python import csv ``` ### Read Rows from CSV File ```python def read_csv_file(filename): with open(filename, encoding='utf-8') as file: return csv.reader(file, delimiter=';') ``` ### Write Rows to CSV File ```python def write_to_csv_file(filename, rows): with open(filename, 'w', encoding='utf-8') as file: writer = csv.writer(file, delimiter=';') writer.writerows(rows) ``` JSON ---- ```python import json = json.dumps(, ensure_ascii=True, indent=None) = json.loads() ``` ### Read Object from JSON File ```python def read_json_file(filename): with open(filename, encoding='utf-8') as file: return json.load(file) ``` ### Write Object to JSON File ```python def write_to_json_file(filename, an_object): with open(filename, 'w', encoding='utf-8') as file: json.dump(an_object, file, ensure_ascii=False, indent=2) ``` Pickle ------ ```python import pickle = pickle.dumps() = pickle.loads() ``` ### Read Object from File ```python def read_pickle_file(filename): with open(filename, 'rb') as file: return pickle.load(file) ``` ### Write Object to File ```python def write_to_pickle_file(filename, an_object): with open(filename, 'wb') as file: pickle.dump(an_object, file) ``` SQLite ------ ```python import sqlite3 db = sqlite3.connect('') ... db.close() ``` ### Read ```python cursor = db.execute('') if cursor: = cursor.fetchone() # First row. = cursor.fetchall() # Remaining rows. ``` ### Write ```python db.execute('') db.commit() ``` Bytes ----- **Bytes object is an immutable sequence of single bytes. Mutable version is called 'bytearray'.** ```python = b'' = [] = [] = list() = b''.join() ``` ### Encode ```python = .encode(encoding='utf-8') = .to_bytes(, byteorder='big|little', signed=False) = bytes.fromhex('') ``` ### Decode ```python = .decode(encoding='utf-8') = int.from_bytes(, byteorder='big|little', signed=False) = .hex() ``` ### Read Bytes from File ```python def read_bytes(filename): with open(filename, 'rb') as file: return file.read() ``` ### Write Bytes to File ```python def write_bytes(filename, bytes_obj): with open(filename, 'wb') as file: file.write(bytes_obj) ``` Struct ------ * **Module that performs conversions between Python values and a C struct, represented as a Python bytes object.** * **Machine’s native type sizes and byte order are used by default.** ```python from struct import pack, unpack, iter_unpack, calcsize = pack('', [, , ...]) = unpack('', ) = iter_unpack('', ) ``` ### Example ```python >>> pack('>hhl', 1, 2, 3) b'\x00\x01\x00\x02\x00\x00\x00\x03' >>> unpack('>hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03') (1, 2, 3) >>> calcsize('>hhl') 8 ``` ### Format #### For standard sizes start format string with: * **`'='` - native byte order** * **`'<'` - little-endian** * **`'>'` - big-endian** #### Use capital letter for unsigned type. Standard sizes are in brackets: * **`'x'` - pad byte** * **`'c'` - char (1)** * **`'h'` - short (2)** * **`'i'` - int (4)** * **`'l'` - long (4)** * **`'q'` - long long (8)** * **`'f'` - float (4)** * **`'d'` - double (8)** Array ----- **List that can hold only elements of predefined type. Available types are listed above.** ```python from array import array = array('' [, ]) ``` Memory View ----------- **Used for accessing the internal data of an object that supports the buffer protocol.** ```python = memoryview( / / ) .release() ``` Deque ----- **Thread-safe list with efficient appends and pops from either side. Pronounced "deck".** ```python from collections import deque = deque(, maxlen=None) ``` ```python .appendleft() = .popleft() ``` ```python .extendleft() # Collection gets reversed. .rotate(n=1) # Rotates elements to the right. ``` Threading --------- ```python from threading import Thread, RLock ``` ### Thread ```python thread = Thread(target=, args=(, )) thread.start() ... thread.join() ``` ### Lock ```python lock = RLock() lock.acquire() ... lock.release() ``` #### Or: ```python with lock: ... ``` Introspection ------------- **Inspecting code at runtime.** ### Variables ```python = dir() # Names of variables in current scope. = locals() # Dict of local variables. Also vars(). = globals() # Dict of global variables. ``` ### Attributes ```python = vars() = hasattr(, '') value = getattr(, '') setattr(, '', value) ``` ### Parameters ```python from inspect import signature = signature() no_of_params = len(.parameters) param_names = list(.parameters.keys()) ``` Metaprograming -------------- **Code that generates code.** ### Type **Type is the root class. If only passed the object it returns its type (class). Otherwise it creates a new class.** ```python = type(, , ) ``` ```python >>> Z = type('Z', (), {'a': 'abcde', 'b': 12345}) >>> z = Z() ``` ### Meta Class **Class that creates class.** ```python def my_meta_class(name, parents, attrs): attrs['a'] = 'abcde' return type(name, parents, attrs) ``` #### Or: ```python class MyMetaClass(type): def __new__(cls, name, parents, attrs): attrs['a'] = 'abcde' return type.__new__(cls, name, parents, attrs) ``` * **New() is a class method that gets called before init(). If it returns an instance of its class, then that instance gets passed to init() as a 'self' argument.** * **It receives the same arguments as init(), except for the first one that specifies the desired class of returned instance (**`'MyMetaClass'` **in our case).** * **New() can also be called directly, usually from a new() method of a child class (**`def __new__(cls): return super().__new__(cls)`**), in which case init() is not called.** ### Metaclass Attribute **When class is created it checks if it has metaclass defined. If not, it recursively checks if any of his parents has it defined and eventually comes to type().** ```python class MyClass(metaclass=MyMetaClass): b = 12345 ``` ```python >>> MyClass.a, MyClass.b ('abcde', 12345) ``` #### Type diagram (str is an instance of type, ...): ```text +---------+-------------+ | Classes | Metaclasses | +---------+-------------| | MyClass > MyMetaClass | | | v | | object ---> type <+ | | | ^ +---+ | | str -------+ | +---------+-------------+ ``` #### Inheritance diagram (str is a subclass of object, ...): ```text +---------+-------------+ | Classes | Metaclasses | +---------+-------------| | MyClass | MyMetaClass | | v | v | | object <--- type | | ^ | | | str | | +---------+-------------+ ``` Operator -------- ```python from operator import add, sub, mul, truediv, floordiv, mod, pow, neg, abs from operator import eq, ne, lt, le, gt, ge from operator import not_, and_, or_ from operator import itemgetter, attrgetter, methodcaller ``` ```python import operator as op product_of_elems = functools.reduce(op.mul, ) sorted_by_second = sorted(, key=op.itemgetter(1)) sorted_by_both = sorted(, key=op.itemgetter(1, 0)) LogicOp = enum.Enum('LogicOp', {'AND': op.and_, 'OR' : op.or_}) last_el = op.methodcaller('pop')() ``` Eval ---- ```python >>> from ast import literal_eval >>> literal_eval('1 + 2') 3 >>> literal_eval('[1, 2, 3]') [1, 2, 3] >>> literal_eval('abs(1)') ValueError: malformed node or string ``` Coroutine --------- * **Similar to generator, but generator pulls data through the pipe with iteration, while coroutine pushes data into the pipeline with send().** * **Coroutines provide more powerful data routing possibilities than iterators.** * **If you build a collection of simple data processing components, you can glue them together into complex arrangements of pipes, branches, merging, etc.** ### Helper Decorator * **All coroutines must be "primed" by first calling next().** * **Remembering to call next() is easy to forget.** * **Solved by wrapping coroutines with a decorator:** ```python def coroutine(func): def out(*args, **kwargs): cr = func(*args, **kwargs) next(cr) return cr return out ``` ### Pipeline Example ```python def reader(target): for i in range(10): target.send(i) target.close() @coroutine def adder(target): while True: value = (yield) target.send(value + 100) @coroutine def printer(): while True: value = (yield) print(value) reader(adder(printer())) # 100, 101, ..., 109 ```

Libraries ========= Progress Bar ------------ ```python # $ pip3 install tqdm from tqdm import tqdm from time import sleep for i in tqdm([1, 2, 3]): sleep(0.2) for i in tqdm(range(100)): sleep(0.02) ``` Plot ---- ```python # $ pip3 install matplotlib from matplotlib import pyplot pyplot.plot( [, , ...]) pyplot.savefig() pyplot.show() ``` Table ----- #### Prints a CSV file as an ASCII table: ```python # $ pip3 install tabulate from tabulate import tabulate import csv with open(, encoding='utf-8') as file: lines = csv.reader(file, delimiter=';') headers = [header.title() for header in next(lines)] table = tabulate(lines, headers) print(table) ``` Curses ------ ```python from curses import wrapper, ascii def main(): wrapper(draw) def draw(screen): screen.clear() screen.addstr(0, 0, 'Press ESC to quit.') while screen.getch() != ascii.ESC: pass def get_border(screen): from collections import namedtuple P = namedtuple('P', 'y x') height, width = screen.getmaxyx() return P(height-1, width-1) if __name__ == '__main__': main() ``` Logging ------- ```python # $ pip3 install loguru from loguru import logger ``` ```python logger.add('debug_{time}.log', colorize=True) # Connects a log file. logger.add('error_{time}.log', level='ERROR') # Another file for errors or higher. logger.('A logging message.') ``` * **Levels: `'debug'`, `'info'`, `'success'`, `'warning'`, `'error'`, `'critical'`.** ### Exceptions **Error description, stack trace and values of variables are appended automatically.** ```python try: ... except : logger.exception('An error happened.') ``` ### Rotation **Parameter that sets a condition when a new log file is created.** ```python rotation=||| ``` * **`''` - Max file size in bytes.** * **`''` - Max age of a file.** * **`'