/
githubmirror
/
python-cheatsheet
Обзор
Документация
Войти
/
githubmirror
/
python-cheatsheet
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
index.html
2 942 строки
321 KB
Jure Šorn
Highlights
27 июл 2026, 22:49
27 июл 2026, 22:49
43e0d05
Код
Авторство
О чём код?
<!DOCTYPE html> <html class="ocks-org do-not-copy" lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" /> <title>Comprehensive Python Cheatsheet</title> <meta name="description" content="Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language."> <link rel="icon" href="web/favicon.png"> <link rel="stylesheet" href="web/default.min.css"> <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.css"> <link rel="stylesheet" href="web/style.css"> <script> // Uses dark theme 3 if it's specified in query string orbrowser prefers dark mode and // theme is not explicitly set. if ((window.location.search.search(/[?&]theme=dark3/) !== -1) || ((window.location.search.search(/[?&]theme=/) == -1) && (window.matchMedia('(prefers-color-scheme: dark)').matches))) { document.write("<link rel=\"stylesheet\" href=\"web/default_dark3.min.css\">"); document.write("<link rel=\"stylesheet\" href=\"web/style_dark3.css\">"); } else if (window.location.search.search(/[?&]theme=dark2/) !== -1) { document.write("<link rel=\"stylesheet\" href=\"web/default_dark2.min.css\">"); document.write("<link rel=\"stylesheet\" href=\"web/style_dark2.css\">"); } else if (window.location.search.search(/[?&]theme=dark1/) !== -1) { document.write("<link rel=\"stylesheet\" href=\"web/default_dark1.min.css\">"); document.write("<link rel=\"stylesheet\" href=\"web/style_dark1.css\">"); } else if (window.location.search.search(/[?&]theme=dark/) !== -1) { document.write("<link rel=\"stylesheet\" href=\"web/default_dark.min.css\">"); document.write("<link rel=\"stylesheet\" href=\"web/style_dark.css\">"); } </script> <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="Comprehensive Python Cheatsheet"> <meta name="twitter:description" content="Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language."> <meta name="twitter:image" content="https://gto76.github.io/python-cheatsheet/web/image_social_4.png"> <meta property="og:url" content="https://gto76.github.io/python-cheatsheet/"> <meta property="og:title" content="Comprehensive Python Cheatsheet"> <meta property="og:description" content="Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language."> <meta property="og:site_name" content="gto76.github.io"> <meta property="og:image" content="https://gto76.github.io/python-cheatsheet/web/image_social_4.png"> <meta property="og:type" content="article"> <meta itemprop="url" content="https://gto76.github.io/python-cheatsheet/"> <meta itemprop="name" content="Comprehensive Python Cheatsheet"> <meta itemprop="description" content="Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language."> <meta itemprop="image" content="https://gto76.github.io/python-cheatsheet/web/image_social_4.png"> <meta name="google-site-verification" content="w3rvuG0D1kUm_w20qsJecSEZh59Am8jK4eSPVU83e_M"> <meta name="viewport" id="viewport-meta"> </head> <body style="margin-top: 17.1px"> <div class="pagebreak"></div> <header> <aside>July 27, 2026</aside> <a href="https://gto76.github.io" rel="author">Jure Šorn</a> </header> <div><h1 id="comprehensivepythoncheatsheet">Comprehensive Python Cheatsheet</h1><p class="banner"><sup><a href="https://raw.githubusercontent.com/gto76/python-cheatsheet/main/README.md">Download text file</a>, <a href="https://github.com/gto76/python-cheatsheet">Fork me on GitHub</a>, <a href="https://github.com/gto76/python-cheatsheet/wiki/Frequently-Asked-Questions">Check out FAQ</a> or <a href="index.html?theme=dark3">Switch to dark theme</a>. </sup></p><p class="banner" style="margin-bottom: 20px; padding-bottom: 7px;"><img src="web/image_888.jpeg" alt="Monty Python" style="width: 909px;"></p><script> // Changes the banner image and link-to-theme if "theme=dark" is in query string // or if browser prefers dark mode and theme is not explicitly set. const theme_not_set_in_query = window.location.search.search(/[?&]theme=light/) == -1 const browser_prefers_dark = window.matchMedia('(prefers-color-scheme: dark)').matches; if ((window.location.search.search(/[?&]theme=dark/) !== -1) || (theme_not_set_in_query && browser_prefers_dark)) { activateDarkMode(); } function activateDarkMode() { var link_to_theme = document.createElement("a") link_to_theme.href = "index.html?theme=light" link_to_theme.text = "Switch to light theme" document.getElementsByClassName("banner")[0].firstChild.children[3].replaceWith(link_to_theme) var img_dark = document.createElement("img"); img_dark.src = "web/image_orig_blue6.png"; img_dark.alt = "Monthy Python"; if ((window.location.search.search(/[?&]theme=dark2/) !== -1) || (window.location.search.search(/[?&]theme=dark3/) !== -1) || (theme_not_set_in_query && browser_prefers_dark)) { img_dark.style = "width: 910px;"; } else { img_dark.style = "width: 960px;"; } document.getElementsByClassName("banner")[1].firstChild.replaceWith(img_dark); } </script><pre style="border-left: none;padding-left: 1.9px;"><code class="hljs bash" style="line-height: 1.327em;"><strong>ToC</strong> = { <strong><span class="hljs-string"><span class="hljs-string">'1. Collections'</span></span></strong>: [<a href="#list">List</a>, <a href="#dictionary">Dictionary</a>, <a href="#set">Set</a>, <a href="#tuple">Tuple</a>, <a href="#range">Range</a>, <a href="#enumerate">Enumerate</a>, <a href="#iterator">Iterator</a>, <a href="#generator">Generator</a>], <strong><span class="hljs-string"><span class="hljs-string">'2. Data Types'</span></span></strong>: [<a href="#type">Type</a>, <a href="#string">String</a>, <a href="#regex">Regular_Exp</a>, <a href="#format">Format</a>, <a href="#numbers">Numbers</a>, <a href="#combinatorics">Combinatorics</a>, <a href="#datetime">Datetime</a>], <strong><span class="hljs-string"><span class="hljs-string">'3. Syntax Rules'</span></span></strong>: [<a href="#function">Function</a>, <a href="#inline">Inline</a>, <a href="#import">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Type</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Except</a>], <strong><span class="hljs-string"><span class="hljs-string">'4. System Calls'</span></span></strong>: [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#arguments">Command_Line_Arguments</a>, <a href="#open">Open</a>, <a href="#paths">Path</a>, <a href="#oscommands">OS_Commands</a>], <strong><span class="hljs-string"><span class="hljs-string">'5. Data Formats'</span></span></strong>: [<a href="#json">JSON</a>, <a href="#pickle">Pickle</a>, <a href="#csv">CSV</a>, <a href="#sqlite">SQLite</a>, <a href="#bytes">Bytes</a>, <a href="#struct">Struct</a>, <a href="#array">Array</a>, <a href="#memoryview">Memory_View</a>, <a href="#deque">Deque</a>], <strong><span class="hljs-string"><span class="hljs-string">'6. Misc Topics'</span></span></strong>: [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Statement</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#threading">Threads</a>, <a href="#asyncio">Asyncio</a>], <strong><span class="hljs-string"><span class="hljs-string">'7. Pip Packages'</span></span></strong>: [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>, <a href="#consoleapp">Console_App</a>, <a href="#guiapp">GUI</a>, <a href="#scraping">Scraping</a>, <a href="#webapp">Web</a>, <a href="#profiling">Profile</a>], <strong><span class="hljs-string"><span class="hljs-string">'8. Multimedia'</span></span></strong>: [<a href="#numpy">NumPy</a>, <a href="#image">Image</a>, <a href="#animation">Animation</a>, <a href="#audio">Audio</a>, <a href="#synthesizer">Synthesizer</a>, <a href="#pygame">Pygame</a>, <a href="#pandas">Pandas</a>, <a href="#plotly">Plotly</a>] } </code></pre></div> <div><h2 id="main"><a href="#main" name="main">#</a>Main</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>: <span class="hljs-comment"># Skips indented lines of code if file was imported.</span> main() <span class="hljs-comment"># Executes user-defined `def main(): ...` function.</span> </code></pre></div> <div><h2 id="list"><a href="#list" name="list">#</a>List</h2><pre><code class="python language-python hljs"><list> = [<el>, <el>, ...] <span class="hljs-comment"># Creates new list object. E.g. `list_a = [1, 2, 3]`.</span> </code></pre></div> <pre><code class="python language-python hljs"><el> = <list>[index] <span class="hljs-comment"># First index is 0, last -1. Also `<list>[i] = <el>`.</span> <list> = <list>[<slice>] <span class="hljs-comment"># Also <list>[from_inclusive : to_exclusive : ±step].</span> </code></pre> <pre><code class="python language-python hljs"><list>.append(<el>) <span class="hljs-comment"># Appends element to the end. Or `<list> += [<el>]`.</span> <list>.extend(<coll>) <span class="hljs-comment"># Appends collection's items. Or `<list> += <coll>`.</span> </code></pre> <pre><code class="python language-python hljs"><list>.sort() <span class="hljs-comment"># Sorts in ascending order. Accepts `reverse=True`.</span> <list>.reverse() <span class="hljs-comment"># Reverses the order of elements. Takes linear time.</span> <list> = sorted(<coll>) <span class="hljs-comment"># Returns a new sorted list. Accepts `reverse=True`.</span> <iter> = reversed(<list>) <span class="hljs-comment"># Returns reversed iterator. Also list(<iterator>).</span> </code></pre> <pre><code class="python language-python hljs"><el> = max(<coll>) <span class="hljs-comment"># Returns the largest element. Also min(<el>, <el>).</span> <num> = sum(<coll>) <span class="hljs-comment"># Returns a sum of elements. Also math.prod(<coll>).</span> </code></pre> <pre><code class="python language-python hljs">elementwise_sum = [sum(pair) <span class="hljs-keyword">for</span> pair <span class="hljs-keyword">in</span> zip(list_a, list_b)] sorted_by_second = sorted(<coll>, key=<span class="hljs-keyword">lambda</span> pair: pair[<span class="hljs-number">1</span>]) sorted_by_both = sorted(<coll>, key=<span class="hljs-keyword">lambda</span> p: (p[<span class="hljs-number">1</span>], p[<span class="hljs-number">0</span>])) flatter_list = list(itertools.chain.from_iterable(<list>)) </code></pre> <ul> <li><strong>For details about sort(), sorted(), max() and min() see <a href="#sortable">Sortable</a>.</strong></li> <li><strong>Module <a href="#operator">operator</a> has function itemgetter() that can replace listed <a href="#lambda">lambdas</a>.</strong></li> <li><strong>This text uses the term collection instead of <a href="#abstractbaseclasses">iterable</a>. For rationale see <a href="#iterableducktypes">duck types</a>.</strong></li> </ul> <pre><code class="python language-python hljs"><int> = len(<list/dict/set/…>) <span class="hljs-comment"># Returns number of items. Doesn't accept iterators.</span> <int> = <list>.count(<el>) <span class="hljs-comment"># Counts occurrences. Also `if <el> in <coll>: ...`.</span> <int> = <list>.index(<el>) <span class="hljs-comment"># Returns index of first occ. or raises ValueError.</span> <el> = <list>.pop() <span class="hljs-comment"># Removes item from the end (or at index if passed).</span> <list>.insert(<int>, <el>) <span class="hljs-comment"># Inserts item at index and shifts remaining items.</span> <list>.remove(<el>) <span class="hljs-comment"># Removes the first occurrence or raises ValueError.</span> <list>.clear() <span class="hljs-comment"># Removes all items. Also provided by dict and set.</span> </code></pre> <div><h2 id="dictionary"><a href="#dictionary" name="dictionary">#</a>Dictionary</h2><pre><code class="python language-python hljs"><dict> = {key: val, key: val, ...} <span class="hljs-comment"># Use `<dict>[key]` to get or assign the value.</span> </code></pre></div> <pre><code class="python language-python hljs"><view> = <dict>.keys() <span class="hljs-comment"># A collection of keys reflecting all changes.</span> <view> = <dict>.values() <span class="hljs-comment"># A collection of values that reflects changes.</span> <view> = <dict>.items() <span class="hljs-comment"># Coll. of tuples. Each contains key and value.</span> </code></pre> <pre><code class="python language-python hljs">value = <dict>.get(key, default=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Returns 'default' argument if key is missing.</span> value = <dict>.setdefault(key, default) <span class="hljs-comment"># Returns/writes 'default' when key is missing.</span> <dict> = collections.defaultdict(<type>) <span class="hljs-comment"># Dict with automatic default value `<type>()`.</span> </code></pre> <pre><code class="python language-python hljs"><dict> = dict(<collection>) <span class="hljs-comment"># Creates a dict from coll. of key-value pairs.</span> <dict> = dict(zip(keys, values)) <span class="hljs-comment"># Creates key-value pairs from two collections.</span> <dict> = dict.fromkeys(keys [, value]) <span class="hljs-comment"># Items get value None if only keys are passed.</span> </code></pre> <pre><code class="python language-python hljs"><dict>.update(<dict>) <span class="hljs-comment"># Adds items to dict. Passed dict has priority.</span> value = <dict>.pop(key) <span class="hljs-comment"># Removes item or raises KeyError when missing.</span> {k <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> <dict>.items() <span class="hljs-keyword">if</span> v == <span class="hljs-number">123</span>} <span class="hljs-comment"># Returns a set of keys whose value equals 123.</span> {k: v <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> <dict>.items() <span class="hljs-keyword">if</span> k <span class="hljs-keyword">in</span> ks} <span class="hljs-comment"># Returns a dict of items with specified keys.</span> </code></pre> <div><h3 id="counter">Counter</h3><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> Counter <span class="hljs-meta">>>> </span>counter = Counter([<span class="hljs-string">'blue'</span>, <span class="hljs-string">'blue'</span>, <span class="hljs-string">'red'</span>]) <span class="hljs-meta">>>> </span>counter[<span class="hljs-string">'yellow'</span>] += <span class="hljs-number">3</span> <span class="hljs-meta">>>> </span>print(counter.most_common()) [(<span class="hljs-string">'yellow'</span>, <span class="hljs-number">3</span>), (<span class="hljs-string">'blue'</span>, <span class="hljs-number">2</span>), (<span class="hljs-string">'red'</span>, <span class="hljs-number">1</span>)] </code></pre></div> <div><h2 id="set"><a href="#set" name="set">#</a>Set</h2><pre><code class="python language-python hljs"><set> = {<el>, <el>, ...} <span class="hljs-comment"># Coll. of unique items. Also set(), set(<coll>).</span> </code></pre></div> <pre><code class="python language-python hljs"><set>.add(<el>) <span class="hljs-comment"># Adds item to the set. Same as `<set> |= {<el>}`.</span> <set>.update(<coll> [, ...]) <span class="hljs-comment"># Adds items to the set. Same as `<set> |= <set>`.</span> </code></pre> <pre><code class="python language-python hljs"><set> = <set>.union(<coll>) <span class="hljs-comment"># Returns a set of all items. Also <set> | <set>.</span> <set> = <set>.intersection(<coll>) <span class="hljs-comment"># Returns every shared item. Also <set> & <set>.</span> <set> = <set>.difference(<coll>) <span class="hljs-comment"># Returns set's unique items. Also <set> - <set>.</span> </code></pre> <pre><code class="python language-python hljs"><bool> = <set>.issuperset(<coll>) <span class="hljs-comment"># Returns False when collection has unique items.</span> <bool> = <set>.issubset(<coll>) <span class="hljs-comment"># Is collection a superset? Also <set> <= <set>.</span> </code></pre> <pre><code class="python language-python hljs"><el> = <set>.pop() <span class="hljs-comment"># Removes one of items. Raises KeyError if empty.</span> <set>.remove(<el>) <span class="hljs-comment"># Removes the item or raises KeyError if missing.</span> <set>.discard(<el>) <span class="hljs-comment"># Same as remove() but it doesn't raise an error.</span> </code></pre> <div><h3 id="frozenset">Frozen Set</h3><ul> <li><strong>Frozenset is immutable and hashable version of the normal set.</strong></li> <li><strong>That means it can be used as a key in a dict or as an item in a set.</strong></li> </ul><pre><code class="python language-python hljs"><frozenset> = frozenset(<collection>) </code></pre></div> <div><h2 id="tuple"><a href="#tuple" name="tuple">#</a>Tuple</h2><p><strong>Tuple is an immutable and hashable list.</strong></p><pre><code class="python language-python hljs"><tuple> = () <span class="hljs-comment"># Returns an empty tuple. Also tuple(), tuple(<coll>).</span> <tuple> = (<el>,) <span class="hljs-comment"># Returns tuple with one element. Or `<tup.> = <el>,`.</span> <tuple> = (<el>, <el> [, ...]) <span class="hljs-comment"># Returns a tuple. Or `<tuple> = <el>, <el> [, ...]`.</span> </code></pre></div> <div><h3 id="namedtuple">Named Tuple</h3><p><strong>Tuple's subclass with named elements.</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">import</span> collections <span class="hljs-keyword">as</span> co <span class="hljs-meta">>>> </span>Point = co.namedtuple(<span class="hljs-string">'Point'</span>, <span class="hljs-string">'x y'</span>) <span class="hljs-meta">>>> </span>p = Point(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>) <span class="hljs-meta">>>> </span>print(p) Point(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>) <span class="hljs-meta">>>> </span>p.x, p[<span class="hljs-number">1</span>] (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>) </code></pre></div> <div><h2 id="range"><a href="#range" name="range">#</a>Range</h2><p><strong>A sequence of evenly spaced integers.</strong></p><pre><code class="python language-python hljs"><range> = range(stop) <span class="hljs-comment"># I.e. range(to_exclusive). Ints from 0 to `stop-1`.</span> <range> = range(start, stop) <span class="hljs-comment"># I.e. range(from, to_exc). From start to `stop-1`.</span> <range> = range(start, stop, step) <span class="hljs-comment"># I.e. range(from_inclusive, to_exclusive, ±step).</span> </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>[i <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">3</span>)] [<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>] </code></pre> <div><h3 id="enumerate">Enumerate</h3><p><strong>Iterator that zips collection with range.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">for</span> i, el <span class="hljs-keyword">in</span> enumerate(<coll>): print(<span class="hljs-string">f'Element <span class="hljs-subst">{el}</span> has index <span class="hljs-subst">{i}</span>.'</span>) </code></pre></div> <div><h2 id="iterator"><a href="#iterator" name="iterator">#</a>Iterator</h2><p><strong>Potentially endless stream of elements.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> itertools <span class="hljs-keyword">as</span> it </code></pre></div> <pre><code class="python language-python hljs"><iter> = iter(<coll>) <span class="hljs-comment"># Iterator that returns passed elements one by one.</span> <iter> = iter(<func>, to_exc) <span class="hljs-comment"># Calls `<func>()` until it receives 'to_exc' value.</span> <iter> = (<expr> <span class="hljs-keyword">for</span> <name> <span class="hljs-keyword">in</span> <coll>) <span class="hljs-comment"># E.g. `(i+1 for i in range(3))`. Evaluates lazily.</span> <el> = next(<iter> [, default]) <span class="hljs-comment"># Raises StopIteration or returns 'default' on end.</span> <list> = list(<iter>) <span class="hljs-comment"># Returns a list of iterator's remaining elements.</span> </code></pre> <pre><code class="python language-python hljs"><iter> = it.count(start=<span class="hljs-number">0</span>, step=<span class="hljs-number">1</span>) <span class="hljs-comment"># Returns updated 'start' endlessly. Accepts floats.</span> <iter> = it.repeat(<obj> [, times]) <span class="hljs-comment"># Returns passed element endlessly or 'times' times.</span> <iter> = it.cycle(<coll>) <span class="hljs-comment"># Repeats the sequence endlessly. Accepts iterators.</span> </code></pre> <pre><code class="python language-python hljs"><iter> = it.chain(<coll>, <coll>, ...) <span class="hljs-comment"># Returns each element of each collection in order.</span> <iter> = it.chain.from_iterable(<coll>) <span class="hljs-comment"># Accepts collection (i.e. iterable) of collections.</span> <iter> = it.islice(<coll>, stop) <span class="hljs-comment"># Also accepts 'start' and 'step'. Args can be None.</span> <iter> = it.product(<coll>, <coll>) <span class="hljs-comment"># Same as `((a, b) for a in arg_1 for b in arg_2)`.</span> </code></pre> <ul> <li><strong>For loops call <code class="python hljs"><span class="hljs-string">'iter(<coll/iter>)'</span></code>, latter returning unmodified iterator.</strong></li> </ul> <div><h2 id="generator"><a href="#generator" name="generator">#</a>Generator</h2><ul> <li><strong>Any function that contains a yield statement returns a generator.</strong></li> <li><strong>Generators and iterators are interchangeable (see <a href="#iterator-1">Iterator</a> duck type).</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">count</span><span class="hljs-params">(start, step)</span>:</span> <span class="hljs-keyword">while</span> <span class="hljs-keyword">True</span>: <span class="hljs-keyword">yield</span> start start += step </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>counter = count(<span class="hljs-number">10</span>, <span class="hljs-number">2</span>) <span class="hljs-meta">>>> </span>next(counter), next(counter), next(counter) (<span class="hljs-number">10</span>, <span class="hljs-number">12</span>, <span class="hljs-number">14</span>) </code></pre> <div><h2 id="type"><a href="#type" name="type">#</a>Type</h2><ul> <li><strong>All values in Python are objects.</strong></li> <li><strong>Every object has a certain type.</strong></li> <li><strong>Type and class are synonymous.</strong></li> </ul><pre><code class="python language-python hljs"><type> = type(<obj>) <span class="hljs-comment"># Object's type. Also `<obj>.__class__`.</span> <bool> = isinstance(<obj>, <type>) <span class="hljs-comment"># Also `issubclass(type(<obj>), <type>)`.</span> </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>type(<span class="hljs-string">'a'</span>), <span class="hljs-string">'a'</span>.__class__, str (<<span class="hljs-class"><span class="hljs-title">class</span> '<span class="hljs-title">str</span>'>, <<span class="hljs-title">class</span> '<span class="hljs-title">str</span>'>, <<span class="hljs-title">class</span> '<span class="hljs-title">str</span>'>) </span></code></pre> <div><h4 id="sometypesdonothavebuiltinnamessotheymustbeimported">Some types do not have built-in names, so they must be imported:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> types <span class="hljs-keyword">import</span> FunctionType, MethodType, LambdaType, GeneratorType </code></pre></div> <div><h3 id="abstractbaseclasses">Abstract Base Classes</h3><p><strong>Each abstract base class specifies a set of virtual subclasses. These classes are then recognized by isinstance() and issubclass() as <a href="#subclass">subclasses</a> of the ABC, although they are really not. An ABC can also manually decide whether or not a specific class is its virtual subclass, usually based on which methods that class has implemented. For instance, Iterable ABC looks for method iter(), while Collection ABC looks for iter(), contains() and len().</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> collections.abc <span class="hljs-keyword">import</span> Iterable, Collection, Sequence <span class="hljs-meta">>>> </span>isinstance([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], Iterable) <span class="hljs-keyword">True</span> </code></pre></div> <pre><code class="text language-text">┏━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┓ ┃ │ Iterable │ Collection │ Sequence ┃ ┠──────────────────┼────────────┼────────────┼────────────┨ ┃ list, range, str │ ✓ │ ✓ │ ✓ ┃ ┃ dict, set │ ✓ │ ✓ │ ┃ ┃ iter │ ✓ │ │ ┃ ┗━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┛ </code></pre> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> numbers <span class="hljs-keyword">import</span> Number, Complex, Real, Rational, Integral <span class="hljs-meta">>>> </span>isinstance(<span class="hljs-number">123</span>, Number) <span class="hljs-keyword">True</span> </code></pre> <pre><code class="text language-text">┏━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━┓ ┃ │ Number │ Complex │ Real │ Rational │ Integral ┃ ┠────────────────────┼─────────┼─────────┼─────────┼──────────┼──────────┨ ┃ int │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ ┃ ┃ fractions.Fraction │ ✓ │ ✓ │ ✓ │ ✓ │ ┃ ┃ float │ ✓ │ ✓ │ ✓ │ │ ┃ ┃ complex │ ✓ │ ✓ │ │ │ ┃ ┃ decimal.Decimal │ ✓ │ │ │ │ ┃ ┗━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━━━┛ </code></pre> <div><h2 id="string"><a href="#string" name="string">#</a>String</h2><p><strong>Immutable sequence of characters.</strong></p><pre><code class="python language-python hljs"><str> = <span class="hljs-string">'abc'</span> <span class="hljs-comment"># Also "abc". Interprets \n, \t, \x00-\xff, etc.</span> </code></pre></div> <pre><code class="python language-python hljs"><str> = <str>.strip() <span class="hljs-comment"># Strips all whitespace characters from both ends.</span> <str> = <str>.strip(<span class="hljs-string">'<chars>'</span>) <span class="hljs-comment"># Strips passed characters. Also lstrip/rstrip().</span> </code></pre> <pre><code class="python language-python hljs"><list> = <str>.split() <span class="hljs-comment"># Splits it on one or more whitespace characters.</span> <list> = <str>.split(<str>) <span class="hljs-comment"># Splits on passed string. Also `maxsplit=<int>`.</span> <list> = <str>.splitlines() <span class="hljs-comment"># On [\n\r\f\v\x1c-\x1e\x85\u2028\u2029] and \r\n.</span> <str> = <str>.join(<coll_of_str>) <span class="hljs-comment"># Joins items by using the string as a separator.</span> </code></pre> <pre><code class="python language-python hljs"><bool> = <str> <span class="hljs-keyword">in</span> <str> <span class="hljs-comment"># Returns True if string contains the substring.</span> <bool> = <str>.startswith(<str>) <span class="hljs-comment"># Pass tuple of strings to give multiple options.</span> <int> = <str>.find(<str>) <span class="hljs-comment"># Returns start index of the first match or `-1`.</span> </code></pre> <pre><code class="python language-python hljs"><str> = <str>.lower() <span class="hljs-comment"># Lowers the case. Also upper/capitalize/title().</span> <str> = <str>.casefold() <span class="hljs-comment"># Lower() that converts ẞ/ß to ss, Σ/ς to σ, etc.</span> <str> = <str>.replace(old, new) <span class="hljs-comment"># Removes occurrences of string old if new is ''.</span> <str> = <str>.translate(table) <span class="hljs-comment"># Get table via str.maketrans(<chr_to_str_dict>).</span> </code></pre> <pre><code class="python language-python hljs"><str> = chr(<int>) <span class="hljs-comment"># Converts passed integer into Unicode character.</span> <int> = ord(<str>) <span class="hljs-comment"># Converts passed Unicode character into integer.</span> </code></pre> <ul> <li><strong>Use <code class="python hljs"><span class="hljs-string">'unicodedata.normalize("NFC", <str>)'</span></code> on strings like <code class="python hljs"><span class="hljs-string">'Motörhead'</span></code> before comparing them to other strings, because <code class="python hljs"><span class="hljs-string">'ö'</span></code> can be stored as one or two characters.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'NFC'</span></code> converts such characters to a single character, while <code class="python hljs"><span class="hljs-string">'NFD'</span></code> converts them to two.</strong></li> </ul> <pre><code class="python language-python hljs"><bool> = <str>.isdecimal() <span class="hljs-comment"># Checks all chars for [0-9]. Also [०-९], [٠-٩].</span> <bool> = <str>.isdigit() <span class="hljs-comment"># Checks for [²³¹…] and isdecimal(). Also [፩-፱].</span> <bool> = <str>.isnumeric() <span class="hljs-comment"># Checks for [¼½¾…] and isdigit(). Also [零〇一…].</span> <bool> = <str>.isalnum() <span class="hljs-comment"># Checks for [ABC…] and isnumeric(). Also [ªµº…].</span> <bool> = <str>.isprintable() <span class="hljs-comment"># Checks for [ !"#…], basic emojis and isalnum().</span> <bool> = <str>.isspace() <span class="hljs-comment"># Checks for [ \t\n\r\f\v\x1c\x1d\x1e\x1f\x85…].</span> </code></pre> <div><h2 id="regex"><a href="#regex" name="regex">#</a>Regex</h2><p><strong>Functions for regular expression matching.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> re <str> = re.sub(<span class="hljs-string">r'<regex>'</span>, new, text) <span class="hljs-comment"># Substitutes occurrences with string 'new'.</span> <list> = re.findall(<span class="hljs-string">r'<regex>'</span>, text) <span class="hljs-comment"># Returns all occurrences as string objects.</span> <list> = re.split(<span class="hljs-string">r'<regex>'</span>, text) <span class="hljs-comment"># Add brackets around regex to keep matches.</span> <Match> = re.search(<span class="hljs-string">r'<regex>'</span>, text) <span class="hljs-comment"># Returns first occ. of the pattern or None.</span> <Match> = re.match(<span class="hljs-string">r'<regex>'</span>, text) <span class="hljs-comment"># Only searches at the start of the 'text'.</span> <iter> = re.finditer(<span class="hljs-string">r'<regex>'</span>, text) <span class="hljs-comment"># Returns all occurrences as Match objects.</span> </code></pre></div> <ul> <li><strong>Raw string literals do not interpret escape sequences, thus enabling us to use the regex-specific escape sequences that cause SyntaxWarning in normal string literals (since 3.12).</strong></li> <li><strong>Argument <code class="python hljs"><span class="hljs-string">'new'</span></code> can also be a function that accepts a Match object and returns a string.</strong></li> <li><strong>Argument <code class="python hljs"><span class="hljs-string">'flags=re.IGNORECASE'</span></code> can be used with all functions that are listed above.</strong></li> <li><strong>Argument <code class="python hljs"><span class="hljs-string">'flags=re.MULTILINE'</span></code> makes <code class="python hljs"><span class="hljs-string">'^'</span></code> and <code class="python hljs"><span class="hljs-string">'$'</span></code> match the start/end of each line.</strong></li> <li><strong>Argument <code class="python hljs"><span class="hljs-string">'flags=re.DOTALL'</span></code> makes <code class="python hljs"><span class="hljs-string">'.'</span></code> also accept the <code class="python hljs"><span class="hljs-string">'\n'</span></code> (besides all other chars).</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'re.compile(r"<regex>")'</span></code> returns a Pattern object with methods sub(), findall(), etc.</strong></li> </ul> <div><h3 id="matchobject">Match Object</h3><pre><code class="python language-python hljs"><str> = <Match>.group() <span class="hljs-comment"># Returns the whole match. Also group(0).</span> <str> = <Match>.group(<span class="hljs-number">1</span>) <span class="hljs-comment"># Returns part inside the first brackets.</span> <tuple> = <Match>.groups() <span class="hljs-comment"># Returns all bracketed parts as strings.</span> <int> = <Match>.start() <span class="hljs-comment"># Returns start index of the whole match.</span> <int> = <Match>.end() <span class="hljs-comment"># Returns the match's end index plus one.</span> </code></pre></div> <div><h3 id="specialsequences">Special Sequences</h3><pre><code class="python language-python hljs"><span class="hljs-string">'\d'</span> == <span class="hljs-string">'[0-9]'</span> <span class="hljs-comment"># Also [०-९…]. Matches decimal character.</span> <span class="hljs-string">'\w'</span> == <span class="hljs-string">'[a-zA-Z0-9_]'</span> <span class="hljs-comment"># Also [ª²³…]. Matches alphanumeric or _.</span> <span class="hljs-string">'\s'</span> == <span class="hljs-string">'[ \t\n\r\f\v]'</span> <span class="hljs-comment"># Also [\x1c-\x1f…]. Matches whitespace.</span> </code></pre></div> <ul> <li><strong>By default, decimal characters and alphanumerics from all alphabets are matched unless <code class="python hljs"><span class="hljs-string">'flags=re.ASCII'</span></code> is used. It restricts special sequence matches to the first 128 Unicode characters and also prevents <code class="python hljs"><span class="hljs-string">'\s'</span></code> from accepting <code class="python hljs"><span class="hljs-string">'\x1c'</span></code>, <code class="python hljs"><span class="hljs-string">'\x1d'</span></code>, <code class="python hljs"><span class="hljs-string">'\x1e'</span></code> and <code class="python hljs"><span class="hljs-string">'\x1f'</span></code> (non-printable characters that divide text into files, tables, rows and fields, respectively).</strong></li> <li><strong>Use a capital letter, i.e. <code class="python hljs"><span class="hljs-string">'\D'</span></code>, <code class="python hljs"><span class="hljs-string">'\W'</span></code> or <code class="python hljs"><span class="hljs-string">'\S'</span></code>, for negation. All non-ASCII characters are matched if ASCII flag is used in conjunction with a capital letter.</strong></li> </ul> <div><h2 id="format"><a href="#format" name="format">#</a>Format</h2><p><strong>String formatting mechanisms.</strong></p><pre><code class="python hljs"><str> = <span class="hljs-string">f'<span class="hljs-subst">{<obj>}</span>, <span class="hljs-subst">{<obj>}</span>'</span> <span class="hljs-comment"># Braces can also contain expressions.</span> <str> = <span class="hljs-string">'{}, {}'</span>.format(<obj>, <obj>) <span class="hljs-comment"># Or '{0}, {a}'.format(<obj>, a=<obj>).</span> <str> = <span class="hljs-string">'%s, %s'</span> % (<obj>, <obj>) <span class="hljs-comment"># Old and redundant formatting method.</span> </code></pre></div> <div><h3 id="example">Example</h3><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>Person = collections.namedtuple(<span class="hljs-string">'Person'</span>, <span class="hljs-string">'name height'</span>) <span class="hljs-meta">>>> </span>jean = Person(<span class="hljs-string">'Jean-Luc'</span>, <span class="hljs-number">187</span>) <span class="hljs-meta">>>> </span><span class="hljs-string">f'<span class="hljs-subst">{jean.name}</span> is <span class="hljs-subst">{jean.height / <span class="hljs-number">100</span>}</span> meters tall.'</span> <span class="hljs-string">'Jean-Luc is 1.87 meters tall.'</span> </code></pre></div> <div><h3 id="options">Options</h3><pre><code class="python language-python hljs">{<obj>:<<span class="hljs-number">10</span>} <span class="hljs-comment"># '<obj> '.</span> {<obj>:^<span class="hljs-number">10</span>} <span class="hljs-comment"># ' <obj> '.</span> {<obj>:><span class="hljs-number">10</span>} <span class="hljs-comment"># ' <obj>'.</span> {<obj>:.<<span class="hljs-number">10</span>} <span class="hljs-comment"># '<obj>.....'.</span> {<obj>:<span class="hljs-number">0</span>} <span class="hljs-comment"># '<obj>'.</span> </code></pre></div> <ul> <li><strong>Objects are converted to strings with format() function, e.g. <code class="python hljs"><span class="hljs-string">'format(<obj>, "<10")'</span></code>.</strong></li> <li><strong>Options can be generated dynamically via nested braces: <code class="python hljs"><span class="hljs-string">f'<span class="hljs-subst">{<obj>:{<str/int>}</span>[…]}'</span></code>.</strong></li> <li><strong>Adding <code class="python hljs"><span class="hljs-string">'='</span></code> to the expression prepends it to its result, e.g. <code class="python hljs"><span class="hljs-string">f'<span class="hljs-subst">{<span class="hljs-number">1</span>+<span class="hljs-number">1</span>=}</span>'</span></code> returns <code class="python hljs"><span class="hljs-string">'1+1=2'</span></code>.</strong></li> <li><strong>Adding <code class="python hljs"><span class="hljs-string">'!r'</span></code> to the expression first calls result's <a href="#class">repr()</a> method and only then format().</strong></li> </ul> <div><h3 id="strings">Strings</h3><pre><code class="python language-python hljs">{<span class="hljs-string">'abcde'</span>:<span class="hljs-number">10</span>} <span class="hljs-comment"># 'abcde '.</span> {<span class="hljs-string">'abcde'</span>:<span class="hljs-number">10.3</span>} <span class="hljs-comment"># 'abc '.</span> {<span class="hljs-string">'abcde'</span>:<span class="hljs-number">.3</span>} <span class="hljs-comment"># 'abc'.</span> {<span class="hljs-string">'abcde'</span>!r:<span class="hljs-number">10</span>} <span class="hljs-comment"># "'abcde' ".</span> </code></pre></div> <div><h3 id="numbers-1">Numbers</h3><pre><code class="python language-python hljs">{<span class="hljs-number">123456</span>:<span class="hljs-number">10</span>} <span class="hljs-comment"># ' 123456'.</span> {<span class="hljs-number">123456</span>:<span class="hljs-number">10</span>,} <span class="hljs-comment"># ' 123,456'.</span> {<span class="hljs-number">123456</span>:<span class="hljs-number">10</span>_} <span class="hljs-comment"># ' 123_456'.</span> {<span class="hljs-number">123456</span>:+<span class="hljs-number">10</span>} <span class="hljs-comment"># ' +123456'.</span> {<span class="hljs-number">123456</span>:=+<span class="hljs-number">10</span>} <span class="hljs-comment"># '+ 123456'.</span> </code></pre></div> <div><h3 id="floats">Floats</h3><pre><code class="python language-python hljs">{<span class="hljs-number">1.23456</span>:<span class="hljs-number">10.3</span>} <span class="hljs-comment"># ' 1.23'.</span> {<span class="hljs-number">1.23456</span>:<span class="hljs-number">10.3</span>f} <span class="hljs-comment"># ' 1.235'.</span> {<span class="hljs-number">1.23456</span>:<span class="hljs-number">10.3</span>e} <span class="hljs-comment"># ' 1.235e+00'.</span> {<span class="hljs-number">1.23456</span>:<span class="hljs-number">10.3</span>%} <span class="hljs-comment"># ' 123.456%'.</span> </code></pre></div> <div><h4 id="comparisonofpresentationtypes">Comparison of presentation types:</h4><pre><code class="text language-text">┏━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ ┃ │ {<number>} │ {<num>:f} │ {<num>:e} │ {<num>:%} ┃ ┠───────────────┼───────────────┼───────────────┼───────────────┼───────────────┨ ┃ 0.000056789 │ 5.6789e-05 │ 0.000057 │ 5.678900e-05 │ 0.005679% ┃ ┃ 0.00056789 │ 0.00056789 │ 0.000568 │ 5.678900e-04 │ 0.056789% ┃ ┃ 0.0056789 │ 0.0056789 │ 0.005679 │ 5.678900e-03 │ 0.567890% ┃ ┃ 0.056789 │ 0.056789 │ 0.056789 │ 5.678900e-02 │ 5.678900% ┃ ┃ 0.56789 │ 0.56789 │ 0.567890 │ 5.678900e-01 │ 56.789000% ┃ ┃ 5.6789 │ 5.6789 │ 5.678900 │ 5.678900e+00 │ 567.890000% ┃ ┃ 56.789 │ 56.789 │ 56.789000 │ 5.678900e+01 │ 5678.900000% ┃ ┗━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ ┏━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ ┃ │ {<float>:.2} │ {<num>:.2f} │ {<num>:.2e} │ {<num>:.2%} ┃ ┠───────────────┼───────────────┼───────────────┼───────────────┼───────────────┨ ┃ 0.000056789 │ 5.7e-05 │ 0.00 │ 5.68e-05 │ 0.01% ┃ ┃ 0.00056789 │ 0.00057 │ 0.00 │ 5.68e-04 │ 0.06% ┃ ┃ 0.0056789 │ 0.0057 │ 0.01 │ 5.68e-03 │ 0.57% ┃ ┃ 0.056789 │ 0.057 │ 0.06 │ 5.68e-02 │ 5.68% ┃ ┃ 0.56789 │ 0.57 │ 0.57 │ 5.68e-01 │ 56.79% ┃ ┃ 5.6789 │ 5.7 │ 5.68 │ 5.68e+00 │ 567.89% ┃ ┃ 56.789 │ 5.7e+01 │ 56.79 │ 5.68e+01 │ 5678.90% ┃ ┗━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ </code></pre></div> <ul> <li><strong><code class="python hljs"><span class="hljs-string">'{<num>:g}'</span></code> is <code class="python hljs"><span class="hljs-string">'{<float>:.6}'</span></code> that strips <code class="python hljs"><span class="hljs-string">'.0'</span></code> and has exponent starting at <code class="python hljs"><span class="hljs-string">'1e+06'</span></code>.</strong></li> <li><strong>When both rounding up and rounding down are possible, the one that returns result with even last digit is chosen. Hence <code class="python hljs"><span class="hljs-string">'{6.5:.0f}'</span></code> becomes a <code class="python hljs"><span class="hljs-string">'6'</span></code>, while <code class="python hljs"><span class="hljs-string">'{7.5:.0f}'</span></code> an <code class="python hljs"><span class="hljs-string">'8'</span></code>.</strong></li> <li><strong>The last rule only effects numbers that can be represented exactly by a float (<code class="python hljs"><span class="hljs-number">.5</span></code>, <code class="python hljs"><span class="hljs-number">.25</span></code>, …).</strong></li> </ul> <div><h3 id="ints">Ints</h3><pre><code class="python language-python hljs">{<span class="hljs-number">90</span>:x} <span class="hljs-comment"># Converts 90 to hexadecimal number '5a'.</span> {<span class="hljs-number">90</span>:b} <span class="hljs-comment"># Converts 90 to binary number '1011010'.</span> {<span class="hljs-number">90</span>:c} <span class="hljs-comment"># Converts 90 to Unicode character 'Z'.</span> </code></pre></div> <div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs"><integer> = int(<float/str/bool>) <span class="hljs-comment"># A whole number. Truncates floats.</span> <float> = float(<integer/str/bool>) <span class="hljs-comment"># 8-byte decimal. Also <fl>e±<int>.</span> <complex> = complex(real=<span class="hljs-number">0</span>, imag=<span class="hljs-number">0</span>) <span class="hljs-comment"># Complex number. Also <fl> ± <fl>j.</span> <Fract> = fractions.Fraction(numr, denom) <span class="hljs-comment"># `<Fraction> = <Fraction> / <int>`.</span> <Decimal> = decimal.Decimal(<str/int/tup>) <span class="hljs-comment"># `Decimal((1, (2,), 3)) == -2000`.</span> </code></pre></div> <ul> <li><strong><code class="python hljs"><span class="hljs-string">'int(<str>)'</span></code> and <code class="python hljs"><span class="hljs-string">'float(<str>)'</span></code> raise ValueError exception if string is malformed.</strong></li> <li><strong>Decimal objects store numbers exactly, unlike most floats where <code class="python hljs"><span class="hljs-string">'1.1 + 2.2 != 3.3'</span></code>.</strong></li> <li><strong>Floats can be compared with: <code class="python hljs"><span class="hljs-string">'math.isclose(<float>, <float>, rel_tol=1e-9)'</span></code>.</strong></li> <li><strong>Precision of decimal operations is set with: <code class="python hljs"><span class="hljs-string">'decimal.getcontext().prec = <int>'</span></code>.</strong></li> <li><strong>Bools can be used anywhere ints can, since bool is a subclass of int: <code class="python hljs"><span class="hljs-string">'True + 1 == 2'</span></code>.</strong></li> </ul> <div><h3 id="builtin">Built-in</h3><pre><code class="python language-python hljs"><num> = abs(<num>) <span class="hljs-comment"># E.g. `abs(-50) == abs(50) == 50`.</span> <num> = pow(<num>, <num>) <span class="hljs-comment"># E.g. `pow(3, 4) == 3 ** 4 == 81`.</span> <num> = round(<num> [, ndigits]) <span class="hljs-comment"># E.g. `round(123.45, -1) == 120`.</span> <num> = min(<coll_of_nums>) <span class="hljs-comment"># Also `max(<num>, <num> [, ...])`.</span> <num> = sum(<coll_of_nums>) <span class="hljs-comment"># Also `math.prod(<coll_of_nums>)`.</span> </code></pre></div> <div><h3 id="math">Math</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> math <span class="hljs-keyword">as</span> mt <num> = mt.pi/inf/nan <span class="hljs-comment"># `inf*0` and `nan+1` return `nan`.</span> <num> = mt.sqrt/factorial(<num>) <span class="hljs-comment"># `sqrt(-1)` will raise ValueError.</span> <num> = mt.sin/cos/tan(<num>) <span class="hljs-comment"># Also degrees, radians, asin, etc.</span> <num> = mt.log/log10/log2(<num>) <span class="hljs-comment"># Log() can accept 'base' argument.</span> </code></pre></div> <div><h3 id="statistics">Statistics</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> statistics <span class="hljs-keyword">as</span> st <obj> = st.mean/median(<coll>) <span class="hljs-comment"># Mode returns most common element.</span> <num> = st.variance/stdev(<coll>) <span class="hljs-comment"># Estimates values from the sample.</span> <list> = st.quantiles(<coll>, n=<span class="hljs-number">4</span>) <span class="hljs-comment"># Estimates cut points from sample.</span> </code></pre></div> <div><h3 id="random">Random</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> random <span class="hljs-keyword">as</span> rd <num> = rd.random() <span class="hljs-comment"># Selects random float from [0, 1).</span> <num> = rd.randint/uniform(a, b) <span class="hljs-comment"># Selects an int/float from [a, b].</span> <num> = rd.gauss(mean, stdev) <span class="hljs-comment"># Also triangular(low, high, mode).</span> <obj> = rd.choice(<sequence>) <span class="hljs-comment"># Doesn't mutate. Also sample(p, n).</span> rd.shuffle(<list>) <span class="hljs-comment"># Works with all mutable sequences.</span> </code></pre></div> <div><h3 id="hexbin">Hex, Bin</h3><pre><code class="python language-python hljs"><int> = <span class="hljs-number">0x</span><hex> <span class="hljs-comment"># E.g. `0xFf == 255`. Also 0b<bin>.</span> <int> = int(<span class="hljs-string">'±<hex>'</span>, <span class="hljs-number">16</span>) <span class="hljs-comment"># Also int('±0x<hex>/±0b<bin>', 0).</span> <str> = hex(<int>) <span class="hljs-comment"># Returns '[-]0x<hex>'. Also bin().</span> </code></pre></div> <div><h3 id="bitwise">Bitwise</h3><pre><code class="python language-python hljs"><int> = <int> & <int> <span class="hljs-comment"># E.g. `0b1100 & 0b1010 == 0b1000`.</span> <int> = <int> | <int> <span class="hljs-comment"># E.g. `0b1100 | 0b1010 == 0b1110`.</span> <int> = <int> ^ <int> <span class="hljs-comment"># E.g. `0b1100 ^ 0b1010 == 0b0110`.</span> <int> = <int> << n_bits <span class="hljs-comment"># E.g. `0b1111 << 4 == 0b11110000`.</span> <int> = ~<int> <span class="hljs-comment"># E.g. `~100 == -(100+1) == -101`.</span> </code></pre></div> <div><h2 id="combinatorics"><a href="#combinatorics" name="combinatorics">#</a>Combinatorics</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> itertools <span class="hljs-keyword">as</span> it </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>list(it.product(<span class="hljs-string">'abc'</span>, repeat=<span class="hljs-number">2</span>)) <span class="hljs-comment"># a b c</span> [(<span class="hljs-string">'a'</span>, <span class="hljs-string">'a'</span>), (<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>), (<span class="hljs-string">'a'</span>, <span class="hljs-string">'c'</span>), <span class="hljs-comment"># a x x x</span> (<span class="hljs-string">'b'</span>, <span class="hljs-string">'a'</span>), (<span class="hljs-string">'b'</span>, <span class="hljs-string">'b'</span>), (<span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>), <span class="hljs-comment"># b x x x</span> (<span class="hljs-string">'c'</span>, <span class="hljs-string">'a'</span>), (<span class="hljs-string">'c'</span>, <span class="hljs-string">'b'</span>), (<span class="hljs-string">'c'</span>, <span class="hljs-string">'c'</span>)] <span class="hljs-comment"># c x x x</span> </code></pre> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>list(it.permutations(<span class="hljs-string">'abc'</span>, <span class="hljs-number">2</span>)) <span class="hljs-comment"># a b c</span> [(<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>), (<span class="hljs-string">'a'</span>, <span class="hljs-string">'c'</span>), <span class="hljs-comment"># a . x x</span> (<span class="hljs-string">'b'</span>, <span class="hljs-string">'a'</span>), (<span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>), <span class="hljs-comment"># b x . x</span> (<span class="hljs-string">'c'</span>, <span class="hljs-string">'a'</span>), (<span class="hljs-string">'c'</span>, <span class="hljs-string">'b'</span>)] <span class="hljs-comment"># c x x .</span> </code></pre> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>list(it.combinations(<span class="hljs-string">'abc'</span>, <span class="hljs-number">2</span>)) <span class="hljs-comment"># a b c</span> [(<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>), (<span class="hljs-string">'a'</span>, <span class="hljs-string">'c'</span>), <span class="hljs-comment"># a . x x</span> (<span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>) <span class="hljs-comment"># b . . x</span> ] <span class="hljs-comment"># c . . .</span> </code></pre> <div><h2 id="datetime"><a href="#datetime" name="datetime">#</a>Datetime</h2><p><strong>Module that provides date, time and datetime objects.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install python-dateutil</span> <span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> * <span class="hljs-keyword">import</span> zoneinfo, dateutil.tz </code></pre></div> <pre><code class="python language-python apache hljs"><D> = date(year, month, day) <span class="hljs-comment"># Only accepts valid dates between AD 1 and 9999.</span> <T> = time(hour=<span class="hljs-number">0</span>, minute=<span class="hljs-number">0</span>, second=<span class="hljs-number">0</span>) <span class="hljs-comment"># Accepts `microsecond=0, tzinfo=None, fold=0`.</span> <DT> = datetime(year, month, day, hour=<span class="hljs-number">0</span>) <span class="hljs-comment"># Accepts `minute=0, second=0, microsecond=0, …`.</span> <TD> = timedelta(weeks=<span class="hljs-number">0</span>, days=<span class="hljs-number">0</span>, hours=<span class="hljs-number">0</span>) <span class="hljs-comment"># Accepts `minutes=0, seconds=0, microseconds=0`.</span> </code></pre> <ul> <li><strong>Times and datetimes that have defined timezone are called <em>aware</em> and ones that don't, <em>naive</em>. If time or datetime object is naive, it is presumed to be in the system's timezone.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'fold=1'</span></code> means the second pass in case of time jumping back (usually for one hour).</strong></li> <li><strong>Timedelta normalizes arguments to ±days, seconds (< 86 400) and microseconds (< 1M). Its str() method returns <code class="python hljs"><span class="hljs-string">'[±D, ]H:MM:SS[.…]'</span></code> and total_seconds() a float of seconds.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'<D/DT>.weekday()'</span></code> to get the day of the week as an int, with Monday being 0.</strong></li> </ul> <div><h3 id="now">Now</h3><pre><code class="python language-python hljs"><D/DTn> = D/DT.today() <span class="hljs-comment"># Current local date or naive DT. Also DT.now().</span> <DTa> = DT.now(<tzinfo>) <span class="hljs-comment"># Aware DT from current time in passed timezone.</span> </code></pre></div> <ul> <li><strong>To extract time use <code class="python hljs"><span class="hljs-string">'<DTn>.time()'</span></code>, <code class="python hljs"><span class="hljs-string">'<DTa>.time()'</span></code> or <code class="python hljs"><span class="hljs-string">'<DTa>.timetz()'</span></code>.</strong></li> </ul> <div><h3 id="timezone">Timezone</h3><pre><code class="python language-python apache hljs"><tzinfo> = timezone.utc <span class="hljs-comment"># Coordinated universal time. London without DST.</span> <tzinfo> = timezone(<timedelta>) <span class="hljs-comment"># Timezone with fixed offset from universal time.</span> <tzinfo> = dateutil.tz.tzlocal() <span class="hljs-comment"># Local timezone with dynamic offset from the UTC.</span> <tzinfo> = zoneinfo.ZoneInfo(<span class="hljs-string">'<iana_key>'</span>) <span class="hljs-comment"># 'Continent/City_Name' zone with dynamic offset.</span> <DTa> = <DT>.astimezone(<tzinfo>) <span class="hljs-comment"># Converts to the passed or local fixed timezone.</span> <Ta/DTa> = <T/DT>.replace(tzinfo=<tzinfo>) <span class="hljs-comment"># Changes the timezone object without conversion.</span> </code></pre></div> <ul> <li><strong>Timezones returned by tzlocal(), ZoneInfo(), and implicit local timezone of naive objects have offsets that vary through time due to DST and historical changes of the base offset.</strong></li> <li><strong>To get ZoneInfo() to work on Windows run <code class="python hljs"><span class="hljs-string">'> pip3 install tzdata'</span></code>.</strong></li> </ul> <div><h3 id="encode">Encode</h3><pre><code class="python language-python apache hljs"><D/T/DT> = D/T/DT.fromisoformat(<str>) <span class="hljs-comment"># Object from the ISO string. Raises ValueError.</span> <DT> = DT.strptime(<str>, <span class="hljs-string">'<format>'</span>) <span class="hljs-comment"># Naive or aware datetime from the custom string.</span> <D/DTn> = D/DT.fromordinal(<int>) <span class="hljs-comment"># Date or DT from days since the Gregorian NYE 1.</span> <DTn> = DT.fromtimestamp(<float>) <span class="hljs-comment"># A local naive DT from seconds since the epoch.</span> <DTa> = DT.fromtimestamp(<float>, <tz>) <span class="hljs-comment"># An aware datetime from seconds since the epoch.</span> </code></pre></div> <ul> <li><strong>ISO strings come in following forms: <code class="python hljs"><span class="hljs-string">'YYYY-MM-DD'</span></code>, <code class="python hljs"><span class="hljs-string">'HH:MM:SS.mmmuuu[±HH:MM]'</span></code>, or both separated by an arbitrary character. All parts following the hours are optional.</strong></li> <li><strong>Python uses the Unix epoch: <code class="python hljs"><span class="hljs-string">'1970-01-01 00:00 UTC'</span></code>, <code class="python hljs"><span class="hljs-string">'1970-01-01 01:00 CET'</span></code>, …</strong></li> </ul> <div><h3 id="decode">Decode</h3><pre><code class="python language-python hljs"><str> = <D/T/DT>.isoformat(sep=<span class="hljs-string">'T'</span>) <span class="hljs-comment"># Also `timespec='auto/hours/minutes/seconds/…'`.</span> <str> = <D/T/DT>.strftime(<span class="hljs-string">'<format>'</span>) <span class="hljs-comment"># Returns custom string representation of object.</span> <int> = <D/DT>.toordinal() <span class="hljs-comment"># Days since NYE 1, ignoring DT's time and zone.</span> <float> = <DTn>.timestamp() <span class="hljs-comment"># Seconds since the epoch from a local naive DT.</span> <float> = <DTa>.timestamp() <span class="hljs-comment"># Seconds since the epoch from an aware datetime.</span> </code></pre></div> <div><h3 id="format-1">Format</h3><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>dta = datetime.strptime(<span class="hljs-string">'2025-08-14 23:39:00.00 +0200'</span>, <span class="hljs-string">'%Y-%m-%d %H:%M:%S.%f %z'</span>) <span class="hljs-meta">>>> </span>dta.strftime(<span class="hljs-string">"%dth of %B '%y (%a), %I:%M %p %Z"</span>) <span class="hljs-string">"14th of August '25 (Thu), 11:39 PM UTC+02:00"</span> </code></pre></div> <ul> <li><strong><code class="python hljs"><span class="hljs-string">'%z'</span></code> accepts <code class="python hljs"><span class="hljs-string">'±HH[:]MM'</span></code> and returns <code class="python hljs"><span class="hljs-string">'±HHMM'</span></code> or empty string if object is naive.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'%Z'</span></code> accepts <code class="python hljs"><span class="hljs-string">'UTC'</span></code>, <code class="python hljs"><span class="hljs-string">'GMT'</span></code> or local timezone's code and returns timezone's name, <code class="python hljs"><span class="hljs-string">'UTC[±HH:MM]'</span></code> if timezone is nameless, or an empty string if object is naive.</strong></li> </ul> <div><h3 id="arithmetics">Arithmetics</h3><pre><code class="python language-python apache hljs"><bool> = <D/DTn> > <D/DTn> <span class="hljs-comment"># Ignores time jumps (fold attribute). Also `==`.</span> <bool> = <DTa> > <DTa> <span class="hljs-comment"># Ignores time jumps if they share tzinfo object.</span> <TD> = <D/DTn> - <D/DTn> <span class="hljs-comment"># Ignores jumps. Convert to UTC for actual delta.</span> <TD> = <DTa> - <DTa> <span class="hljs-comment"># Ignores jumps if they share the tzinfo object.</span> <D/DT> = <D/DT> ± <TD> <span class="hljs-comment"># Returned datetime can fall into a missing hour.</span> <TD> = <TD> ± <TD> <span class="hljs-comment"># Also `<TD> = abs(<TD>)`, `<num> = <TD> / <TD>`.</span> </code></pre></div> <div><h2 id="function"><a href="#function" name="function">#</a>Function</h2><p><strong>Independent block of code that returns a value when called.</strong></p><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_func</span><span class="hljs-params">(<nondefault_args>)</span>:</span> ... <span class="hljs-comment"># E.g. `my_func(x, y):`.</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_func</span><span class="hljs-params">(<default_args>)</span>:</span> ... <span class="hljs-comment"># E.g. `my_func(x=0, y=0):`.</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_func</span><span class="hljs-params">(<nondef_args>, <def_args>)</span>:</span> ... <span class="hljs-comment"># E.g. `my_func(x, y=0):`.</span> </code></pre></div> <ul> <li><strong>Function returns None if it doesn't encounter the <code class="python hljs"><span class="hljs-string">'return <object/expr>'</span></code> statement.</strong></li> <li><strong>Run <code class="python hljs"><span class="hljs-string">'global <var_name>'</span></code> inside the function before assigning to the global variable.</strong></li> <li><strong>Value of a default argument is evaluated when function is first encountered in the scope.</strong></li> <li><strong>Any mutation of a default argument value will persist between function invocations!</strong></li> </ul> <div><h3 id="functioncall">Function Call</h3><pre><code class="python language-python hljs"><obj> = <func>(<positional_args>) <span class="hljs-comment"># E.g. `my_func(0, 0)`.</span> <obj> = <func>(<keyword_args>) <span class="hljs-comment"># E.g. `my_func(x=0, y=0)`.</span> <obj> = <func>(<pos_args>, <key_args>) <span class="hljs-comment"># E.g. `my_func(0, y=0)`.</span> </code></pre></div> <div><h2 id="splat"><a href="#splat" name="splat">#</a>Splat</h2><p><strong>Splat operator, i.e. <code class="python hljs"><span class="hljs-string">'*'</span></code>, expands collection into positional arguments, while splatty-splat, i.e. <code class="python hljs"><span class="hljs-string">'**'</span></code>, expands a dictionary into keyword arguments.</strong></p><pre><code class="python language-python hljs">args, kwargs = (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>), {<span class="hljs-string">'z'</span>: <span class="hljs-number">3</span>} func(*args, **kwargs) </code></pre></div> <div><h4 id="isthesameas">Is the same as:</h4><pre><code class="python language-python hljs">func(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) </code></pre></div> <div><h3 id="insidefunctiondef">Inside Function Def</h3><p><strong>Splat combines zero or more positional arguments into a tuple, while splatty-splat combines zero or more keyword arguments into a dictionary.</strong></p><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span><span class="hljs-params">(*args)</span>:</span> <span class="hljs-keyword">return</span> sum(args) </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>add(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-number">6</span> </code></pre> <pre><code class="text language-text">┏━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━┓ ┃ │ fn(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>) │ fn(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>) │ fn(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>) ┃ ┠─────────────────────────┼──────────────┼──────────────┼────────────┨ ┃ <span class="hljs-title">fn</span>(x, *args, **kwargs): │ ✓ │ ✓ │ ✓ ┃ ┃ <span class="hljs-title">fn</span>(*args, y, **kwargs): │ ✓ │ ✓ │ ┃ ┃ <span class="hljs-title">fn</span>(*, x, **kwargs): │ ✓ │ │ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━┛ </code></pre> <div><h3 id="collectionunpacking">Collection Unpacking</h3><pre><code class="python language-python hljs">head, *body, tail = <collection> <span class="hljs-comment"># Head or tail can be omitted.</span> </code></pre></div> <div><h3 id="insidecollliterals">Inside Coll Literals</h3><pre><code class="python language-python hljs"><list> = [*<coll> [, ...]] <span class="hljs-comment"># Same as `list(<coll>) [+ ...]`.</span> <tuple> = (*<coll>, [...]) <span class="hljs-comment"># Same as `tuple(<coll>) [+ ...]`.</span> <set> = {*<coll> [, ...]} <span class="hljs-comment"># Same as `set(<coll>) [| ...]`.</span> <dict> = {**<dict> [, ...]} <span class="hljs-comment"># Last dict has priority. Also |.</span> </code></pre></div> <div><h2 id="inline"><a href="#inline" name="inline">#</a>Inline</h2><div><h3 id="lambda">Lambda</h3><pre><code class="python language-python hljs"><func> = <span class="hljs-keyword">lambda</span>: <return_val> <span class="hljs-comment"># A single statement function.</span> <func> = <span class="hljs-keyword">lambda</span> <arg> [, ...]: <return_val> <span class="hljs-comment"># Also allows default arguments.</span> </code></pre></div></div> <div><h3 id="comprehensions">Comprehensions</h3><pre><code class="python language-python hljs"><list> = [i+<span class="hljs-number">1</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>)] <span class="hljs-comment"># Returns `[1, 2, 3, 4, 5]`.</span> <iter> = (i <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>) <span class="hljs-keyword">if</span> i > <span class="hljs-number">5</span>) <span class="hljs-comment"># Returns `iter([6, 7, 8, 9])`.</span> <set> = {i+<span class="hljs-number">5</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>)} <span class="hljs-comment"># Returns `{5, 6, 7, 8, 9}`.</span> <dict> = {i: i**<span class="hljs-number">2</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, <span class="hljs-number">4</span>)} <span class="hljs-comment"># Returns `{1: 1, 2: 4, 3: 9}`.</span> </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>[l+r <span class="hljs-keyword">for</span> l <span class="hljs-keyword">in</span> <span class="hljs-string">'abc'</span> <span class="hljs-keyword">for</span> r <span class="hljs-keyword">in</span> <span class="hljs-string">'123'</span>] <span class="hljs-comment"># Inner loop is on right side.</span> [<span class="hljs-string">'a1'</span>, <span class="hljs-string">'a2'</span>, <span class="hljs-string">'a3'</span>, ..., <span class="hljs-string">'c3'</span>] </code></pre> <div><h3 id="mapfilterreduce">Map, Filter, Reduce</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> reduce </code></pre></div> <pre><code class="python language-python hljs"><iter> = map(<span class="hljs-keyword">lambda</span> x: x + <span class="hljs-number">1</span>, range(<span class="hljs-number">5</span>)) <span class="hljs-comment"># Returns `iter([1, 2, 3, 4, 5])`.</span> <iter> = filter(<span class="hljs-keyword">lambda</span> x: x > <span class="hljs-number">5</span>, range(<span class="hljs-number">10</span>)) <span class="hljs-comment"># Returns `iter([6, 7, 8, 9])`.</span> <obj> = reduce(<span class="hljs-keyword">lambda</span> out, x: out+x, range(<span class="hljs-number">5</span>)) <span class="hljs-comment"># Returns 10. Accepts 'initial'.</span> </code></pre> <div><h3 id="anyall">Any, All</h3><pre><code class="python language-python hljs"><bool> = any(<collection>) <span class="hljs-comment"># Is bool(<el>) True for any el?</span> <bool> = all(<collection>) <span class="hljs-comment"># Is it True for all (or empty)?</span> </code></pre></div> <div><h3 id="conditionalexp">Conditional Exp</h3><pre><code class="python language-python hljs"><obj> = <exp> <span class="hljs-keyword">if</span> <condition> <span class="hljs-keyword">else</span> <exp> <span class="hljs-comment"># Evaluates only one expression.</span> </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>[i <span class="hljs-keyword">if</span> i <span class="hljs-keyword">else</span> <span class="hljs-string">'zero'</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> (<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>)] <span class="hljs-comment"># `any(['', [], None])` is False.</span> [<span class="hljs-string">'zero'</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>] </code></pre> <div><h3 id="andor">And, Or</h3><pre><code class="python language-python hljs"><obj> = <exp> <span class="hljs-keyword">and</span> <exp> [<span class="hljs-keyword">and</span> ...] <span class="hljs-comment"># Returns first false or last obj.</span> <obj> = <exp> <span class="hljs-keyword">or</span> <exp> [<span class="hljs-keyword">or</span> ...] <span class="hljs-comment"># Returns first true or last obj.</span> </code></pre></div> <div><h3 id="walrusoperator">Walrus Operator</h3><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>[i <span class="hljs-keyword">for</span> ch <span class="hljs-keyword">in</span> <span class="hljs-string">'0123'</span> <span class="hljs-keyword">if</span> (i := int(ch))] <span class="hljs-comment"># Assigns to var in mid-sentence.</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>] </code></pre></div> <div><h3 id="namedtupleenumdataclass">Named Tuple, Enum, Dataclass</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> namedtuple Point = namedtuple(<span class="hljs-string">'Point'</span>, <span class="hljs-string">'x y'</span>) <span class="hljs-comment"># Creates tuple's subclass.</span> point = Point(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>) <span class="hljs-comment"># Returns its instance.</span> <span class="hljs-keyword">from</span> enum <span class="hljs-keyword">import</span> Enum Direction = Enum(<span class="hljs-string">'Direction'</span>, <span class="hljs-string">'N E S W'</span>) <span class="hljs-comment"># Creates an enumeration.</span> direction = Direction.N <span class="hljs-comment"># Returns its member.</span> <span class="hljs-keyword">from</span> dataclasses <span class="hljs-keyword">import</span> make_dataclass Player = make_dataclass(<span class="hljs-string">'Player'</span>, [<span class="hljs-string">'p'</span>, <span class="hljs-string">'d'</span>]) <span class="hljs-comment"># Creates a normal class.</span> player = Player(point, direction) <span class="hljs-comment"># Returns its instance.</span> </code></pre></div> <div><h2 id="import"><a href="#import" name="import">#</a>Import</h2><p><strong>Mechanism that makes code in one file available to another file.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> <module> <span class="hljs-comment"># Imports a built-in module or `<module>.py`.</span> <span class="hljs-keyword">import</span> <package> <span class="hljs-comment"># Built-in package or `<package>/__init__.py`.</span> <span class="hljs-keyword">import</span> <package>.<module> <span class="hljs-comment"># Package's module or `<package>/<module>.py`.</span> <span class="hljs-keyword">from</span> <pkg/mod>[.…] <span class="hljs-keyword">import</span> <obj> <span class="hljs-comment"># Imports a module, class, func or variable.</span> </code></pre></div> <ul> <li><strong>Package is a collection of modules, but it can also define its own functions, variables, etc. On a filesystem this corresponds to a directory of Python files with an optional init script.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'import <package>'</span></code> only exposes modules that are imported inside <code class="python hljs"><span class="hljs-string">'__init__.py'</span></code>.</strong></li> <li><strong>Directory of the file that is passed to python command serves as the root of local imports.</strong></li> <li><strong>Use relative imports, i.e. <code class="python hljs"><span class="hljs-string">'from .[…][<pkg/mod>[.…]] import <obj>'</span></code>, if project has scattered entry points. Another option is to install the whole project by moving its code into 'src' dir, adding <a href="https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#basic-information">'pyproject.toml'</a> to its root, and running <code class="python hljs"><span class="hljs-string">'$ pip3 install -e .'</span></code>.</strong></li> </ul> <div><h2 id="closure"><a href="#closure" name="closure">#</a>Closure</h2><p><strong>We have/get a closure in Python when a nested function references a value of its enclosing function and then the enclosing function returns its nested function (any value that is referenced from within multiple nested functions gets shared).</strong></p><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_multiplier</span><span class="hljs-params">(a)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">out</span><span class="hljs-params">(b)</span>:</span> <span class="hljs-keyword">return</span> a * b <span class="hljs-keyword">return</span> out </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>mul_by_3 = get_multiplier(<span class="hljs-number">3</span>) <span class="hljs-meta">>>> </span>mul_by_3(<span class="hljs-number">10</span>) <span class="hljs-number">30</span> </code></pre> <div><h3 id="partial">Partial</h3><p><strong>Partial transforms a function by storing some (or all) of its arguments. It is useful when a function needs to be passed as an argument, e.g. <code class="python hljs"><span class="hljs-string">'collections.defaultdict(<func>)'</span></code>, <code class="python hljs"><span class="hljs-string">'iter(<func>, to_exc)'</span></code> and <code class="python hljs"><span class="hljs-string">'dataclasses.field(default_factory=<func>)'</span></code>.</strong></p><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">mul</span><span class="hljs-params">(a, b)</span>:</span> <span class="hljs-keyword">return</span> a * b </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">import</span> functools <span class="hljs-keyword">as</span> ft <span class="hljs-meta">>>> </span>mul_by_3 = ft.partial(mul, <span class="hljs-number">3</span>) <span class="hljs-meta">>>> </span>mul_by_3(<span class="hljs-number">10</span>) <span class="hljs-number">30</span> </code></pre> <div><h3 id="nonlocal">Non-Local</h3><p><strong>If variable is being assigned to anywhere in the scope (i.e., body of a function), it is treated as a local variable unless it is declared <code class="python hljs"><span class="hljs-string">'global'</span></code> or <code class="python hljs"><span class="hljs-string">'nonlocal'</span></code> before its first usage.</strong></p><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_counter</span><span class="hljs-params">()</span>:</span> i = <span class="hljs-number">0</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">out</span><span class="hljs-params">()</span>:</span> <span class="hljs-keyword">nonlocal</span> i i += <span class="hljs-number">1</span> <span class="hljs-keyword">return</span> i <span class="hljs-keyword">return</span> out </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>counter = get_counter() <span class="hljs-meta">>>> </span>counter(), counter(), counter() (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) </code></pre> <div class="pagebreak"></div><div><h2 id="decorator"><a href="#decorator" name="decorator">#</a>Decorator</h2><p><strong>A decorator takes a function, adds some functionality and returns it. It can be any <a href="#callable">callable</a>, but is usually implemented as a function that returns a <a href="#closure">closure</a>.</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">@decorator_name</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func_that_is_passed_to_dec</span><span class="hljs-params">()</span>:</span> ... </code></pre></div> <div><h3 id="debugger">Debugger</h3><p><strong>Prints function's name every time function is called. It uses <code class="python hljs"><span class="hljs-string">'@wraps'</span></code> decorator to move the metadata from func() into out(). Without it, <code class="python hljs"><span class="hljs-string">'add.__name__'</span></code> would return <code class="python hljs"><span class="hljs-string">'out'</span></code>.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">debug</span><span class="hljs-params">(func)</span>:</span> <span class="hljs-meta"> @wraps(func)</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">out</span><span class="hljs-params">(*args, **kwargs)</span>:</span> print(func.__name__) <span class="hljs-keyword">return</span> func(*args, **kwargs) <span class="hljs-keyword">return</span> out <span class="hljs-meta">@debug</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span><span class="hljs-params">(x, y)</span>:</span> <span class="hljs-keyword">return</span> x + y </code></pre></div> <div><h3 id="cache">Cache</h3><p><strong>Stores function's return values and reuses them later. To clear stored return values run <code class="python hljs"><span class="hljs-string">'<func>.cache_clear()'</span></code>, or use <code class="python hljs"><span class="hljs-string">'@lru_cache(maxsize=<int>)'</span></code> decorator instead.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> cache <span class="hljs-meta">@cache</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fibonacci</span><span class="hljs-params">(n)</span>:</span> <span class="hljs-keyword">return</span> n <span class="hljs-keyword">if</span> n < <span class="hljs-number">2</span> <span class="hljs-keyword">else</span> fibonacci(n-<span class="hljs-number">2</span>) + fibonacci(n-<span class="hljs-number">1</span>)</code></pre></div> <ul> <li><strong>CPython interpreter limits recursion depth to 3000 by default.</strong></li> <li><strong>To increase this limit run <code class="python hljs"><span class="hljs-string">'sys.setrecursionlimit(<int>)'</span></code>.</strong></li> </ul> <div><h3 id="debugwithargs">Debug with Args</h3><p><strong>Decorator that prints function's name and optionally also it's result.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">debug</span><span class="hljs-params">(print_result=<span class="hljs-keyword">False</span>)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">decorator</span><span class="hljs-params">(func)</span>:</span> <span class="hljs-meta"> @wraps(func)</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">out</span><span class="hljs-params">(*args, **kwargs)</span>:</span> print(func.__name__) res = func(*args, **kwargs) <span class="hljs-keyword">if</span> print_result: print(res) <span class="hljs-keyword">return</span> res <span class="hljs-keyword">return</span> out <span class="hljs-keyword">return</span> decorator <span class="hljs-meta">@debug(print_result=True)</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span><span class="hljs-params">(x, y)</span>:</span> <span class="hljs-keyword">return</span> x + y </code></pre></div> <ul> <li><strong>Using <code class="python hljs"><span class="hljs-string">'@debug'</span></code> without arguments won't work here because add() is then passed via 'print_result' argument. To fix this issue use <code class="python hljs"><span class="hljs-string">'def debug(fn=None, *, ...)'</span></code> in def and <code class="python hljs"><span class="hljs-string">'return decorator(fn) if fn else decorator'</span></code> as the last line.</strong></li> </ul> <div><h2 id="class"><a href="#class" name="class">#</a>Class</h2><p><strong>A template for creating user-defined objects.</strong></p><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span> self.a = a <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__str__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> str(self.a) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__repr__</span><span class="hljs-params">(self)</span>:</span> class_name = self.__class__.__name__ <span class="hljs-keyword">return</span> <span class="hljs-string">f'<span class="hljs-subst">{class_name}</span>(<span class="hljs-subst">{self.a!r}</span>)'</span> <span class="hljs-meta"> @classmethod</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_class_name</span><span class="hljs-params">(cls)</span>:</span> <span class="hljs-keyword">return</span> cls.__name__ </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>obj = MyClass(<span class="hljs-number">1</span>) <span class="hljs-meta">>>> </span>obj.a, str(obj), repr(obj) (<span class="hljs-number">1</span>, <span class="hljs-string">'1'</span>, <span class="hljs-string">'MyClass(1)'</span>) </code></pre> <ul> <li><strong>Methods whose names start and end with two underscores are called special methods.</strong></li> <li><strong>They are executed when object is passed to a built-in function or used as an operand. For example, <code class="python hljs"><span class="hljs-string">'print(a)'</span></code> calls <code class="python hljs"><span class="hljs-string">'a.__str__()'</span></code> and <code class="python hljs"><span class="hljs-string">'a + b'</span></code> calls <code class="python hljs"><span class="hljs-string">'a.__add__(b)'</span></code>.</strong></li> <li><strong>See module <a href="#operator">operator</a> to get names of all special methods that are called by operators.</strong></li> <li><strong>Methods that are decorated with <code class="python hljs"><span class="hljs-string">'@staticmethod'</span></code> receive neither 'self' nor 'cls' arg.</strong></li> <li><strong>Return value of str() special method should be readable and of repr() unambiguous.<br>All calls to str() special method are dispatched to repr() when only repr() is provided.</strong></li> </ul> <div><h4 id="expressionsthatcallstrspecialmethod">Expressions that call str() special method:</h4><pre><code class="python language-python hljs"><span class="hljs-string">f'<span class="hljs-subst">{obj}</span>'</span> str(obj) print(obj) </code></pre></div> <div><h4 id="expressionsthatcallreprspecialmethod">Expressions that call repr() special method:</h4><pre><code class="python language-python hljs"><span class="hljs-string">f'<span class="hljs-subst">{obj!r}</span>'</span> str/repr/print([obj]) str/repr/print({obj: obj}) str/repr/print(MyDataClass(obj)) </code></pre></div> <div><h3 id="subclass">Subclass</h3><ul> <li><strong>Inheritance is a mechanism that enables a class to extend some other class (i.e. subclass to extend its parent) and by doing so inherit all of its methods and attributes.</strong></li> <li><strong>Subclass can then add its own methods and attributes or override inherited ones by reusing their names.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, name)</span>:</span> self.name = name <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__repr__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> <span class="hljs-string">f'Person(<span class="hljs-subst">{self.name!r}</span>)'</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__lt__</span><span class="hljs-params">(self, other)</span>:</span> <span class="hljs-keyword">return</span> self.name < other.name <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Employee</span><span class="hljs-params">(Person)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, name, staff_num)</span>:</span> super().__init__(name) self.staff_num = staff_num <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__repr__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> <span class="hljs-string">f'Employee(<span class="hljs-subst">{self.name!r}</span>, <span class="hljs-subst">{self.staff_num}</span>)'</span> </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>people = [Person(<span class="hljs-string">'Bob'</span>), Employee(<span class="hljs-string">'Ann'</span>, <span class="hljs-number">0</span>)] <span class="hljs-meta">>>> </span>sorted(people) [Employee(<span class="hljs-string">'Ann'</span>, <span class="hljs-number">0</span>), Person(<span class="hljs-string">'Bob'</span>)] </code></pre> <div><h3 id="typeannotations">Type Annotations</h3><p><strong>They are used by type checkers like <a href="https://pypi.org/project/mypy/">mypy</a> and <a href="https://pypi.org/project/pydantic/">Pydantic</a>, however they are not enforced by CPython interpreter. To annotate a function use <code class="python hljs"><span class="hljs-string">'def f(a: int = 0) -> int: ...'</span></code>.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> collections.abc <span class="hljs-keyword">import</span> * <name>: <type> [| ...] [= <obj>] <name>: list/set/Iterable/Sequence[<type>] [= <obj>] <name>: tuple/dict[<type>, ...] [= <obj>] </code></pre></div> <div><h3 id="dataclass">Dataclass</h3><p><strong>It uses class variables to generate init(), repr() and eq() special methods.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> dataclasses <span class="hljs-keyword">as</span> dc </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">@dc.dataclass(order=False, frozen=False)</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span>:</span> <attr_name>: <type> <attr_name>: <type> = <obj> <attr_name>: list = dc.field(default_factory=list) </code></pre> <ul> <li><strong>Objects can be made <a href="#sortable">sortable</a> with <code class="python hljs"><span class="hljs-string">'order=True'</span></code> and immutable with <code class="python hljs"><span class="hljs-string">'frozen=True'</span></code>.</strong></li> <li><strong>For object to be <a href="#hashable">hashable</a>, all attributes must be hashable and <code class="python hljs"><span class="hljs-string">'frozen'</span></code> must be <code class="python hljs"><span class="hljs-string">'True'</span></code>.</strong></li> <li><strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">'<attr_name>: list = []'</span></code> would make a list that is shared among all instances. Its 'default_factory' argument accepts any <a href="#callable">callable</a> object.</strong></li> <li><strong>For attributes and arguments of arbitrary type use <code class="python hljs"><span class="hljs-string">'<attr_name>: typing.Any'</span></code>.</strong></li> </ul> <div><h4 id="inline-1">Inline:</h4><pre><code class="python language-python hljs">P = dc.make_dataclass(<span class="hljs-string">'P'</span>, [<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>]) P = dc.make_dataclass(<span class="hljs-string">'P'</span>, [(<span class="hljs-string">'x'</span>, float), (<span class="hljs-string">'y'</span>, float)]) P = dc.make_dataclass(<span class="hljs-string">'P'</span>, [(<span class="hljs-string">'x'</span>, float, <span class="hljs-number">0</span>), (<span class="hljs-string">'y'</span>, float, <span class="hljs-number">0</span>)]) </code></pre></div> <div><h3 id="property">Property</h3><p><strong>Pythonic way of implementing getters and setters.</strong></p><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span> <span class="hljs-meta"> @property</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">name</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> <span class="hljs-string">' '</span>.join(self._name) <span class="hljs-meta"> @name.setter</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">name</span><span class="hljs-params">(self, value)</span>:</span> self._name = value.split() </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>person = Person() <span class="hljs-meta">>>> </span>person.name = <span class="hljs-string">'\t Guido van Rossum \n'</span> <span class="hljs-meta">>>> </span>person.name <span class="hljs-string">'Guido van Rossum'</span> </code></pre> <div><h3 id="slots">Slots</h3><p><strong>Mechanism restricting objects to listed attributes.</strong></p><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Point</span>:</span> __slots__ = (<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>) </code></pre></div> <div><h3 id="copy">Copy</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> copy <span class="hljs-keyword">import</span> copy, deepcopy <object> = copy/deepcopy(<object>) </code></pre></div> <div><h2 id="ducktypes"><a href="#ducktypes" name="ducktypes">#</a>Duck Types</h2><p><strong>A duck type is an implicit type that prescribes a set of special methods. Any object that possesses all of the duck type's prescribed methods is considered a member of that duck type.</strong></p><div><h3 id="comparable">Comparable</h3><ul> <li><strong>If eq() method is not overridden, it returns <code class="python hljs"><span class="hljs-string">'id(self) == id(other)'</span></code>, which is the same as <code class="python hljs"><span class="hljs-string">'self is other'</span></code>. That means all user-defined objects compare not equal by default (because id() returns object's memory address that is guaranteed to be unique).</strong></li> <li><strong>Only the left side object has eq() method called, unless it returns NotImplemented, in which case the right object is consulted. Result is False if both return NotImplemented.</strong></li> <li><strong>Method ne() (called by <code class="python hljs"><span class="hljs-string">'!='</span></code>) automatically works on any object that has eq() defined.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyComparable</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span> self.a = a <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__eq__</span><span class="hljs-params">(self, other)</span>:</span> <span class="hljs-keyword">if</span> isinstance(other, type(self)): <span class="hljs-keyword">return</span> self.a == other.a <span class="hljs-keyword">return</span> <span class="hljs-built_in">NotImplemented</span> </code></pre></div></div> <div><h3 id="hashable">Hashable</h3><ul> <li><strong>Hashable object needs hash() and eq() methods and its hash value must never change.</strong></li> <li><strong>Hashable objects that compare equal must have the same hash value, meaning default hash() that returns <code class="python hljs"><span class="hljs-string">'id(self)'</span></code> will not do. That is why Python automatically makes classes unhashable if you only implement the eq() method.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyHashable</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span> self._a = a <span class="hljs-meta"> @property</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">a</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> self._a <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__eq__</span><span class="hljs-params">(self, other)</span>:</span> <span class="hljs-keyword">if</span> isinstance(other, type(self)): <span class="hljs-keyword">return</span> self.a == other.a <span class="hljs-keyword">return</span> <span class="hljs-built_in">NotImplemented</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__hash__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> hash(self.a) </code></pre></div> <div><h3 id="sortable">Sortable</h3><ul> <li><strong>With 'total_ordering' decorator, you only need to provide eq() and one of lt(), gt(), le() or ge() special methods (called by <, >, <=, >=) and the rest will be automatically generated.</strong></li> <li><strong>Built-in functions sorted() and min() only require lt() method, while max() only requires gt(). However, it's best to define them all so that confusion doesn't arise in other context.</strong></li> <li><strong>When two lists, strings, or data classes are compared, their values get compared one by one until a pair of unequal values is found. The comparison of this two values is then returned. The shorter sequence is considered smaller in case of all their values being equal.</strong></li> <li><strong>To sort collection of strings in proper alphabetical order pass <code class="python hljs"><span class="hljs-string">'key=locale.strxfrm'</span></code> to sorted() after running <code class="python hljs"><span class="hljs-string">'locale.setlocale(locale.LC_COLLATE, "en_US.UTF-8")'</span></code>.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> total_ordering <span class="hljs-meta">@total_ordering</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MySortable</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span> self.a = a <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__eq__</span><span class="hljs-params">(self, other)</span>:</span> <span class="hljs-keyword">if</span> isinstance(other, type(self)): <span class="hljs-keyword">return</span> self.a == other.a <span class="hljs-keyword">return</span> <span class="hljs-built_in">NotImplemented</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__lt__</span><span class="hljs-params">(self, other)</span>:</span> <span class="hljs-keyword">if</span> isinstance(other, type(self)): <span class="hljs-keyword">return</span> self.a < other.a <span class="hljs-keyword">return</span> <span class="hljs-built_in">NotImplemented</span> </code></pre></div> <div><h3 id="iterator-1">Iterator</h3><ul> <li><strong>Any object that has special methods next() and iter() is an iterator.</strong></li> <li><strong>Next() should return the next item or raise StopIteration exception.</strong></li> <li><strong>Iter() should return an unmodified iterator, i.e. the 'self' argument.</strong></li> <li><strong>Any object that has iter() special method can be used in a for loop.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span> self.i = <span class="hljs-number">0</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__next__</span><span class="hljs-params">(self)</span>:</span> self.i += <span class="hljs-number">1</span> <span class="hljs-keyword">return</span> self.i <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__iter__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> self </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>counter = Counter() <span class="hljs-meta">>>> </span>next(counter), next(counter), next(counter) (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) </code></pre> <div><h4 id="pythonhasmanydifferentiteratorobjects">Python has many different iterator objects:</h4><ul> <li><strong>Sequence iterators returned by the <a href="#iterator">iter()</a> function, such as 'list_iterator'.</strong></li> <li><strong>Objects returned by the <a href="#iterator">itertools</a> module, such as count, repeat and cycle.</strong></li> <li><strong>Generator objects returned by the generator <a href="#generator">functions</a> and <a href="#comprehensions">expressions</a>.</strong></li> <li><strong>File objects returned by the <a href="#open">open()</a> function, <a href="#sqlite">SQLite</a> cursor objects, etc.</strong></li> </ul><div><h3 id="callable">Callable</h3><ul> <li><strong>All functions and classes have a call() method that is executed when they are called.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'callable(<obj>)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(<obj>, collections.abc.Callable)'</span></code> to check if object is callable and <code class="python hljs"><span class="hljs-string">'inspect.signature(<obj>)'</span></code> for info about args.</strong></li> <li><strong>When this text uses <code class="python hljs"><span class="hljs-string">'<function>'</span></code> as an argument, it actually means <code class="python hljs"><span class="hljs-string">'<callable>'</span></code>.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span> self.i = <span class="hljs-number">0</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__call__</span><span class="hljs-params">(self, step)</span>:</span> self.i += step <span class="hljs-keyword">return</span> self.i </code></pre></div></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>counter = Counter() <span class="hljs-meta">>>> </span>counter(<span class="hljs-number">1</span>), counter(<span class="hljs-number">1</span>), counter(<span class="hljs-number">1</span>) (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) </code></pre> <div><h3 id="contextmanager">Context Manager</h3><ul> <li><strong>With statements only work on objects that have enter() and exit() special methods.</strong></li> <li><strong>Enter() should lock the resources and optionally return an object (file, socket, etc.).</strong></li> <li><strong>Exit() should release the resources (for example close the file, release the lock, etc.).</strong></li> <li><strong>Any exception that happens inside the with block is passed to exit() method. Exit() can then suppress this exception by returning a true value (not None, False, 0, etc.).</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyOpen</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, filename)</span>:</span> self.filename = filename <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__enter__</span><span class="hljs-params">(self)</span>:</span> self.file = open(self.filename) <span class="hljs-keyword">return</span> self.file <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__exit__</span><span class="hljs-params">(self, exc_type, exception, traceback)</span>:</span> self.file.close() </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">with</span> open(<span class="hljs-string">'test.txt'</span>, <span class="hljs-string">'w'</span>) <span class="hljs-keyword">as</span> file: <span class="hljs-meta">... </span> file.write(<span class="hljs-string">'Hello World!'</span>) <span class="hljs-meta">>>> </span><span class="hljs-keyword">with</span> MyOpen(<span class="hljs-string">'test.txt'</span>) <span class="hljs-keyword">as</span> file: <span class="hljs-meta">... </span> print(file.read()) Hello World! </code></pre> <div><h2 id="iterableducktypes"><a href="#iterableducktypes" name="iterableducktypes">#</a>Iterable Duck Types</h2><div><h3 id="iterable">Iterable</h3><ul> <li><strong>Only required special method is iter(). It should return an iterator of object's items.</strong></li> <li><strong>Special method contains() automatically works on any object that has iter() defined.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyIterable</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span> self.a = a <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__iter__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> iter(self.a) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__contains__</span><span class="hljs-params">(self, el)</span>:</span> <span class="hljs-keyword">return</span> el <span class="hljs-keyword">in</span> self.a </code></pre></div></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>obj = MyIterable([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]) <span class="hljs-meta">>>> </span>[el <span class="hljs-keyword">for</span> el <span class="hljs-keyword">in</span> obj] [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>] <span class="hljs-meta">>>> </span><span class="hljs-number">1</span> <span class="hljs-keyword">in</span> obj <span class="hljs-keyword">True</span> </code></pre> <div><h3 id="collection">Collection</h3><ul> <li><strong>Only required methods are iter() and len(). Len() should return the length of collection.</strong></li> <li><strong>This text refers to all iterable objects as collections, which is technically incorrect. The term <em>iterable</em> was avoided because it sounds scarier and more vague than <em>collection</em>. The main drawback of this decision is that the reader could think a certain function doesn't accept iterators when it actually does, since iterators are the only built-in objects that are iterable but are not collections.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyCollection</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span> self.a = a <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__iter__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> iter(self.a) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__contains__</span><span class="hljs-params">(self, el)</span>:</span> <span class="hljs-keyword">return</span> el <span class="hljs-keyword">in</span> self.a <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__len__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> len(self.a) </code></pre></div> <div><h3 id="sequence">Sequence</h3><ul> <li><strong>Only required methods are len() and getitem(). Getitem() should return an item at the passed index or raise IndexError (it may also support negative indices and/or slices).</strong></li> <li><strong>Iter() and contains() automatically work on any object with defined getitem() method.</strong></li> <li><strong>Reversed() automatically works on any object that has len() and getitem() defined. It returns reversed iterator of object's items.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MySequence</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span> self.a = a <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__iter__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> iter(self.a) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__contains__</span><span class="hljs-params">(self, el)</span>:</span> <span class="hljs-keyword">return</span> el <span class="hljs-keyword">in</span> self.a <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__len__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> len(self.a) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__getitem__</span><span class="hljs-params">(self, i)</span>:</span> <span class="hljs-keyword">return</span> self.a[i] <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__reversed__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> reversed(self.a) </code></pre></div> <div><h4 id="discrepanciesbetweenglossarydefinitionsandabstractbaseclasses">Discrepancies between glossary definitions and abstract base classes:</h4><ul> <li><strong>Python's <a href="https://docs.python.org/3/glossary.html">glossary</a> defines iterable as any object with special methods iter() or getitem(), and sequence as any object with getitem() and len(). It doesn't define the term <em>collection</em>.</strong></li> <li><strong>Using <a href="#abstractbaseclasses">ABC</a> Iterable with isinstance() or issubclass() only checks whether object/class has special method iter(), while ABC Collection checks for iter(), contains() and len().</strong></li> </ul></div> <div><h3 id="abcsequence">ABC Sequence</h3><ul> <li><strong>It's a richer interface than the basic sequence that also requires just len() and getitem().</strong></li> <li><strong>Extending it generates iter(), contains(), reversed(), index() and count() special methods.</strong></li> <li><strong>Unlike <code class="python hljs"><span class="hljs-string">'abc.Iterable'</span></code> and <code class="python hljs"><span class="hljs-string">'abc.Collection'</span></code>, it is not a duck type. That is why exp. <code class="python hljs"><span class="hljs-string">'issubclass(MySequence, abc.Sequence)'</span></code> would return False even if MySequence had all methods defined. It however recognizes list, tuple, range, string, bytes, bytearray, array, memoryview and deque, since they are registered as Sequence's virtual subclasses.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> abc <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyAbcSequence</span><span class="hljs-params">(abc.Sequence)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span> self.a = a <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__len__</span><span class="hljs-params">(self)</span>:</span> <span class="hljs-keyword">return</span> len(self.a) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__getitem__</span><span class="hljs-params">(self, i)</span>:</span> <span class="hljs-keyword">return</span> self.a[i] </code></pre></div><div><h4 id="requiredandautomaticallyavailablemethods">Required and automatically available methods:</h4><pre><code class="text language-text">┏━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━┓ ┃ │ Iterable │ Collection │ Sequence │ abc.Sequence ┃ ┠──────────────┼────────────┼────────────┼────────────┼──────────────┨ ┃ __iter__ │ ! │ ! │ ✓ │ ✓ ┃ ┃ __contains__ │ ✓ │ ✓ │ ✓ │ ✓ ┃ ┃ __len__ │ │ ! │ ! │ ! ┃ ┃ __getitem__ │ │ │ ! │ ! ┃ ┃ __reversed__ │ │ │ ✓ │ ✓ ┃ ┃ index │ │ │ │ ✓ ┃ ┃ count │ │ │ │ ✓ ┃ ┗━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━┛ </code></pre></div> <ul> <li><strong>Method iter() is required for <code class="python hljs"><span class="hljs-string">'isinstance(<obj>, abc.Iterable)'</span></code> to return True, however any object with getitem() method works with any code expecting an iterable.</strong></li> <li><strong>MutableSequence, Set, MutableSet, Mapping and MutableMapping ABCs are also extendable. Use <code class="python hljs"><span class="hljs-string">'<abc>.__abstractmethods__'</span></code> to get names of required methods.</strong></li> </ul> <div><h2 id="enum"><a href="#enum" name="enum">#</a>Enum</h2><p><strong>Class of named constants called members.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> enum <span class="hljs-keyword">import</span> Enum, auto </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyEnum</span><span class="hljs-params">(Enum)</span>:</span> <member_name> = auto() <span class="hljs-comment"># An increment of last numeric value or 1.</span> <member_name> = <value> <span class="hljs-comment"># Values don't have to be hashable/unique.</span> <member_name> = <el>, <el>, ... <span class="hljs-comment"># Value can be a collection, e.g. a tuple.</span> </code></pre> <ul> <li><strong>Methods receive the member they were called on as the 'self' argument.</strong></li> <li><strong>Accessing a member named after a reserved keyword raises SyntaxError.</strong></li> </ul> <pre><code class="python language-python hljs"><memb> = <enum>.<member_name> <span class="hljs-comment"># Accesses a member via enum's attribute.</span> <memb> = <enum>[<span class="hljs-string">'<member_name>'</span>] <span class="hljs-comment"># Returns the member or raises KeyError.</span> <memb> = <enum>(<value>) <span class="hljs-comment"># Returns the member or raises ValueError.</span> <str> = <member>.name <span class="hljs-comment"># Returns the member's name as a string.</span> <obj> = <member>.value <span class="hljs-comment"># Value can't be a user-defined function.</span> </code></pre> <pre><code class="python language-python hljs"><list> = list(<enum>) <span class="hljs-comment"># Returns a list containing every member.</span> <list> = <enum>._member_names_ <span class="hljs-comment"># Returns a list containing member names.</span> <list> = [m.value <span class="hljs-keyword">for</span> m <span class="hljs-keyword">in</span> <enum>] <span class="hljs-comment"># Returns a list containing member values.</span> </code></pre> <pre><code class="python language-python hljs"><enum> = type(<member>) <span class="hljs-comment"># Returns an enum. Also <memb>.__class__.</span> <iter> = itertools.cycle(<enum>) <span class="hljs-comment"># Returns an endless iterator of members.</span> <memb> = random.choice(list(<enum>)) <span class="hljs-comment"># Randomly selects one of enum's members.</span> </code></pre> <div><h3 id="inline-2">Inline</h3><pre><code class="python language-python hljs">Cutlery = Enum(<span class="hljs-string">'Cutlery'</span>, <span class="hljs-string">'FORK KNIFE SPOON'</span>) Cutlery = Enum(<span class="hljs-string">'Cutlery'</span>, [<span class="hljs-string">'FORK'</span>, <span class="hljs-string">'KNIFE'</span>, <span class="hljs-string">'SPOON'</span>]) Cutlery = Enum(<span class="hljs-string">'Cutlery'</span>, {<span class="hljs-string">'FORK'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'KNIFE'</span>: <span class="hljs-number">2</span>, <span class="hljs-string">'SPOON'</span>: <span class="hljs-number">3</span>}) </code></pre></div> <div><h4 id="userdefinedfunctionscannotbevaluessotheymustbewrapped">User-defined functions cannot be values, so they must be wrapped:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> functools <span class="hljs-keyword">as</span> ft and_ = ft.partial(<span class="hljs-keyword">lambda</span> l, r: l <span class="hljs-keyword">and</span> r) or_ = ft.partial(<span class="hljs-keyword">lambda</span> l, r: l <span class="hljs-keyword">or</span> r) LogicOp = Enum(<span class="hljs-string">'LogicOp'</span>, {<span class="hljs-string">'AND'</span>: and_, <span class="hljs-string">'OR'</span>: or_}) </code></pre></div> <div><h2 id="exceptions"><a href="#exceptions" name="exceptions">#</a>Exceptions</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">try</span>: <code> <span class="hljs-keyword">except</span> <exception>: <code> </code></pre></div> <div><h3 id="fulltrystatement">Full Try Statement</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">try</span>: <code_1> <span class="hljs-keyword">except</span> <exception_a>: <code_2_a> <span class="hljs-keyword">except</span> <exception_b>: <code_2_b> <span class="hljs-keyword">else</span>: <code_2_c> <span class="hljs-keyword">finally</span>: <code_3> </code></pre></div> <ul> <li><strong>Code inside the <code class="python hljs"><span class="hljs-string">'else'</span></code> block will only be executed if <code class="python hljs"><span class="hljs-string">'try'</span></code> block had no exceptions.</strong></li> <li><strong>Code inside the <code class="python hljs"><span class="hljs-string">'finally'</span></code> block will always be executed (unless a signal is received).</strong></li> <li><strong>All variables that are initialized in executed blocks are also visible in all subsequent blocks, as well as outside the try statement (only the function block delimits scope).</strong></li> <li><strong>To catch signals use <code class="python hljs"><span class="hljs-string">'signal.signal(signal_number, my_handler_function)'</span></code>.</strong></li> </ul> <div><h3 id="catchingexceptions">Catching Exceptions</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">except</span> <exception>: ... <span class="hljs-keyword">except</span> <exception> <span class="hljs-keyword">as</span> <name>: ... <span class="hljs-keyword">except</span> (<exception>, ...) [<span class="hljs-keyword">as</span> <name>]: ... </code></pre></div> <ul> <li><strong>Except clause catches all subclasses, e.g. <code class="python hljs"><span class="hljs-string">'OSError'</span></code> is caught by <code class="python hljs"><span class="hljs-string">'except Exception:'</span></code>.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'traceback.print_exc()'</span></code> to print the full error message to standard error stream.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'print(<name>)'</span></code> to print just the cause of the exception (its arguments) to stdout.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'logging.exception(<str>)'</span></code> to log the passed message followed by the full error message of the caught exception. For details about how to set up the logger see <a href="#logging">Logging</a>.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'sys.exc_info()'</span></code> returns type, object and traceback of the caught exception as a tuple.</strong></li> </ul> <div><h3 id="raisingexceptions">Raising Exceptions</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">raise</span> <exception> <span class="hljs-keyword">raise</span> <exception>() <span class="hljs-keyword">raise</span> <exception>(<obj> [, ...]) </code></pre></div> <div><h4 id="reraisingcaughtexception">Re-raising caught exception:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">except</span> <exception> [<span class="hljs-keyword">as</span> <name>]: ... <span class="hljs-keyword">raise</span> </code></pre></div> <div><h3 id="exceptionobject">Exception Object</h3><pre><code class="python language-python hljs">arguments = <name>.args exc_type = <name>.__class__ filename = <name>.__traceback__.tb_frame.f_code.co_filename func_name = <name>.__traceback__.tb_frame.f_code.co_name line_str = linecache.getline(filename, <name>.__traceback__.tb_lineno) trace_str = <span class="hljs-string">''</span>.join(traceback.format_tb(<name>.__traceback__)) error_msg = <span class="hljs-string">''</span>.join(traceback.format_exception(*sys.exc_info())) </code></pre></div> <div><h3 id="builtinexceptions">Built-in Exceptions</h3><pre><code class="text language-text">BaseException ├─ SystemExit <span class="hljs-comment"># Raised when `sys.exit()` is called. See #Exit for details.</span> ├─ KeyboardInterrupt <span class="hljs-comment"># Raised when the user hits the interrupt key, i.e. `ctrl-c`.</span> └─ Exception <span class="hljs-comment"># User-defined exceptions should be derived from this class.</span> ├─ ArithmeticError <span class="hljs-comment"># Base class for arithmetic errors such as ZeroDivisionError.</span> ├─ AssertionError <span class="hljs-comment"># Raised by `assert <exp>` if expression returns false value.</span> ├─ AttributeError <span class="hljs-comment"># Raised when object doesn't have requested attribute/method.</span> ├─ EOFError <span class="hljs-comment"># Raised by `input()` when it hits an end-of-file condition.</span> ├─ LookupError <span class="hljs-comment"># Base class for errors when a collection can't find an item.</span> │ ├─ IndexError <span class="hljs-comment"># Raised when index of a sequence (list/str) is out of range.</span> │ └─ KeyError <span class="hljs-comment"># Raised when a dictionary's key or a set element is missing.</span> ├─ MemoryError <span class="hljs-comment"># Out of memory. May be too late to start deleting variables.</span> ├─ NameError <span class="hljs-comment"># Raised when nonexistent name (variable/func/class) is used.</span> │ └─ UnboundLocalError <span class="hljs-comment"># Raised when a local name is used before it's being defined.</span> ├─ OSError <span class="hljs-comment"># Errors such as FileExistsError and TimeoutError. See #Open.</span> │ └─ ConnectionError <span class="hljs-comment"># Errors such as BrokenPipeError and ConnectionAbortedError.</span> ├─ RuntimeError <span class="hljs-comment"># Is raised by errors that do not fit into other categories.</span> │ ├─ NotImplementedEr… <span class="hljs-comment"># Can be raised by abstract methods or by an unfinished code.</span> │ └─ RecursionError <span class="hljs-comment"># Raised if max recursion depth is exceeded (3k by default).</span> ├─ StopIteration <span class="hljs-comment"># Raised when exhausted (empty) iterator is passed to next().</span> ├─ TypeError <span class="hljs-comment"># Raised when argument of wrong type is passed to a function.</span> └─ ValueError <span class="hljs-comment"># Raised when it has the right type but inappropriate value.</span> </code></pre></div> <div><h4 id="exceptionsraisedbycollections">Exceptions raised by collections:</h4><pre><code class="text language-text">┏━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┓ ┃ │ <list> │ <set> │ <dict> ┃ ┠───────────┼────────────┼────────────┼────────────┨ ┃ [i/key] │ IndexError │ │ KeyError ┃ ┃ .pop() │ IndexError │ KeyError │ KeyError ┃ ┃ .remove() │ ValueError │ KeyError │ ┃ ┃ .index() │ ValueError │ │ ┃ ┗━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┛ </code></pre></div> <div><h4 id="usefulbuiltinexceptions">Useful built-in exceptions:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">raise</span> TypeError(<span class="hljs-string">'Function received argument of the wrong type!'</span>) <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">'Argument has right type but its value is off!'</span>) <span class="hljs-keyword">raise</span> RuntimeError(<span class="hljs-string">'I am too lazy to define my own exception!'</span>) </code></pre></div> <div><h3 id="userdefinedexceptions">User-defined Exceptions</h3><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyError</span><span class="hljs-params">(Exception)</span>:</span> <span class="hljs-keyword">pass</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyInputError</span><span class="hljs-params">(MyError)</span>:</span> <span class="hljs-keyword">pass</span> </code></pre></div> <div><h2 id="exit"><a href="#exit" name="exit">#</a>Exit</h2><p><strong>Exits the interpreter by raising SystemExit exception.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> sys sys.exit() <span class="hljs-comment"># Exits with exit code 0 (success).</span> sys.exit(<int>) <span class="hljs-comment"># Exits with the passed exit code.</span> sys.exit(<obj>) <span class="hljs-comment"># Prints to stderr and exits with 1.</span> </code></pre></div> <div><h2 id="print"><a href="#print" name="print">#</a>Print</h2><pre><code class="python language-python hljs">print(<obj>, ..., sep=<span class="hljs-string">' '</span>, end=<span class="hljs-string">'\n'</span>, file=sys.stdout, flush=<span class="hljs-keyword">False</span>) </code></pre></div> <ul> <li><strong>Use <code class="python hljs"><span class="hljs-string">'file=sys.stderr'</span></code> or <code class="python hljs"><span class="hljs-string">'sys.stderr.write(<str>)'</span></code> for messages about errors.</strong></li> <li><strong>Stdout and stderr streams hold output in a buffer until they receive a string containing '\n' or '\r', buffer reaches 4096 characters, <code class="python hljs"><span class="hljs-string">'flush=True'</span></code> is used, or the program exits.</strong></li> </ul> <div><h3 id="prettyprint">Pretty Print</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> pprint <span class="hljs-keyword">import</span> pprint pprint(<collection>, width=<span class="hljs-number">80</span>, depth=<span class="hljs-keyword">None</span>, compact=<span class="hljs-keyword">False</span>) </code></pre></div> <ul> <li><strong>Each item is printed on its own line if collection exceeds 'width' characters.</strong></li> <li><strong>Nested collections that are <code class="python hljs"><span class="hljs-string">'depth=<int>'</span></code> levels deep get printed as <code class="python hljs"><span class="hljs-string">'...'</span></code>.</strong></li> </ul> <div><h2 id="input"><a href="#input" name="input">#</a>Input</h2><pre><code class="python language-python hljs"><str> = input() </code></pre></div> <ul> <li><strong>Reads a line from the user input or pipe if present (trailing newline gets stripped).</strong></li> <li><strong>If argument is passed, it gets printed to the standard output before input is read.</strong></li> <li><strong>EOFError is raised if user hits EOF (ctrl-d/ctrl-z⏎) or stream is already exhausted.</strong></li> </ul> <div><h2 id="arguments"><a href="#arguments" name="arguments">#</a>Arguments</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> sys scripts_path = sys.argv[<span class="hljs-number">0</span>] arguments = sys.argv[<span class="hljs-number">1</span>:] </code></pre></div> <div><h3 id="argumentparser">Argument Parser</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> argparse <span class="hljs-keyword">import</span> ArgumentParser p = ArgumentParser(description=<str>) <span class="hljs-comment"># Also accepts 'usage' str.</span> p.add_argument(<span class="hljs-string">'-<chr>'</span>, <span class="hljs-string">'--<name>'</span>, action=<span class="hljs-string">'store_true'</span>) <span class="hljs-comment"># Flag (defaults to False).</span> p.add_argument(<span class="hljs-string">'-<chr>'</span>, <span class="hljs-string">'--<name>'</span>, type=<type>) <span class="hljs-comment"># Option (defaults to None).</span> p.add_argument(<span class="hljs-string">'<name>'</span>, type=<type>, nargs=<span class="hljs-number">1</span>) <span class="hljs-comment"># Mandatory first argument.</span> p.add_argument(<span class="hljs-string">'<name>'</span>, type=<type>, nargs=<span class="hljs-string">'+'</span>) <span class="hljs-comment"># Mandatory remaining args.</span> p.add_argument(<span class="hljs-string">'<name>'</span>, type=<type>, nargs=<span class="hljs-string">'?'</span>) <span class="hljs-comment"># Optional argument. Also *.</span> args = p.parse_args() <span class="hljs-comment"># Exits on a parsing error.</span> <obj> = args.<name> <span class="hljs-comment"># Returns `<type>(<arg>)`.</span> </code></pre></div> <ul> <li><strong>Use <code class="python hljs"><span class="hljs-string">'help=<str>'</span></code> to set argument description that is used by <code class="python hljs"><span class="hljs-string">'-h'</span></code>.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'default=<obj>'</span></code> to set option's or argument's default value.</strong></li> </ul> <div><h2 id="open"><a href="#open" name="open">#</a>Open</h2><p><strong>Opens a file and returns the corresponding file object.</strong></p><pre><code class="python language-python hljs"><file> = open(<path>, mode=<span class="hljs-string">'r'</span>, encoding=<span class="hljs-keyword">None</span>, newline=<span class="hljs-keyword">None</span>) </code></pre></div> <ul> <li><strong><code class="python hljs"><span class="hljs-string">'encoding=None'</span></code> means that a default encoding is used, which is platform dependent. Best practice is to use <code class="python hljs"><span class="hljs-string">'encoding="utf-8"'</span></code> until it becomes the default (Python 3.15).</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'newline=None'</span></code> means that all different end of line combinations are converted to '\n' on read, while on write all '\n' characters are converted to the system's default separator.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'newline=""'</span></code> means no conversions take place, but input is still broken into chunks by readline() on every '\n', '\r' and '\r\n'. Passing <code class="python hljs"><span class="hljs-string">'newline="\n"'</span></code> breaks input only on '\n'.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'newline="\r\n"'</span></code> breaks input only on '\r\n' and converts every '\n' to '\r\n' on write.</strong></li> </ul> <div><h3 id="modes">Modes</h3><ul> <li><strong><code class="python hljs"><span class="hljs-string">'r'</span></code> - Reads text from the file (the default option).</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'w'</span></code> - Writes to the file. Deletes existing contents.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'x'</span></code> - Writes or raises FileExistsError if file exists.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'a'</span></code> - Appends. Creates new file if it doesn't exist.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'w+'</span></code> - Reads and writes. Deletes existing contents.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'r+'</span></code> - Reads and writes from the start of the file.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'a+'</span></code> - Reads and writes from the end of the file.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'rb'</span></code> - Reads <a href="#bytes">bytes objects</a>. Also <code class="python hljs"><span class="hljs-string">'wb'</span></code>, <code class="python hljs"><span class="hljs-string">'xb'</span></code>, etc.</strong></li> </ul><div><h3 id="exceptions-1">Exceptions</h3><ul> <li><strong><code class="python hljs"><span class="hljs-string">'FileNotFoundError'</span></code> can be raised when reading with <code class="python hljs"><span class="hljs-string">'r'</span></code> or <code class="python hljs"><span class="hljs-string">'r+'</span></code>.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'FileExistsError'</span></code> exception can be raised when writing with <code class="python hljs"><span class="hljs-string">'x'</span></code>.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'IsADirectoryError'</span></code>, <code class="python hljs"><span class="hljs-string">'PermissionError'</span></code> can be raised by any.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'except OSError [as <name>]: …'</span></code> catches all listed exceptions.</strong></li> </ul><div><h3 id="fileobject">File Object</h3><pre><code class="python language-python hljs"><file>.seek(<span class="hljs-number">0</span>) <span class="hljs-comment"># Moves current position to the file's start.</span> <file>.seek(offset) <span class="hljs-comment"># Moves 'offset' chars/bytes from the start.</span> <file>.seek(<span class="hljs-number">0</span>, <span class="hljs-number">2</span>) <span class="hljs-comment"># Moves current position to the end of file.</span> <b_file>.seek(±offset, origin) <span class="hljs-comment"># Origin: 0 start, 1 current position, 2 end.</span> </code></pre></div></div></div> <pre><code class="python language-python hljs"><obj> = <file>.read(size=<span class="hljs-number">-1</span>) <span class="hljs-comment"># Reads 'size' chars/bytes or until the EOF.</span> <obj> = <file>.readline() <span class="hljs-comment"># Returns a line or empty string/bytes on EOF.</span> <list> = <file>.readlines() <span class="hljs-comment"># Returns remaining lines. Also list(<file>).</span> <obj> = next(<file>) <span class="hljs-comment"># Returns a line using the read-ahead buffer.</span> </code></pre> <pre><code class="python language-python hljs"><file>.write(<obj>) <span class="hljs-comment"># Writes str or bytes object to write buffer.</span> <file>.writelines(<coll>) <span class="hljs-comment"># Writes a coll. of strings or bytes objects.</span> <file>.flush() <span class="hljs-comment"># Flushes write buff. Runs every 4096/8192 B.</span> <file>.close() <span class="hljs-comment"># Closes a file after flushing write buffer.</span> </code></pre> <ul> <li><strong>Methods do not add or strip trailing newlines, not even writelines().</strong></li> </ul> <div><h3 id="readtextfromfile">Read Text from File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_file</span><span class="hljs-params">(filename)</span>:</span> <span class="hljs-keyword">with</span> open(filename, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> file: <span class="hljs-keyword">return</span> file.readlines() </code></pre></div> <div><h3 id="writetexttofile">Write Text to File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_file</span><span class="hljs-params">(filename, text)</span>:</span> <span class="hljs-keyword">with</span> open(filename, <span class="hljs-string">'w'</span>, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> file: file.write(text) </code></pre></div> <div><h2 id="paths"><a href="#paths" name="paths">#</a>Paths</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> os, glob <span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path </code></pre></div> <pre><code class="python language-python hljs"><str> = os.getcwd() <span class="hljs-comment"># Returns working dir. Starts as shell's `$PWD`.</span> <str> = os.path.join(<path>, ...) <span class="hljs-comment"># Uses `os.sep` to join strings or Path objects.</span> <str> = os.path.realpath(<path>) <span class="hljs-comment"># Resolves symlinks and calls os.path.abspath().</span> </code></pre> <pre><code class="python language-python hljs"><str> = os.path.basename(<path>) <span class="hljs-comment"># Returns final component (filename or dirname).</span> <str> = os.path.dirname(<path>) <span class="hljs-comment"># Returns the path without its final component.</span> <tup.> = os.path.splitext(<path>) <span class="hljs-comment"># Splits on last period of the final component.</span> </code></pre> <pre><code class="python language-python hljs"><list> = os.listdir(path=<span class="hljs-string">'.'</span>) <span class="hljs-comment"># Returns all file/dir names located at 'path'.</span> <list> = glob.glob(<span class="hljs-string">'<pattern>'</span>) <span class="hljs-comment"># Returns paths matching the wildcard pattern.</span> </code></pre> <pre><code class="python language-python hljs"><bool> = os.path.exists(<path>) <span class="hljs-comment"># Checks if path exists. Also <Path>.exists().</span> <bool> = os.path.isfile(<path>) <span class="hljs-comment"># Also <Path>.is_file(), <DirEntry>.is_file().</span> <bool> = os.path.isdir(<path>) <span class="hljs-comment"># Also <Path>.is_dir() and <DirEntry>.is_dir().</span> </code></pre> <pre><code class="python language-python hljs"><stat> = os.stat(<path>) <span class="hljs-comment"># A status object. Also <Path/DirEntry>.stat().</span> <num> = <stat>.st_size/st_mtime/… <span class="hljs-comment"># Returns size in bytes, modification time, ...</span> </code></pre> <div><h3 id="direntry">DirEntry</h3><p><strong>Unlike listdir(), scandir() returns DirEntry objects that cache isfile, isdir, and on Windows also stat information, thus significantly increasing the performance of code that requires it.</strong></p><pre><code class="python language-python hljs"><iter> = os.scandir(path=<span class="hljs-string">'.'</span>) <span class="hljs-comment"># Returns DirEntry objects located at the path.</span> <str> = <DirEntry>.path <span class="hljs-comment"># Is absolute if 'path' argument was absolute.</span> <str> = <DirEntry>.name <span class="hljs-comment"># Returns the path's final component as string.</span> <file> = open(<DirEntry>) <span class="hljs-comment"># Opens the file and returns its file object.</span> </code></pre></div> <div><h3 id="pathobject">Path Object</h3><pre><code class="python language-python hljs"><Path> = Path(<path> [, ...]) <span class="hljs-comment"># Accepts strings, Paths, and DirEntry objects.</span> <Path> = <path> / <path> [/ ...] <span class="hljs-comment"># First or second object must be a Path object.</span> <Path> = <Path>.resolve() <span class="hljs-comment"># Returns absolute path with resolved symlinks.</span> </code></pre></div> <pre><code class="python language-python hljs"><Path> = Path() <span class="hljs-comment"># Returns current working dir. Also Path('.').</span> <Path> = Path.cwd() <span class="hljs-comment"># Returns absolute CWD. Also Path().resolve().</span> <Path> = Path.home() <span class="hljs-comment"># Returns the user's absolute home directory.</span> <Path> = Path(__file__) <span class="hljs-comment"># Use resolve() to get module's absolute path.</span> </code></pre> <pre><code class="python language-python hljs"><Path> = <Path>.parent <span class="hljs-comment"># Returns the path without its final component.</span> <str> = <Path>.name <span class="hljs-comment"># Returns final component (i.e. file/dirname).</span> <str> = <Path>.suffix <span class="hljs-comment"># Returns the name's last extension with a dot.</span> <str> = <Path>.stem <span class="hljs-comment"># Returns the name without its last extension.</span> <tup.> = <Path>.parts <span class="hljs-comment"># Starts with '/' or 'C:\' if path is absolute.</span> </code></pre> <pre><code class="python language-python hljs"><iter> = <Path>.iterdir() <span class="hljs-comment"># Returns directory contents as Path objects.</span> <iter> = <Path>.glob(<span class="hljs-string">'<patt>'</span>) <span class="hljs-comment"># Returns Paths matching the wildcard pattern.</span> </code></pre> <pre><code class="python language-python hljs"><str> = str(<Path>) <span class="hljs-comment"># Returns path as string. Also <Path>.as_uri().</span> <file> = open(<Path>) <span class="hljs-comment"># Also <Path>.read_text/write_bytes/…(<args>).</span> </code></pre> <div><h2 id="oscommands"><a href="#oscommands" name="oscommands">#</a>OS Commands</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> os, shutil <span class="hljs-keyword">as</span> sh </code></pre></div> <pre><code class="python language-python hljs">os.chdir(<path>) <span class="hljs-comment"># Changes the current working directory (or CWD).</span> os.mkdir(<path>) <span class="hljs-comment"># Creates dir. Set permissions with `mode=0o777`.</span> os.makedirs(<path>) <span class="hljs-comment"># Creates all path's dirs. Also `exist_ok=False`.</span> </code></pre> <pre><code class="python language-python hljs">sh.copy(from, to) <span class="hljs-comment"># Copies file (arg. 'to' can exist or be a dir).</span> sh.copy2(from, to) <span class="hljs-comment"># Also copies the creation and modification time.</span> sh.copytree(from, to) <span class="hljs-comment"># Copies directory (arg. 'to' should not exist).</span> </code></pre> <pre><code class="python language-python hljs">os.rename(from, to) <span class="hljs-comment"># Renames or moves the file or directory 'from'.</span> os.replace(from, to) <span class="hljs-comment"># Same, but overwrites file 'to' even on Windows.</span> sh.move(from, to) <span class="hljs-comment"># `rename()` that moves into 'to' if it's a dir.</span> </code></pre> <pre><code class="python language-python hljs">os.remove(<path>) <span class="hljs-comment"># Deletes file. Also `$ pip3 install send2trash`.</span> os.rmdir(<path>) <span class="hljs-comment"># Deletes empty dir. Raises OSError if it's not.</span> sh.rmtree(<path>) <span class="hljs-comment"># Deletes the directory and all of its contents.</span> </code></pre> <ul> <li><strong>Passed paths can be either strings, Path objects, or DirEntry objects.</strong></li> <li><strong>Functions report errors by raising OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong></li> </ul> <div><h2 id="shellcommands"><a href="#shellcommands" name="shellcommands">#</a>Shell Commands</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> os, subprocess <span class="hljs-keyword">as</span> sp </code></pre></div> <pre><code class="python language-python hljs"><int> = os.system(<span class="hljs-string">'<cmds>'</span>) <span class="hljs-comment"># Runs commands in sh/cmd shell. Prints results.</span> <proc> = sp.run(<str/list>) <span class="hljs-comment"># For parameters see examples. Prints by default.</span> <pipe> = os.popen(<span class="hljs-string">'<cmds>'</span>) <span class="hljs-comment"># Prints only stderr. Soft deprecated since 3.14.</span> <str> = <pipe>.read() <span class="hljs-comment"># Returns combined stdout. Provides readline/s().</span> <int> = <pipe>.close() <span class="hljs-comment"># Returns None if last command had returncode 0.</span> </code></pre> <div><h4 id="sends11tothebasiccalculatorandcapturesitsstdoutandstderrstreams">Sends "1+1" to the basic calculator and captures its stdout and stderr streams:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>sp.run(<span class="hljs-string">'bc'</span>, input=<span class="hljs-string">'1+1\n'</span>, capture_output=<span class="hljs-keyword">True</span>, text=<span class="hljs-keyword">True</span>) CompletedProcess(args=<span class="hljs-string">'bc'</span>, returncode=<span class="hljs-number">0</span>, stdout=<span class="hljs-string">'2\n'</span>, stderr=<span class="hljs-string">''</span>) </code></pre></div> <div><h4 id="sendstestintobcrunninginstandardmodeandsavesitsstdouttotestout">Sends test.in to `bc` running in standard mode and saves its stdout to test.out:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">if</span> os.system(<span class="hljs-string">'echo 1+1 > test.in'</span>) == <span class="hljs-number">0</span>: <span class="hljs-meta">... </span> <span class="hljs-keyword">with</span> open(<span class="hljs-string">'test.in'</span>) <span class="hljs-keyword">as</span> in_, open(<span class="hljs-string">'test.out'</span>, <span class="hljs-string">'w'</span>) <span class="hljs-keyword">as</span> out: <span class="hljs-meta">... </span> sp.run(shlex.split(<span class="hljs-string">'bc -s'</span>), stdin=in_, stdout=out) <span class="hljs-meta">... </span> print(open(<span class="hljs-string">'test.out'</span>).read()) <span class="hljs-number">2</span> </code></pre></div> <div><h2 id="json"><a href="#json" name="json">#</a>JSON</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> json <str> = json.dumps(<list/dict>) <span class="hljs-comment"># Converts collection to JSON string.</span> <coll> = json.loads(<str>) <span class="hljs-comment"># Converts JSON string to collection.</span> </code></pre></div> <div><h3 id="readcollectionfromjsonfile">Read Collection from JSON File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_json_file</span><span class="hljs-params">(filename)</span>:</span> <span class="hljs-keyword">with</span> open(filename, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> file: <span class="hljs-keyword">return</span> json.load(file) </code></pre></div> <div><h3 id="writecollectiontojsonfile">Write Collection to JSON File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_json_file</span><span class="hljs-params">(filename, coll)</span>:</span> <span class="hljs-keyword">with</span> open(filename, <span class="hljs-string">'w'</span>, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> file: json.dump(coll, file, ensure_ascii=<span class="hljs-keyword">False</span>, indent=<span class="hljs-number">2</span>) </code></pre></div> <div><h2 id="pickle"><a href="#pickle" name="pickle">#</a>Pickle</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> pickle <bytes> = pickle.dumps(<object>) <span class="hljs-comment"># Converts object to bytes object.</span> <object> = pickle.loads(<bytes>) <span class="hljs-comment"># Converts bytes object to object.</span> </code></pre></div> <div><h3 id="readobjectfrompicklefile">Read Object from Pickle File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_pickle_file</span><span class="hljs-params">(filename)</span>:</span> <span class="hljs-keyword">with</span> open(filename, <span class="hljs-string">'rb'</span>) <span class="hljs-keyword">as</span> file: <span class="hljs-keyword">return</span> pickle.load(file) </code></pre></div> <div><h3 id="writeobjecttopicklefile">Write Object to Pickle File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_pickle_file</span><span class="hljs-params">(filename, an_object)</span>:</span> <span class="hljs-keyword">with</span> open(filename, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> file: pickle.dump(an_object, file) </code></pre></div> <div><h2 id="csv"><a href="#csv" name="csv">#</a>CSV</h2><p><strong>Text file format for storing spreadsheets.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> csv </code></pre></div> <pre><code class="python language-python hljs"><file> = open(<path>, newline=<span class="hljs-string">''</span>) <span class="hljs-comment"># Opens the text file for reading.</span> <read> = csv.reader(<file>, <span class="hljs-string">'excel'</span>) <span class="hljs-comment"># Also `delimiter=','`. See Params.</span> <list> = next(<read>) <span class="hljs-comment"># Returns a row as list of strings.</span> <list> = list(<read>) <span class="hljs-comment"># Returns list of remaining rows.</span> </code></pre> <ul> <li><strong>For XML and binary Excel files (with extensions xlsx, xlsm and xlsb) use <a href="#fileformats">Pandas</a> library.</strong></li> <li><strong>To nicely print the spreadsheet to the console use either <a href="#table">Tabulate</a> or PrettyTable library.</strong></li> <li><strong>Reader can consume any iterator or collection of strings, not just text files.</strong></li> </ul> <div><h3 id="write">Write</h3><pre><code class="python language-python hljs"><file> = open(<path>, <span class="hljs-string">'a'</span>, newline=<span class="hljs-string">''</span>) <span class="hljs-comment"># Opens the text file for writing.</span> <write> = csv.writer(<file>, <span class="hljs-string">'excel'</span>) <span class="hljs-comment"># Also `delimiter=','`. See Params.</span> <write>.writerow(<collection>) <span class="hljs-comment"># Encodes objects using str(<obj>).</span> <write>.writerows(<coll_of_coll>) <span class="hljs-comment"># Appends rows to the opened file.</span> </code></pre></div> <ul> <li><strong>Always pass <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument to open(), or newlines embedded inside quoted fields will flip between '\n' and '\r\n' (in some cases '\r\n' may even change to '\r\r\n'). Also rows won't be terminated with passed or dialect's <code class="python hljs"><span class="hljs-string">'lineterminator'</span></code> parameter.</strong></li> <li><strong>Open existing file with <code class="python hljs"><span class="hljs-string">'mode="a"'</span></code> to append to it or <code class="python hljs"><span class="hljs-string">'mode="w"'</span></code> to overwrite it.</strong></li> </ul> <div><h3 id="params">Params</h3><ul> <li><strong><code class="python hljs"><span class="hljs-string">'dialect'</span></code> - Master parameter that sets the default values. String or a <em>csv.Dialect</em> object.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'delimiter'</span></code> - A one-character string that separates fields. Comma, tab, semicolon, etc.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'lineterminator'</span></code> - Sets how writer terminates rows. Reader looks for '\n', '\r' and '\r\n'.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'quotechar'</span></code> - Character for quoting fields containing delimiters, quotechars, '\n' or '\r'.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'escapechar'</span></code> - Character for escaping quotechars. Can be None if doublequote is True.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'doublequote'</span></code> - Whether quotechars inside fields are/get doubled (instead of escaped).</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'quoting'</span></code> - 0: As necessary, 1: All, 2: All but numbers which are read as floats, 3: None.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'skipinitialspace'</span></code> - Is space character at the start of the field stripped by the reader.</strong></li> </ul><div><h3 id="dialects">Dialects</h3><pre><code class="text language-text">┏━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┓ ┃ │ excel │ excel-tab │ unix ┃ ┠──────────────────┼──────────────┼──────────────┼──────────────┨ ┃ delimiter │ ',' │ '\t' │ ',' ┃ ┃ lineterminator │ '\r\n' │ '\r\n' │ '\n' ┃ ┃ quotechar │ '"' │ '"' │ '"' ┃ ┃ escapechar │ None │ None │ None ┃ ┃ doublequote │ True │ True │ True ┃ ┃ quoting │ 0 │ 0 │ 1 ┃ ┃ skipinitialspace │ False │ False │ False ┃ ┗━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┛ </code></pre></div></div> <div><h3 id="readrowsfromcsvfile">Read Rows from CSV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_csv_file</span><span class="hljs-params">(filename, **csv_params)</span>:</span> <span class="hljs-keyword">with</span> open(filename, encoding=<span class="hljs-string">'utf-8'</span>, newline=<span class="hljs-string">''</span>) <span class="hljs-keyword">as</span> file: <span class="hljs-keyword">return</span> list(csv.reader(file, **csv_params)) </code></pre></div> <div><h3 id="writerowstocsvfile">Write Rows to CSV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_csv_file</span><span class="hljs-params">(filename, rows, mode=<span class="hljs-string">'w'</span>, **csv_params)</span>:</span> <span class="hljs-keyword">with</span> open(filename, mode, encoding=<span class="hljs-string">'utf-8'</span>, newline=<span class="hljs-string">''</span>) <span class="hljs-keyword">as</span> file: writer = csv.writer(file, **csv_params) writer.writerows(rows) </code></pre></div> <div><h2 id="sqlite"><a href="#sqlite" name="sqlite">#</a>SQLite</h2><p><strong>A server-less database engine that stores each database into its own file.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> sqlite3 <con> = sqlite3.connect(<path>) <span class="hljs-comment"># Opens existing or new file. Also ':memory:'.</span> <con>.close() <span class="hljs-comment"># Closes connection. Discards uncommitted data.</span> </code></pre></div> <div><h3 id="read">Read</h3><pre><code class="python language-python hljs"><cursor> = <con>.execute(<span class="hljs-string">'SELECT …'</span>) <span class="hljs-comment"># Can raise a subclass of the `sqlite3.Error`.</span> <tuple> = <cursor>.fetchone() <span class="hljs-comment"># Returns the next row. Same as next(<cursor>).</span> <list> = <cursor>.fetchall() <span class="hljs-comment"># Returns remaining rows. Also list(<cursor>).</span> </code></pre></div> <div><h3 id="write-1">Write</h3><pre><code class="python language-python hljs"><con>.execute(<span class="hljs-string">'INSERT …'</span>) <span class="hljs-comment"># Can raise a subclass of the `sqlite3.Error`.</span> <con>.commit() <span class="hljs-comment"># Saves all the changes since the last commit.</span> <con>.rollback() <span class="hljs-comment"># Discards all changes since the last commit.</span> </code></pre></div> <div><h4 id="or">Or:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">with</span> <con>: <span class="hljs-comment"># Exits the block with commit() or rollback(),</span> <con>.execute(<span class="hljs-string">'INSERT …'</span>) <span class="hljs-comment"># depending on whether any exception occurred.</span> </code></pre></div> <div><h3 id="params-1">Params</h3><pre><code class="python language-python hljs"><con>.execute(<sql>, <list/tuple>) <span class="hljs-comment"># Replaces every '?' with corresponding item.</span> <con>.execute(<sql>, <dict/namedtup>) <span class="hljs-comment"># Replaces every ':<key>' with matching value.</span> <con>.executemany(<sql>, <colls>) <span class="hljs-comment"># Executes statement once for each collection.</span> </code></pre></div> <ul> <li><strong>Accepts strings, ints, floats, bytes, None objects, and bools (stored as 1 or 0).</strong></li> <li><strong>Columns are not restricted to any specific type unless table is declared strict.</strong></li> </ul> <div><h3 id="example-1">Example</h3><p><strong>Values are not actually saved in this example because <code class="python hljs"><span class="hljs-string">'con.commit()'</span></code> is omitted!</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>con = sqlite3.connect(<span class="hljs-string">'test.db'</span>) <span class="hljs-meta">>>> </span>con.execute(<span class="hljs-string">'CREATE TABLE person (name TEXT, height INTEGER) STRICT'</span>) <span class="hljs-meta">>>> </span>con.execute(<span class="hljs-string">'INSERT INTO person VALUES (?, ?)'</span>, (<span class="hljs-string">'Jean-Luc'</span>, <span class="hljs-number">187</span>)) <span class="hljs-meta">>>> </span>con.execute(<span class="hljs-string">'SELECT rowid, * FROM person'</span>).fetchall() [(<span class="hljs-number">1</span>, <span class="hljs-string">'Jean-Luc'</span>, <span class="hljs-number">187</span>)] </code></pre></div> <div><h3 id="sqlalchemy">SQLAlchemy</h3><p><strong>Library for interacting with various DB systems via SQL, <a href="https://docs.sqlalchemy.org/en/latest/tutorial/data_select.html#the-select-sql-expression-construct">method chaining</a> or <a href="https://docs.sqlalchemy.org/en/latest/orm/quickstart.html#simple-select">ORM</a>.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install sqlalchemy</span> <span class="hljs-keyword">import</span> sqlalchemy <span class="hljs-keyword">as</span> sa <eng> = sa.create_engine(<url>) <span class="hljs-comment"># Url: 'dialect://user:password@host/dbname'.</span> <con> = <eng>.connect() <span class="hljs-comment"># Creates new connection. Also <con>.close().</span> <cur> = <con>.execute(sa.text(<sql>)) <span class="hljs-comment"># Add dict to execute() to replace ':<key>'s.</span> <span class="hljs-keyword">with</span> <con>.begin(): ... <span class="hljs-comment"># Exits the block with a commit or rollback.</span> </code></pre></div> <pre><code class="text language-text">┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ Dialect │ pip3 install │ Dependencies ┃ ┠─────────────────┼──────────────┼──────────────────────────────────┨ ┃ mysql │ mysqlclient │ www.pypi.org/project/mysqlclient ┃ ┃ postgresql │ psycopg2 │ www.pypi.org/project/psycopg2 ┃ ┃ mssql │ pyodbc │ www.pypi.org/project/pyodbc ┃ ┃ oracle+oracledb │ oracledb │ www.pypi.org/project/oracledb ┃ ┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ </code></pre> <div><h2 id="bytes"><a href="#bytes" name="bytes">#</a>Bytes</h2><p><strong>An immutable sequence of single bytes. Mutable version is called bytearray.</strong></p><pre><code class="python language-python hljs"><bytes> = <span class="hljs-string">b'<str>'</span> <span class="hljs-comment"># Accepts ASCII characters and \x00 to \xff.</span> <int> = <bytes>[index] <span class="hljs-comment"># Returns the byte as int between 0 and 255.</span> <bytes> = <bytes>[<slice>] <span class="hljs-comment"># Returns bytes even if it has one element.</span> <bytes> = <bytes>.join(<coll>) <span class="hljs-comment"># Joins bytes objects using bytes as a sep.</span> </code></pre></div> <div><h3 id="encode-1">Encode</h3><pre><code class="python language-python hljs"><bytes> = bytes(<ints>) <span class="hljs-comment"># Accepts coll of integers between 0 and 255.</span> <bytes> = bytes(<str>, <span class="hljs-string">'utf-8'</span>) <span class="hljs-comment"># Encodes the string. Same as <str>.encode().</span> <bytes> = bytes.fromhex(<span class="hljs-string">'<hex>'</span>) <span class="hljs-comment"># Hex pairs can be separated by whitespaces.</span> <bytes> = <int>.to_bytes(n_bytes) <span class="hljs-comment"># Accepts `byteorder='little', signed=True`.</span> </code></pre></div> <div><h3 id="decode-1">Decode</h3><pre><code class="python language-python hljs"><list> = list(<bytes>) <span class="hljs-comment"># Returns a list of ints between 0 and 255.</span> <str> = str(<bytes>, <span class="hljs-string">'utf-8'</span>) <span class="hljs-comment"># Returns a string. Same as <bytes>.decode().</span> <str> = <bytes>.hex() <span class="hljs-comment"># Returns hex pairs separated by `sep=<str>`.</span> <int> = int.from_bytes(<bytes>) <span class="hljs-comment"># Accepts `byteorder='little', signed=True`.</span> </code></pre></div> <div><h3 id="readbytesfromfile">Read Bytes from File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_bytes</span><span class="hljs-params">(filename)</span>:</span> <span class="hljs-keyword">with</span> open(filename, <span class="hljs-string">'rb'</span>) <span class="hljs-keyword">as</span> file: <span class="hljs-keyword">return</span> file.read() </code></pre></div> <div><h3 id="writebytestofile">Write Bytes to File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_bytes</span><span class="hljs-params">(filename, bytes_obj)</span>:</span> <span class="hljs-keyword">with</span> open(filename, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> file: file.write(bytes_obj) </code></pre></div> <div><h2 id="struct"><a href="#struct" name="struct">#</a>Struct</h2><ul> <li><strong>Performs conversions between a sequence of numbers and a bytes object.</strong></li> <li><strong>System’s type sizes, byte order, and alignment rules are used by default.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> struct <span class="hljs-keyword">import</span> pack, unpack <bytes> = pack(<span class="hljs-string">'<format>'</span>, <num>, ...) <span class="hljs-comment"># Packs numbers according to format.</span> <tuple> = unpack(<span class="hljs-string">'<format>'</span>, <bytes>) <span class="hljs-comment"># Use `iter_unpack()` to get tuples.</span> </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>pack(<span class="hljs-string">'>hhl'</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) <span class="hljs-string">b'\x00\x01\x00\x02\x00\x00\x00\x03'</span> <span class="hljs-meta">>>> </span>unpack(<span class="hljs-string">'bhh'</span>, <span class="hljs-string">b'\x01\x00\x02\x00\x03\x00'</span>) (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) </code></pre> <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignmentpaddingstartformatstringwith">For standard type sizes and manual alignment (padding) start format string with:</h4><ul> <li><strong><code class="python hljs"><span class="hljs-string">'='</span></code> - System's byte order (usually little-endian).</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'<'</span></code> - Little-endian (i.e. least significant byte first).</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'>'</span></code> - Big-endian (also <code class="python hljs"><span class="hljs-string">'!'</span></code>).</strong></li> </ul><div><h4 id="besidesnumberspackandunpackalsosupportbytesobjectsaspartofthesequence">Besides numbers, pack() and unpack() also support bytes objects as part of the sequence:</h4><ul> <li><strong><code class="python hljs"><span class="hljs-string">'c'</span></code> - A bytes object with a single element. For pad byte use <code class="python hljs"><span class="hljs-string">'x'</span></code>.</strong></li> <li><strong><code class="apache hljs"><span class="hljs-section">'<n>s'</span><span class="hljs-attribute"></span></code> - A bytes object with n elements (not effected by byte order).</strong></li> </ul></div></div><div><div><h4 id="integersunsignedtypesusecapitallettersminimumandstandardsizesareinbrackets">Integers. Unsigned types use capital letters. Minimum and standard sizes are in brackets:</h4><ul> <li><strong><code class="python hljs"><span class="hljs-string">'b'</span></code> - char (1/1)</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'h'</span></code> - short (2/2)</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'i'</span></code> - int (2/4)</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'l'</span></code> - long (4/4)</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'q'</span></code> - long long (8/8)</strong></li> </ul></div><div><h4 id="floatingpointtypesstructalwaysusesstandardsizes">Floating point types (struct always uses standard sizes):</h4><ul> <li><strong><code class="python hljs"><span class="hljs-string">'f'</span></code> - float (4/4)</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'d'</span></code> - double (8/8)</strong></li> </ul></div></div> <div><h2 id="array"><a href="#array" name="array">#</a>Array</h2><p><strong>List that can only hold numbers that fit into selected C type. Available types and their minimum sizes in bytes are listed above. Type sizes and byte order are always determined by the system, however bytes of each element can be reversed by calling the byteswap() method.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> array <span class="hljs-keyword">import</span> array </code></pre></div> <pre><code class="python language-python hljs"><array> = array(<span class="hljs-string">'<ctype>'</span> [, <coll>]) <span class="hljs-comment"># Creates array. Accepts collection of numbers.</span> <array> = array(<span class="hljs-string">'<ctype>'</span>, <bytes>) <span class="hljs-comment"># Copies passed bytes into the array's memory.</span> <array> = array(<span class="hljs-string">'<ctype>'</span>, <array>) <span class="hljs-comment"># Treats passed array as a sequence of numbers.</span> <array>.fromfile(<file>, n_items) <span class="hljs-comment"># Appends file contents to the array's memory.</span> </code></pre> <pre><code class="python language-python hljs"><bytes> = bytes(<array>) <span class="hljs-comment"># Returns copy of the memory as a bytes object.</span> <file>.write(<array>) <span class="hljs-comment"># Appends the array's memory to a binary file.</span> </code></pre> <div><h2 id="memoryview"><a href="#memoryview" name="memoryview">#</a>Memory View</h2><p><strong>A sequence object that points to the memory of another bytes-like object. Each element can reference a single or multiple consecutive bytes, depending on format. Order and number of elements can be changed with slicing.</strong></p><pre><code class="python language-python hljs"><mview> = memoryview(<bytes/array>) <span class="hljs-comment"># Returns mutable memoryview if array is passed.</span> <obj> = <mview>[index] <span class="hljs-comment"># Returns an int/float. Bytes if format is 'c'.</span> <mview> = <mview>[<slice>] <span class="hljs-comment"># Returns a memoryview with rearranged elements.</span> <mview> = <mview>.cast(<span class="hljs-string">'<ctype>'</span>) <span class="hljs-comment"># Only works between B/b/c and the other types.</span> <mview>.release() <span class="hljs-comment"># Releases the memory buffer of the base object.</span> </code></pre></div> <pre><code class="python language-python hljs"><bytes> = bytes(<mview>) <span class="hljs-comment"># Returns a new bytes object. Also bytearray().</span> <bytes> = <bytes>.join(<coll>) <span class="hljs-comment"># Joins memoryviews using bytes as a separator.</span> <array> = array(<span class="hljs-string">'<ctype>'</span>, <mview>) <span class="hljs-comment"># Treats passed mview as a sequence of numbers.</span> <file>.write(<mview>) <span class="hljs-comment"># Appends `bytes(<mview>)` to the binary file.</span> </code></pre> <pre><code class="python language-python hljs"><list> = list(<mview>) <span class="hljs-comment"># Returns list of ints, floats or bytes objects.</span> <str> = str(<mview>, <span class="hljs-string">'utf-8'</span>) <span class="hljs-comment"># Treats passed memoryview as `bytes(<mview>)`.</span> <str> = <mview>.hex() <span class="hljs-comment"># Returns hex pairs separated with `sep=<str>`.</span> </code></pre> <div><h2 id="deque"><a href="#deque" name="deque">#</a>Deque</h2><p><strong>List with efficient appends and pops from either side.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> deque </code></pre></div> <pre><code class="python language-python hljs"><deque> = deque(<coll>) <span class="hljs-comment"># Pass `maxlen=<int>` to set the size limit.</span> <deque>.appendleft(<el>) <span class="hljs-comment"># Drops last element if maxlen is exceeded.</span> <deque>.extendleft(<coll>) <span class="hljs-comment"># Prepends reversed collection to the deque.</span> <deque>.rotate(n=<span class="hljs-number">1</span>) <span class="hljs-comment"># Moves last element to the start of deque.</span> <el> = <deque>.popleft() <span class="hljs-comment"># Removes and returns deque's first element.</span> </code></pre> <div><h2 id="operator"><a href="#operator" name="operator">#</a>Operator</h2><p><strong>Module of functions that provide the functionality of operators. Functions are grouped by operator precedence, from least to most binding. Functions/operators in first and third line are also ordered by precedence within a line.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> operator <span class="hljs-keyword">as</span> op </code></pre></div> <pre><code class="python language-python hljs"><bool> = op.not_(<obj>) <span class="hljs-comment"># or, and, not (or/and missing).</span> <bool> = op.eq/ne/lt/ge/is_/is_not/contains(<obj>, <obj>) <span class="hljs-comment"># ==, !=, <, >=, is, is not, in.</span> <obj> = op.or_/xor/and_(<int/set>, <int/set>) <span class="hljs-comment"># |, ^, & (sorted by precedence).</span> <int> = op.lshift/rshift(<int>, <int>) <span class="hljs-comment"># <<, >> (i.e. <int> << n_bits).</span> <obj> = op.add/sub(<obj>, <obj>) <span class="hljs-comment"># +, - (e.g. 'a' + 'b' == 'ab').</span> <obj> = op.mul/truediv/floordiv/mod(<obj>, <obj>) <span class="hljs-comment"># *, /, //, % (evaluated l to r).</span> <num> = op.neg/invert(<num>) <span class="hljs-comment"># -, ~ (negate and bitwise not).</span> <num> = op.pow(<num>, <num>) <span class="hljs-comment"># ** (pow() accepts 3 arguments).</span> <func> = op.itemgetter/attrgetter/methodcaller(<obj>, …) <span class="hljs-comment"># [i/key], .attr_name, .name(…).</span> </code></pre> <pre><code class="python language-python hljs">elementwise_sum = map(op.add, list_a, list_b) sorted_by_second = sorted(<coll>, key=op.itemgetter(<span class="hljs-number">1</span>)) sorted_by_both = sorted(<coll>, key=op.itemgetter(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>)) </code></pre> <ul> <li><strong>Most operators call the object's special method that is named after them (second object is passed as an argument), while logical operators call their own code that relies on bool().</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'and/or'</span></code> can't be emulated by a function because they might not evaluate all operands.</strong></li> <li><strong>Comparisons can be chained: <code class="python hljs"><span class="hljs-string">'x < y < z'</span></code> gets converted to <code class="python hljs"><span class="hljs-string">'(x < y) and (y < z)'</span></code>.</strong></li> </ul> <div><h2 id="matchstatement"><a href="#matchstatement" name="matchstatement">#</a>Match Statement</h2><p><strong>Executes the first block with matching pattern.</strong></p><pre><code class="python language-python hljs"><code class="python language-python hljs"><span class="hljs-keyword">match</span> <obj/expr>: <span class="hljs-keyword">case</span> <pattern> [<span class="hljs-keyword">if</span> <cond>]: <code> ... </code></code></pre></div> <div><h3 id="patterns">Patterns</h3><pre><code class="python language-python hljs"><val_patt> = <span class="hljs-number">1</span>/<span class="hljs-string">'a'</span>/<span class="hljs-keyword">True</span>/<span class="hljs-keyword">None</span>/math.pi <span class="hljs-comment"># Matches the literal or attribute's value.</span> <cls_patt> = <type>() <span class="hljs-comment"># Matches any object of that type (or ABC).</span> <wildcard> = _ <span class="hljs-comment"># Matches any object. Useful in last case.</span> <capture> = <name> <span class="hljs-comment"># Matches any object and binds it to name.</span> <as_patt> = <pattern> <span class="hljs-keyword">as</span> <name> <span class="hljs-comment"># Binds match to name. Also <type>(<name>).</span> <or_patt> = <pattern> | ... <span class="hljs-comment"># Matches if any of listed patterns match.</span> <seq_patt> = [<pattern>, ...] <span class="hljs-comment"># Matches a sequence. All items must match.</span> <map_patt> = {<val_patt>: <patt>, ...} <span class="hljs-comment"># Matches a dict if it has matching items.</span> <cls_patt> = <type>(<name>=<patt>, ...) <span class="hljs-comment"># Matches object with matching attributes.</span> </code></pre></div> <ul> <li><strong>The sequence pattern can also be written as a tuple, either with or without the brackets.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'*<name>'</span></code> and <code class="python hljs"><span class="hljs-string">'**<name>'</span></code> in sequence/mapping patterns to bind remaining items.</strong></li> <li><strong>Patterns can be surrounded with brackets to override their precedence: <code class="python hljs"><span class="hljs-string">'|'</span></code> > <code class="python hljs"><span class="hljs-string">'as'</span></code> > <code class="python hljs"><span class="hljs-string">','</span></code>. For example, <code class="python hljs"><span class="hljs-string">'[1, 2]'</span></code> is matched by expression <code class="python hljs"><span class="hljs-string">'case 1|2, 2|3 as y if y == 2:'</span></code>.</strong></li> <li><strong>All names that are bound in the matching case, as well as variables initialized in its body, are visible after the match statement (only function block delimits scope).</strong></li> </ul> <div><h3 id="example-2">Example</h3><pre><code class="python language-python hljs"><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path <span class="hljs-meta">>>> </span><span class="hljs-keyword">match</span> Path(<span class="hljs-string">'/home/bwk/documents/README.md'</span>): <span class="hljs-meta">... </span> <span class="hljs-keyword">case</span> Path( <span class="hljs-meta">... </span> parts=[<span class="hljs-string">'/'</span>, <span class="hljs-string">'home'</span>, user, *_, name] <span class="hljs-meta">... </span> ) <span class="hljs-keyword">as</span> p <span class="hljs-keyword">if</span> p.is_file() <span class="hljs-keyword">and</span> <span class="hljs-string">'readme'</span> <span class="hljs-keyword">in</span> name.lower(): <span class="hljs-meta">... </span> print(<span class="hljs-string">f"{name} is {user}'s readme file."</span>) README.md is bwk's readme file. </code></code></pre></div> <div><h2 id="logging"><a href="#logging" name="logging">#</a>Logging</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> logging <span class="hljs-keyword">as</span> log </code></pre></div> <pre><code class="python language-python hljs">log.basicConfig(filename=<path>) <span class="hljs-comment"># Configures the root logger (see Setup).</span> log.debug/info/warning/error/critical(<str>) <span class="hljs-comment"># Sends passed message to the root logger.</span> <Logger> = log.getLogger(__name__) <span class="hljs-comment"># Returns a logger named after the module.</span> <Logger>.<level>(<str>) <span class="hljs-comment"># Sends the message. Same levels as above.</span> <Logger>.exception(<str>) <span class="hljs-comment"># `error()` that appends caught exception.</span> </code></pre> <div><h3 id="setup">Setup</h3><pre><code class="python language-python hljs">log.basicConfig( filename=<span class="hljs-keyword">None</span>, <span class="hljs-comment"># Prints to stderr when filename is None.</span> filemode=<span class="hljs-string">'a'</span>, <span class="hljs-comment"># Use mode 'w' to overwrite existing file.</span> format=<span class="hljs-string">'%(levelname)s:%(name)s:%(message)s'</span>, <span class="hljs-comment"># Using '%(asctime)s' adds local datetime.</span> level=log.WARNING, <span class="hljs-comment"># Drops messages that have lower priority.</span> handlers=[log.StreamHandler(sys.stderr)] <span class="hljs-comment"># Uses FileHandler when 'filename' is set.</span> ) </code></pre></div> <pre><code class="python language-python hljs"><Formatr> = log.Formatter(<span class="hljs-string">'<format>'</span>) <span class="hljs-comment"># Formats messages using the format str.</span> <Handler> = log.FileHandler(<path>, mode=<span class="hljs-string">'a'</span>) <span class="hljs-comment"># Appends to file. Also `encoding=None`.</span> <Handler>.setFormatter(<Formatter>) <span class="hljs-comment"># Only outputs bare messages by default.</span> <Handler>.setLevel(<str/int>) <span class="hljs-comment"># Prints/saves every message by default.</span> <Logger>.addHandler(<Handler>) <span class="hljs-comment"># Loggers can have more than one handler.</span> <Logger>.setLevel(<str/int>) <span class="hljs-comment"># What's sent to its/ancestors' handlers.</span> <Logger>.propagate = <bool> <span class="hljs-comment"># Cuts off ancestors' handlers if False.</span> </code></pre> <ul> <li><strong>Parent logger can be specified by naming the child logger <code class="python hljs"><span class="hljs-string">'<parent_name>.<name>'</span></code>.</strong></li> <li><strong>Logger will inherit the level from its parent if you don't set it via the setLevel() method.</strong></li> <li><strong>Format string can contain: pathname, filename, funcName, lineno, thread and process.</strong></li> <li><strong>RotatingFileHandler rotates files according to 'maxBytes' and 'backupCount' arguments.</strong></li> <li><strong>An object with <code class="python hljs"><span class="hljs-string">'filter(<LogRecord>)'</span></code> method (or the method itself) can be added to loggers and handlers via addFilter(). Message is dropped if filter() returns a false value.</strong></li> <li><strong>Logging messages generated by libraries are passed to the root's handlers. Level of the library's logger can be set with <code class="python hljs"><span class="hljs-string">'log.getLogger("<library>").setLevel(<str>)'</span></code>.</strong></li> </ul> <div><h4 id="loggerthatwritesmessagestoafileandsendsthemtotherootshandlerthatprintswarningsorhigher">Logger that writes messages to a file and sends them to the root's handler that prints warnings or higher:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>logger = log.getLogger(<span class="hljs-string">'my_module'</span>) <span class="hljs-meta">>>> </span>handler = log.FileHandler(<span class="hljs-string">'test.log'</span>, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-meta">>>> </span>format_str = <span class="hljs-string">'%(asctime)s %(levelname)s:%(name)s:%(message)s'</span> <span class="hljs-meta">>>> </span>handler.setFormatter(log.Formatter(format_str)) <span class="hljs-meta">>>> </span>logger.addHandler(handler) <span class="hljs-meta">>>> </span>logger.setLevel(<span class="hljs-string">'DEBUG'</span>) <span class="hljs-meta">>>> </span>log.basicConfig() <span class="hljs-meta">>>> </span>stream_handler = log.root.handlers[<span class="hljs-number">0</span>] <span class="hljs-meta">>>> </span>stream_handler.setLevel(<span class="hljs-string">'WARNING'</span>) <span class="hljs-meta">>>> </span>logger.critical(<span class="hljs-string">'Missing config file.'</span>) CRITICAL:my_module:Missing config file. <span class="hljs-meta">>>> </span>print(open(<span class="hljs-string">'test.log'</span>).read()) 2023-02-07 23:21:01,430 CRITICAL:my_module:Missing config file. </code></pre></div> <div><h2 id="introspection"><a href="#introspection" name="introspection">#</a>Introspection</h2><pre><code class="python language-python hljs"><list> = dir() <span class="hljs-comment"># Local names of objects, incl. functions/classes.</span> <dict> = vars() <span class="hljs-comment"># Local names and their objects. Same as locals().</span> <dict> = globals() <span class="hljs-comment"># Global names and their objects. E.g. __builtin__.</span> </code></pre></div> <pre><code class="python language-python hljs"><list> = dir(<obj>) <span class="hljs-comment"># Names of object's attributes, including methods.</span> <dict> = vars(<obj>) <span class="hljs-comment"># Dict of writable attributes. Or <obj>.__dict__.</span> <bool> = hasattr(<obj>, <span class="hljs-string">'<name>'</span>) <span class="hljs-comment"># Checks if object possesses attr. of passed name.</span> value = getattr(<obj>, <span class="hljs-string">'<name>'</span>) <span class="hljs-comment"># Returns object's attr. or raises AttributeError.</span> setattr(<obj>, <span class="hljs-string">'<name>'</span>, value) <span class="hljs-comment"># Only works on objects with `__dict__` attribute.</span> delattr(<obj>, <span class="hljs-string">'<name>'</span>) <span class="hljs-comment"># Deletes from __dict__. Also `del <obj>.<name>`.</span> </code></pre> <div><h2 id="threading"><a href="#threading" name="threading">#</a>Threading</h2><p><strong>Threads are functions that run concurrently. Things can get messy when they share objects. <code class="python hljs"><span class="hljs-string">'$ uv init --python 3.15t'</span></code> installs interpreter that can run threads on multiple cores.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> threading <span class="hljs-keyword">as</span> th, queue <span class="hljs-keyword">as</span> qu <span class="hljs-keyword">import</span> concurrent.futures <span class="hljs-keyword">as</span> cf </code></pre></div> <div><h3 id="thread">Thread</h3><pre><code class="python language-python hljs"><Thread> = th.Thread(target=<func>) <span class="hljs-comment"># Use `args=<coll>` to set function's arguments.</span> <Thread>.start() <span class="hljs-comment"># Runs function in background. Also is_alive().</span> <Thread>.join() <span class="hljs-comment"># Waits until the function finishes executing.</span> </code></pre></div> <ul> <li><strong>Use <code class="python hljs"><span class="hljs-string">'kwargs=<dict>'</span></code> to pass keyword arguments to the function, i.e. thread.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'daemon=True'</span></code>, or the program won't be able to exit while thread is alive.</strong></li> </ul> <div><h3 id="lock">Lock</h3><pre><code class="python language-python hljs"><lock> = th.Lock/RLock() <span class="hljs-comment"># RLock can only be released by acquirer thread.</span> <lock>.acquire() <span class="hljs-comment"># Waits/blocks until the lock becomes available.</span> <lock>.release() <span class="hljs-comment"># Releases the lock so it can be acquired again.</span> </code></pre></div> <div><h4 id="or-1">Or:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">with</span> <lock>: <span class="hljs-comment"># Enters the block by calling method acquire().</span> ... <span class="hljs-comment"># Exits it by calling release(), even on error.</span> </code></pre></div> <div><h3 id="syncobjects">Sync Objects</h3><pre><code class="python language-python hljs"><Semaphr> = th.Semaphore(value=<span class="hljs-number">1</span>) <span class="hljs-comment"># A lock that can be acquired by value threads.</span> <Event> = th.Event() <span class="hljs-comment"># `<Event>.wait()` blocks until set() is called.</span> <Barrier> = th.Barrier(parties) <span class="hljs-comment"># Wait() blocks until it's called parties times.</span> </code></pre></div> <div><h3 id="queue">Queue</h3><pre><code class="python language-python hljs"><Queue> = qu.Queue(maxsize=<span class="hljs-number">0</span>) <span class="hljs-comment"># A first-in-first-out queue. It's thread safe.</span> <Queue>.put(<obj>) <span class="hljs-comment"># The call blocks until queue stops being full.</span> <Queue>.put_nowait(<obj>) <span class="hljs-comment"># Raises the qu.Full exception if queue is full.</span> <obj> = <Queue>.get() <span class="hljs-comment"># The call blocks until queue stops being empty.</span> <obj> = <Queue>.get_nowait() <span class="hljs-comment"># Raises the qu.Empty exception if it is empty.</span> </code></pre></div> <div><h3 id="threadexecutor">Thread Executor</h3><pre><code class="python language-python hljs"><Exec> = cf.ThreadPoolExecutor() <span class="hljs-comment"># Or use `with ThreadPoolExecutor() as <name>:`.</span> <iter> = <Exec>.map(<fn>, <args>, …) <span class="hljs-comment"># Multithreaded and non-lazy map(). Keeps order.</span> <Futr> = <Exec>.submit(<fn>, <arg>, …) <span class="hljs-comment"># Queues function for execution. Returns Future.</span> <Exec>.shutdown() <span class="hljs-comment"># Waits until all submitted tasks are completed.</span> </code></pre></div> <pre><code class="python language-python hljs"><iter> = cf.as_completed(<Futrs>) <span class="hljs-comment"># `next(<iter>)` returns next completed Future.</span> <obj> = <Future>.result() <span class="hljs-comment"># Raises TimeoutError if `timeout=<fl>` is used.</span> <bool> = <Future>.done() <span class="hljs-comment"># Returns True if function has finished running.</span> <bool> = <Future>.cancel() <span class="hljs-comment"># Just returns False if func is already running.</span> </code></pre> <ul> <li><strong>Map() and as_completed() also accept 'timeout' arg. It causes <em>futures.TimeoutError</em> when next() is called or blocking. Map() times from original call and as_completed() from first call to next(). As_completed() fails if next() is called too late, even if all tasks are done.</strong></li> <li><strong>Exceptions that happen inside threads are raised when map's next() or Future's result() method is called. Future's exception() method returns caught exception object or None.</strong></li> <li><strong>ProcessPoolExecutor provides true parallelism but: everything sent to and from workers must be <a href="#pickle">pickable</a>, queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via <code class="python hljs"><span class="hljs-string">'if __name__ == "__main__": …'</span></code>.</strong></li> </ul> <div><h2 id="asyncio"><a href="#asyncio" name="asyncio">#</a>Asyncio</h2><ul> <li><strong>Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t consume as much memory.</strong></li> <li><strong>Coroutine definition starts with <code class="python hljs"><span class="hljs-string">'async'</span></code> keyword and its call with <code class="python hljs"><span class="hljs-string">'await'</span></code> keyword.</strong></li> <li><strong>Execute <code class="python hljs"><span class="hljs-string">'asyncio.run(<coroutine>)'</span></code> to start running the first/main coroutine.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> asyncio <span class="hljs-keyword">as</span> ac </code></pre></div> <pre><code class="python language-python hljs"><coro> = <async_function>(<args>) <span class="hljs-comment"># Creates a coroutine by calling async func.</span> <obj> = <span class="hljs-keyword">await</span> <coroutine> <span class="hljs-comment"># Starts coroutine. Returns result or None.</span> <task> = ac.create_task(<coroutine>) <span class="hljs-comment"># Schedules coroutine. Always keep the task.</span> <obj> = <span class="hljs-keyword">await</span> <task> <span class="hljs-comment"># Returns the result. Also <task>.cancel().</span> </code></pre> <pre><code class="python language-python hljs"><coro> = ac.gather(<coro/task>, ...) <span class="hljs-comment"># Schedules coros. Returns list of results.</span> <iter> = ac.as_completed(<coros/tasks>) <span class="hljs-comment"># `await next(<iter>)` returns next result.</span> <coro> = ac.wait(<tasks>) <span class="hljs-comment"># Accepts `return_when=ac.FIRST_COMPLETED`.</span> </code></pre> <div><h4 id="runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">Runs a terminal game where you control an asterisk that must avoid numbers:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> asyncio <span class="hljs-keyword">as</span> ac, collections <span class="hljs-keyword">as</span> co, curses, curses.textpad, enum, random P = co.namedtuple(<span class="hljs-string">'P'</span>, <span class="hljs-string">'x y'</span>) <span class="hljs-comment"># Position (x and y coordinates).</span> D = enum.Enum(<span class="hljs-string">'D'</span>, <span class="hljs-string">'n e s w'</span>) <span class="hljs-comment"># Direction (north, east, etc.).</span> W, H = <span class="hljs-number">15</span>, <span class="hljs-number">7</span> <span class="hljs-comment"># Width and height of the field.</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">(screen)</span>:</span> curses.curs_set(<span class="hljs-number">0</span>) <span class="hljs-comment"># Makes the cursor invisible.</span> screen.nodelay(<span class="hljs-keyword">True</span>) <span class="hljs-comment"># Makes getch() non-blocking.</span> ac.run(main_coroutine(screen)) <span class="hljs-comment"># Starts running asyncio code.</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main_coroutine</span><span class="hljs-params">(scr)</span>:</span> moves = ac.Queue() state = {<span class="hljs-string">'*'</span>: P(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)} | dict.fromkeys(range(<span class="hljs-number">10</span>), P(W//<span class="hljs-number">2</span>, H//<span class="hljs-number">2</span>)) ai = [random_controller(id_, moves) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)] mvc = [controller(scr, moves), model(moves, state), view(state, scr)] tasks = [ac.create_task(coro) <span class="hljs-keyword">for</span> coro <span class="hljs-keyword">in</span> ai + mvc] <span class="hljs-keyword">await</span> ac.wait(tasks, return_when=ac.FIRST_COMPLETED) <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">random_controller</span><span class="hljs-params">(id_, moves)</span>:</span> <span class="hljs-keyword">while</span> <span class="hljs-keyword">True</span>: d = random.choice(list(D)) moves.put_nowait((id_, d)) <span class="hljs-keyword">await</span> ac.sleep(random.triangular(<span class="hljs-number">0.01</span>, <span class="hljs-number">0.65</span>)) <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">controller</span><span class="hljs-params">(scr, moves)</span>:</span> <span class="hljs-keyword">while</span> <span class="hljs-keyword">True</span>: key_mappings = {<span class="hljs-number">258</span>: D.s, <span class="hljs-number">259</span>: D.n, <span class="hljs-number">260</span>: D.w, <span class="hljs-number">261</span>: D.e} <span class="hljs-keyword">if</span> d := key_mappings.get(scr.getch()): moves.put_nowait((<span class="hljs-string">'*'</span>, d)) <span class="hljs-keyword">await</span> ac.sleep(<span class="hljs-number">0.005</span>) <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">model</span><span class="hljs-params">(moves, state)</span>:</span> <span class="hljs-keyword">while</span> state[<span class="hljs-string">'*'</span>] <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> (state[id_] <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)): id_, d = <span class="hljs-keyword">await</span> moves.get() dx, dy = (d == D.e) - (d == D.w), (d == D.s) - (d == D.n) state[id_] = P((state[id_].x + dx) % W, (state[id_].y + dy) % H) <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">view</span><span class="hljs-params">(state, scr)</span>:</span> x, y = curses.COLS//<span class="hljs-number">2</span> - W//<span class="hljs-number">2</span>, curses.LINES//<span class="hljs-number">2</span> - H//<span class="hljs-number">2</span> <span class="hljs-keyword">while</span> <span class="hljs-keyword">True</span>: scr.erase() curses.textpad.rectangle(scr, y-<span class="hljs-number">1</span>, x-<span class="hljs-number">1</span>, y+H, x+W) <span class="hljs-keyword">for</span> id_, p <span class="hljs-keyword">in</span> state.items(): dx, dy = p.x - state[<span class="hljs-string">'*'</span>].x + W//<span class="hljs-number">2</span>, p.y - state[<span class="hljs-string">'*'</span>].y + H//<span class="hljs-number">2</span> scr.addstr(y + (dy % H), x + (dx % W), str(id_)) scr.refresh() <span class="hljs-keyword">await</span> ac.sleep(<span class="hljs-number">0.005</span>) <span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>: curses.wrapper(main) </code></pre></div> <p><br></p> <div><h1 id="libraries" style="font-size: 64px;">Libraries</h1><div><h2 id="progressbar"><a href="#progressbar" name="progressbar">#</a>Progress Bar</h2><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install tqdm</span> <span class="hljs-meta">>>> </span><span class="hljs-keyword">import</span> tqdm, time <span class="hljs-meta">>>> </span><span class="hljs-keyword">for</span> el <span class="hljs-keyword">in</span> tqdm.tqdm([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], desc=<span class="hljs-string">'Processing'</span>): <span class="hljs-meta">... </span> time.sleep(<span class="hljs-number">1</span>) Processing: 100%|████████████████████| 3/3 [00:03<00:00, 1.00s/it] </code></pre></div></div> <div><h2 id="plot"><a href="#plot" name="plot">#</a>Plot</h2><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install matplotlib</span> <span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt plt.plot/bar/scatter(x_data, y_data, label=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Accepts plt.plot(y_data).</span> plt.legend() <span class="hljs-comment"># Adds a legend of labels.</span> plt.title/xlabel/ylabel(<str>) <span class="hljs-comment"># Adds title or axis label.</span> plt.show() <span class="hljs-comment"># Also plt.savefig(<path>).</span> plt.clf() <span class="hljs-comment"># Clears the plot (figure).</span> </code></pre></div> <div><h2 id="table"><a href="#table" name="table">#</a>Table</h2><div><h4 id="printsacsvspreadsheettotheconsole">Prints a CSV spreadsheet to the console:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install tabulate</span> <span class="hljs-keyword">import</span> csv, tabulate <span class="hljs-keyword">with</span> open(<span class="hljs-string">'test.csv'</span>, encoding=<span class="hljs-string">'utf-8'</span>, newline=<span class="hljs-string">''</span>) <span class="hljs-keyword">as</span> file: rows = list(csv.reader(file)) print(tabulate.tabulate(rows, headers=<span class="hljs-string">'firstrow'</span>)) </code></pre></div></div> <div><h2 id="consoleapp"><a href="#consoleapp" name="consoleapp">#</a>Console App</h2><div><h4 id="runsabasicfileexplorerintheconsole">Runs a basic file explorer in the console:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install windows-curses</span> <span class="hljs-keyword">import</span> curses, os <span class="hljs-keyword">from</span> curses <span class="hljs-keyword">import</span> A_REVERSE, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">(screen)</span>:</span> ch, first, selected, paths = <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, os.listdir() <span class="hljs-keyword">while</span> ch != ord(<span class="hljs-string">'q'</span>): height, width = screen.getmaxyx() screen.erase() <span class="hljs-keyword">for</span> y, filename <span class="hljs-keyword">in</span> enumerate(paths[first : first+height]): color = A_REVERSE <span class="hljs-keyword">if</span> filename == paths[selected] <span class="hljs-keyword">else</span> <span class="hljs-number">0</span> screen.addnstr(y, <span class="hljs-number">0</span>, filename, width-<span class="hljs-number">1</span>, color) ch = screen.getch() selected -= (ch == KEY_UP) <span class="hljs-keyword">and</span> (selected > <span class="hljs-number">0</span>) selected += (ch == KEY_DOWN) <span class="hljs-keyword">and</span> (selected < len(paths)-<span class="hljs-number">1</span>) first -= (first > selected) first += (first < selected-(height-<span class="hljs-number">1</span>)) <span class="hljs-keyword">if</span> ch <span class="hljs-keyword">in</span> [KEY_LEFT, KEY_RIGHT, ord(<span class="hljs-string">'\n'</span>)]: new_dir = <span class="hljs-string">'..'</span> <span class="hljs-keyword">if</span> ch == KEY_LEFT <span class="hljs-keyword">else</span> paths[selected] <span class="hljs-keyword">if</span> os.path.isdir(new_dir): os.chdir(new_dir) first, selected, paths = <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, os.listdir() <span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>: curses.wrapper(main) </code></pre></div></div> <div><h2 id="guiapp"><a href="#guiapp" name="guiapp">#</a>GUI App</h2><div><h4 id="runsadesktopappforconvertingmetricweightsintopounds">Runs a desktop app for converting metric weights into pounds:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install FreeSimpleGUI</span> <span class="hljs-keyword">import</span> FreeSimpleGUI <span class="hljs-keyword">as</span> sg field = sg.Input(default_text=<span class="hljs-string">'100'</span>, enable_events=<span class="hljs-keyword">True</span>, key=<span class="hljs-string">'QUANTITY'</span>) menu = sg.Drop([<span class="hljs-string">'g'</span>, <span class="hljs-string">'kg'</span>, <span class="hljs-string">'t'</span>], <span class="hljs-string">'kg'</span>, readonly=<span class="hljs-keyword">True</span>, enable_events=<span class="hljs-keyword">True</span>, k=<span class="hljs-string">'UNIT'</span>) text = sg.Text(<span class="hljs-string">'is 220.462 lbs.'</span>, key=<span class="hljs-string">'RESULT'</span>) win = sg.Window(<span class="hljs-string">'GUI App'</span>, [[field, menu], [text], [sg.Button(<span class="hljs-string">'Close'</span>)]]) <span class="hljs-keyword">while</span> <span class="hljs-keyword">True</span>: event, values = win.read() <span class="hljs-keyword">if</span> event <span class="hljs-keyword">in</span> [sg.WIN_CLOSED, <span class="hljs-string">'Close'</span>]: <span class="hljs-keyword">break</span> <span class="hljs-keyword">try</span>: quantity = float(values[<span class="hljs-string">'QUANTITY'</span>]) <span class="hljs-keyword">except</span> ValueError: <span class="hljs-keyword">continue</span> unit = values[<span class="hljs-string">'UNIT'</span>] lbs = quantity * {<span class="hljs-string">'g'</span>: <span class="hljs-number">0.001</span>, <span class="hljs-string">'kg'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'t'</span>: <span class="hljs-number">1000</span>}[unit] / <span class="hljs-number">0.45359237</span> win[<span class="hljs-string">'RESULT'</span>].update(value=<span class="hljs-string">f'is <span class="hljs-subst">{lbs:g}</span> lbs.'</span>) win.close() </code></pre></div></div> <div><h2 id="scraping"><a href="#scraping" name="scraping">#</a>Scraping</h2><div><h4 id="scrapespythonsurlandlogofromitswikipediapage">Scrapes Python's URL and logo from its Wikipedia page:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install requests beautifulsoup4</span> <span class="hljs-keyword">import</span> requests, bs4, os get = <span class="hljs-keyword">lambda</span> url: requests.get(url, headers={<span class="hljs-string">'User-Agent'</span>: <span class="hljs-string">'cpc-bot'</span>}) response = get(<span class="hljs-string">'https://en.wikipedia.org/wiki/Python_(programming_language)'</span>) document = bs4.BeautifulSoup(response.text, <span class="hljs-string">'html.parser'</span>) table = document.find(<span class="hljs-string">'table'</span>, class_=<span class="hljs-string">'infobox vevent'</span>) python_url = table.find(<span class="hljs-string">'th'</span>, string=<span class="hljs-string">'Website'</span>).next_sibling.a[<span class="hljs-string">'href'</span>] logo_url = table.find(<span class="hljs-string">'img'</span>)[<span class="hljs-string">'src'</span>] filename = os.path.basename(logo_url) <span class="hljs-keyword">with</span> open(filename, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> file: file.write(get(<span class="hljs-string">f'https:<span class="hljs-subst">{logo_url}</span>'</span>).content) print(<span class="hljs-string">f'URL: <span class="hljs-subst">{python_url}</span>, logo: file://<span class="hljs-subst">{os.path.abspath(filename)}</span>'</span>) </code></pre></div></div> <div><h3 id="selenium">Selenium</h3><p><strong>Library for scraping websites with dynamic content.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install selenium</span> <span class="hljs-keyword">from</span> selenium <span class="hljs-keyword">import</span> webdriver </code></pre></div> <pre><code class="python language-python hljs"><Drv> = webdriver.Chrome/Firefox/Safari() <span class="hljs-comment"># Opens the browser. Also `<Driver>.quit()`.</span> <Drv>.implicitly_wait(seconds) <span class="hljs-comment"># Sets timeout for find_element/s() methods.</span> <Drv>.get(<span class="hljs-string">'<url>'</span>) <span class="hljs-comment"># Blocks until browser fires the load event.</span> <str> = <Drv>.page_source <span class="hljs-comment"># Returns HTML of the page's current state.</span> <El> = <Drv/El>.find_element(<span class="hljs-string">'xpath'</span>, <str>) <span class="hljs-comment"># Accepts '//<tag>[@<attr_name>="<val>"]…'.</span> <str> = <El>.get_attribute(<span class="hljs-string">'<name>'</span>) <span class="hljs-comment"># Returns attribute or a property if exists.</span> <El>.click/clear() <span class="hljs-comment"># Also <El>.text and <El>.send_keys(<str>).</span> </code></pre> <div><h4 id="xpathavailableinbrowsersconsoleviadxxpath">XPath — available in browser's console via <code class="python hljs"><span class="hljs-string">'$x("<xpath>")'</span></code>:</h4><pre><code class="python language-python hljs"><xpath> = //<element>[/ <span class="hljs-keyword">or</span> // <element>] <span class="hljs-comment"># E.g. …/child, …//descendant, …/../sibling.</span> <xpath> = //<el>/following-sibling::<el> <span class="hljs-comment"># Looks under first element. Also parent::.</span> <element> = <tag><conditions><index> <span class="hljs-comment"># Tag accepts */a/…. Use [1/2/…] for index.</span> <condit.> = [<sub_con> [<span class="hljs-keyword">and</span>/<span class="hljs-keyword">or</span> <sub_con>]] <span class="hljs-comment"># Use not(<sub_con>) to negate subcondition.</span> <sub_con> = @<attr>[=<span class="hljs-string">"<val>"</span>] <span class="hljs-comment"># `text()=` and `.=` match (complete) text.</span> <sub_con> = contains(@<attr>, <span class="hljs-string">"<val>"</span>) <span class="hljs-comment"># Is <val> a substring of attribute's value?</span> <sub_con> = <element> <span class="hljs-comment"># Has matching child? Descendant if //<el>.</span> </code></pre></div> <div><h2 id="webapp"><a href="#webapp" name="webapp">#</a>Web App</h2><p><strong>Flask is a micro web framework that also includes a simple WSGI/HTTP server. If you just want to open a HTML file in a web browser use <code class="python hljs"><span class="hljs-string">'webbrowser.open(<path>)'</span></code> instead.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install flask</span> <span class="hljs-keyword">import</span> flask <span class="hljs-keyword">as</span> fl </code></pre></div> <pre><code class="python language-python hljs">app = fl.Flask(__name__) <span class="hljs-comment"># Returns app object. Put at the top.</span> app.run(host=<span class="hljs-keyword">None</span>, port=<span class="hljs-keyword">None</span>, debug=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Or `$ flask --app FILE run --ARG=…`.</span> </code></pre> <ul> <li><strong>Starts the app at <code class="python hljs"><span class="hljs-string">'http://localhost:5000'</span></code>. Use <code class="python hljs"><span class="hljs-string">'host="0.0.0.0"'</span></code> to run externally.</strong></li> <li><strong>Install a <a href="https://en.wikipedia.org/wiki/Web_Server_Gateway_Interface">WSGI</a> server like <a href="https://flask.palletsprojects.com/en/latest/deploying/waitress/">Waitress</a> and a HTTP server such as <a href="https://flask.palletsprojects.com/en/latest/deploying/nginx/">Nginx</a> to get better security.</strong></li> <li><strong>Debug mode restarts the app whenever script changes and displays errors in the browser.</strong></li> </ul> <div><h3 id="servingfiles">Serving Files</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/img/<path:filename>')</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">serve_file</span><span class="hljs-params">(filename)</span>:</span> <span class="hljs-keyword">return</span> fl.send_from_directory(<span class="hljs-string">'DIRNAME'</span>, filename) </code></pre></div> <div><h3 id="servinghtml">Serving HTML</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/<sport>')</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">serve_html</span><span class="hljs-params">(sport)</span>:</span> <span class="hljs-keyword">return</span> fl.render_template_string(<span class="hljs-string">'<h1>{{t}}</h1>'</span>, t=sport) </code></pre></div> <ul> <li><strong><code class="python hljs"><span class="hljs-string">'fl.render_template(filename, <kwargs>)'</span></code> renders a file located in 'templates' dir.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'fl.abort(<int>)'</span></code> returns error code and <code class="python hljs"><span class="hljs-string">'return fl.redirect(<url>)'</span></code> redirects.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'fl.request.args[<str>]'</span></code> returns parameter from query string (URL part right of '?').</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'fl.session[<str>] = <obj>'</span></code> stores session data and <code class="python hljs"><span class="hljs-string">'fl.session.clear()'</span></code> clears it. A session cookie key needs to be set at the startup with <code class="python hljs"><span class="hljs-string">'app.secret_key = <str>'</span></code>.</strong></li> </ul> <div><h3 id="servingjson">Serving JSON</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.post('/<sport>/odds')</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">serve_json</span><span class="hljs-params">(sport)</span>:</span> team = fl.request.form[<span class="hljs-string">'team'</span>] <span class="hljs-keyword">return</span> {<span class="hljs-string">'team'</span>: team, <span class="hljs-string">'odds'</span>: [<span class="hljs-number">2.09</span>, <span class="hljs-number">3.74</span>, <span class="hljs-number">3.68</span>]} </code></pre></div> <div><h4 id="startstheappinitsownthreadandqueriesitsrestapi">Starts the app in its own thread and queries its REST API:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install requests</span> <span class="hljs-meta">>>> </span><span class="hljs-keyword">import</span> threading, requests <span class="hljs-meta">>>> </span>threading.Thread(target=app.run, daemon=<span class="hljs-keyword">True</span>).start() <span class="hljs-meta">>>> </span>url = <span class="hljs-string">'http://localhost:5000/football/odds'</span> <span class="hljs-meta">>>> </span>resp = requests.post(url, data={<span class="hljs-string">'team'</span>: <span class="hljs-string">'Arsenal FC'</span>}) <span class="hljs-meta">>>> </span>resp.json() {<span class="hljs-string">'team'</span>: <span class="hljs-string">'Arsenal FC'</span>, <span class="hljs-string">'odds'</span>: [<span class="hljs-number">2.09</span>, <span class="hljs-number">3.74</span>, <span class="hljs-number">3.68</span>]} </code></pre></div> <div><h2 id="profiling"><a href="#profiling" name="profiling">#</a>Profiling</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> time <span class="hljs-keyword">import</span> perf_counter start_time = perf_counter() ... seconds = perf_counter() - start_time </code></pre></div> <div><h3 id="timingasnippet">Timing a Snippet</h3><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> timeit <span class="hljs-keyword">import</span> timeit <span class="hljs-meta">>>> </span>timeit(<span class="hljs-string">'list(range(10_000))'</span>, number=<span class="hljs-number">1000</span>, globals=globals()) <span class="hljs-number">0.19373</span> </code></pre></div> <div><h3 id="profilingbyline">Profiling by Line</h3><pre><code class="text language-text">$ pip3 install line_profiler $ echo '@profile def main(): a = list(range(10_000)) b = set(range(10_000)) main()' > test.py $ kernprof -lv test.py Line # Hits Time Per Hit % Time Line Contents ============================================================== 1 @profile 2 def main(): 3 1 253.4 253.4 32.2 a = list(range(10_000)) 4 1 534.1 534.1 67.8 b = set(range(10_000)) </code></pre></div> <div><h3 id="visualizations">Visualizations</h3><pre><code class="bash language-bash hljs">$ apt install graphviz && pip3 install gprof2dot snakeviz <span class="hljs-comment"># Or install graphviz.exe.</span> $ tail -n +2 test.py > test.tmp && mv test.tmp test.py <span class="hljs-comment"># Removes the first line.</span> $ python3 -m cProfile -o test.prof test.py <span class="hljs-comment"># Runs a tracing profiler.</span> $ gprof2dot -f pstats test.prof | dot -T png -o test.png <span class="hljs-comment"># Generates a call graph.</span> $ xdg-open test.png <span class="hljs-comment"># Displays the call graph.</span> $ snakeviz test.prof <span class="hljs-comment"># Displays a flame graph.</span> </code></pre></div> <div><h3 id="samplingprofilers">Sampling Profilers</h3><pre><code class="text language-text">┏━━━━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━┯━━━━━━┓ ┃ pip3 install │ Profiles │ How to run │ Lines │ Live ┃ ┠──────────────┼───────────┼───────────────────────────────┼───────┼──────┨ ┃ pyinstrument │ CPU │ pyinstrument test.py │ × │ × ┃ ┃ py-spy │ CPU │ py-spy top -- python3 test.py │ × │ ✓ ┃ ┃ scalene │ CPU & RAM │ scalene test.py │ ✓ │ × ┃ ┃ memray │ RAM │ memray run --live test.py │ ✓ │ ✓ ┃ ┗━━━━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━┷━━━━━━┛ </code></pre></div> <div><h2 id="numpy"><a href="#numpy" name="numpy">#</a>NumPy</h2><p><strong>Array manipulation library. Can run hundred times faster than equivalent Python code.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install numpy</span> <span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np </code></pre></div> <pre><code class="python language-python hljs"><array> = np.array(<list/list_of_lists/…>) <span class="hljs-comment"># NumPy array. Accepts `dtype=np.int64`.</span> <array> = np.load(<path/file>) <span class="hljs-comment"># Save array with np.save(<path>, <arr>).</span> </code></pre> <pre><code class="python language-python hljs"><array> = np.zeros/ones/empty(shape) <span class="hljs-comment"># Pass a tuple of ints (dimension sizes).</span> <array> = np.arange(from, to_exc, ±step) <span class="hljs-comment"># Also np.linspace(start, stop, length).</span> <array> = np.random.randint(from, to_exc, shape) <span class="hljs-comment"># Also random.uniform(low, high, shape).</span> </code></pre> <pre><code class="python language-python hljs"><view> = <array>.reshape(shape) <span class="hljs-comment"># Also `<array>.shape = (<int>, [...])`.</span> <array> = <array>.flatten() <span class="hljs-comment"># Returns 1d copy. Also <array>.ravel().</span> </code></pre> <pre><code class="python language-python hljs"><array> = np.abs/sqrt/log/copy(<array>) <span class="hljs-comment"># Returns a new array of the same shape.</span> <array> = <array>.sum/max/mean/argmax(axis) <span class="hljs-comment"># Aggregates dimension with passed index.</span> <array> = np.apply_along_axis(<func>, axis, <arr>) <span class="hljs-comment"># Func. can return a scalar or an array.</span> </code></pre> <pre><code class="python language-python hljs"><array> = np.concat(<arrays>, axis=<span class="hljs-number">0</span>) <span class="hljs-comment"># Links arrays along first axis (rows).</span> <array> = np.vstack/column_stack(<arrays>) <span class="hljs-comment"># A 1d array is treated as a row/column.</span> <array> = np.tile/repeat(<arr>, <int/s> [, axis]) <span class="hljs-comment"># Tiles whole array or repeats elements.</span> </code></pre> <ul> <li><strong>Shape is a tuple of dimension sizes. A 100x50 RGB image has shape (50, 100, 3).</strong></li> <li><strong>Axis is an index of a dimension. Leftmost dimension has index 0. Summing the RGB image along axis 2 will return a greyscale image with shape (50, 100).</strong></li> </ul> <div><h3 id="indexing">Indexing</h3><pre><code class="bash hljs"><object> = <2d>[row_index, col_index] <span class="hljs-comment"># Or <3d>[<int>, <int>, <int>].</span> <1d_view> = <2d>[row_index] <span class="hljs-comment"># Or <3d>[<int>, <int>, <slice>].</span> <1d_view> = <2d>[:, col_index] <span class="hljs-comment"># Or <3d>[<int>, <slice>, <int>].</span> <2d_view> = <2d>[row_i:to_exc, col_i:to_exc] <span class="hljs-comment"># Or <3d>[<int>, <slice>, <slice>].</span> </code></pre></div> <pre><code class="bash hljs"><1d_array> = <2d>[row_indices, col_indices] <span class="hljs-comment"># Or <3d>[<int/1d>, <1d>, <1d>].</span> <2d_array> = <2d>[row_indices] <span class="hljs-comment"># Or <3d>[<int/1d>, <1d>, <slice>].</span> <2d_array> = <2d>[:, col_indices] <span class="hljs-comment"># Or <3d>[<int/1d>, <slice>, <1d>].</span> <2d_array> = <2d>[np.ix_(row_is, col_is)] <span class="hljs-comment"># Or <3d>[<int/1d/2d>, <2d>, <2d>].</span> </code></pre> <pre><code class="bash hljs"><2d_bools> = <2d> > <el/1d/2d> <span class="hljs-comment"># A 1d object must be size of row.</span> <1/2d_arr> = <2d>[<2d/1d_bools>] <span class="hljs-comment"># A 1d object must be size of col.</span> </code></pre> <ul> <li><strong><code class="python hljs"><span class="hljs-string">':'</span></code> returns a slice of all dimension's indices. If dimension is omitted, it defaults to <code class="python hljs"><span class="hljs-string">':'</span></code>.</strong></li> <li><strong>Passing two slices (line 4) works the same as when a slice and 1d array are passed (line 7).</strong></li> <li><strong>Python converts <code class="python hljs"><span class="hljs-string">'obj[i, j]'</span></code> to <code class="python hljs"><span class="hljs-string">'obj[(i, j)]'</span></code>. This makes <code class="python hljs"><span class="hljs-string">'<2d>[row_i, col_i]'</span></code> and <code class="python hljs"><span class="hljs-string">'<2d>[row_indices]'</span></code> indistinguishable to NumPy if tuple of two indices is passed.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'ix_([1, 2], [3, 4])'</span></code> returns <code class="python hljs"><span class="hljs-string">'[[1], [2]]'</span></code> and <code class="python hljs"><span class="hljs-string">'[[3, 4]]'</span></code>. Due to broadcasting rules, this is the same as indexing via <code class="python hljs"><span class="hljs-string">'[[1, 1], [2, 2]]'</span></code> and <code class="python hljs"><span class="hljs-string">'[[3, 4], [3, 4]]'</span></code>.</strong></li> <li><strong>Any value that is broadcastable to the indexed shape can be assigned to the selection.</strong></li> </ul> <div><h3 id="broadcasting">Broadcasting</h3><p><strong>Array reshaping procedure used by arithmetic operations, etc.</strong></p><pre><code class="python language-python hljs">array_a = np.array([<span class="hljs-number">0.1</span>, <span class="hljs-number">0.6</span>, <span class="hljs-number">0.8</span>]) <span class="hljs-comment"># I.e. `array_a.shape == (3,)`.</span> array_b = np.array([[<span class="hljs-number">0.1</span>], [<span class="hljs-number">0.6</span>], [<span class="hljs-number">0.8</span>]]) <span class="hljs-comment"># I.e. `array_b.shape == (3, 1)`.</span> </code></pre></div> <div><h4 id="1ifarrayshapesdifferinlengthleftpadtheshortershapewithones">1. If array shapes differ in length, left-pad the shorter shape with ones:</h4><pre><code class="python language-python hljs">array_a = np.array([[<span class="hljs-number">0.1</span>, <span class="hljs-number">0.6</span>, <span class="hljs-number">0.8</span>]]) <span class="hljs-comment"># I.e. `array_a.shape == (1, 3)`.</span> array_b = np.array([[<span class="hljs-number">0.1</span>], [<span class="hljs-number">0.6</span>], [<span class="hljs-number">0.8</span>]]) <span class="hljs-comment"># I.e. `array_b.shape == (3, 1)`.</span> </code></pre></div> <div><h4 id="2expanddimensionswithsize1byduplicatingtheirelementsarrays">2. Expand dimensions with size 1 by duplicating their elements/arrays:</h4><pre><code class="python language-python hljs">array_a = np.array([[<span class="hljs-number">0.1</span>, <span class="hljs-number">0.6</span>, <span class="hljs-number">0.8</span>], <span class="hljs-comment"># I.e. `array_a.shape == (3, 3)`.</span> [<span class="hljs-number">0.1</span>, <span class="hljs-number">0.6</span>, <span class="hljs-number">0.8</span>], [<span class="hljs-number">0.1</span>, <span class="hljs-number">0.6</span>, <span class="hljs-number">0.8</span>]]) array_b = np.array([[<span class="hljs-number">0.1</span>, <span class="hljs-number">0.1</span>, <span class="hljs-number">0.1</span>], <span class="hljs-comment"># I.e. `array_b.shape == (3, 3)`.</span> [<span class="hljs-number">0.6</span>, <span class="hljs-number">0.6</span>, <span class="hljs-number">0.6</span>], [<span class="hljs-number">0.8</span>, <span class="hljs-number">0.8</span>, <span class="hljs-number">0.8</span>]]) </code></pre></div> <div><h3 id="example-3">Example</h3><div><h4 id="foreachpointreturnsindexofitsnearestpoint010608121">For each point returns index of its nearest point (<code class="python hljs">[<span class="hljs-number">0.1</span>, <span class="hljs-number">0.6</span>, <span class="hljs-number">0.8</span>] => [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span>]</code>):</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>print(points := np.array([<span class="hljs-number">0.1</span>, <span class="hljs-number">0.6</span>, <span class="hljs-number">0.8</span>])) [<span class="hljs-number">0.1</span> <span class="hljs-number">0.6</span> <span class="hljs-number">0.8</span>] <span class="hljs-meta">>>> </span>print(wrapped_points := points.reshape(<span class="hljs-number">3</span>, <span class="hljs-number">1</span>)) [[<span class="hljs-number">0.1</span>] [<span class="hljs-number">0.6</span>] [<span class="hljs-number">0.8</span>]] <span class="hljs-meta">>>> </span>print(deltas := points - wrapped_points) [[ <span class="hljs-number">0.</span> <span class="hljs-number">0.5</span> <span class="hljs-number">0.7</span>] [<span class="hljs-number">-0.5</span> <span class="hljs-number">0.</span> <span class="hljs-number">0.2</span>] [<span class="hljs-number">-0.7</span> <span class="hljs-number">-0.2</span> <span class="hljs-number">0.</span> ]] <span class="hljs-meta">>>> </span>deltas[range(<span class="hljs-number">3</span>), range(<span class="hljs-number">3</span>)] = np.inf <span class="hljs-meta">>>> </span>print(distances := np.abs(deltas)) [[inf <span class="hljs-number">0.5</span> <span class="hljs-number">0.7</span>] [<span class="hljs-number">0.5</span> inf <span class="hljs-number">0.2</span>] [<span class="hljs-number">0.7</span> <span class="hljs-number">0.2</span> inf]] <span class="hljs-meta">>>> </span>print(distances.argmin(axis=<span class="hljs-number">1</span>)) [<span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">1</span>] </code></pre></div></div> <div><h2 id="image"><a href="#image" name="image">#</a>Image</h2><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pillow</span> <span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image </code></pre></div> <pre><code class="python language-python hljs"><Image> = Image.new(<span class="hljs-string">'RGB'</span>, (width, heig)) <span class="hljs-comment"># Creates an image. Also `color=<tuple_of_ints>`.</span> <Image> = Image.open(<path>) <span class="hljs-comment"># Identifies format based on the file's contents.</span> <Image> = <Image>.convert(<span class="hljs-string">'<mode>'</span>) <span class="hljs-comment"># Converts the image to the new mode (see Modes).</span> <Image>.save(<path>) <span class="hljs-comment"># Also `quality=<int>` if extension is jpg/jpeg.</span> <Image>.show() <span class="hljs-comment"># Displays image in system's default preview app.</span> </code></pre> <pre><code class="python language-python hljs"><int/tup> = <Image>.getpixel((x, y)) <span class="hljs-comment"># Returns the pixel's value, that is, its color.</span> <ImgCore> = <Image>.getdata() <span class="hljs-comment"># Returns a flattened view of the pixel values.</span> <Image>.putpixel((x, y), <int/tuple>) <span class="hljs-comment"># Updates pixel's value. Clips passed integer/s.</span> <Image>.putdata(<list/ImgCore>) <span class="hljs-comment"># Updates pixels with a copy of passed sequence.</span> <Image>.paste(<Image>, (x, y)) <span class="hljs-comment"># Draws passed image at the specified location.</span> </code></pre> <pre><code class="python language-python hljs"><Image> = <Image>.filter(<Filter>) <span class="hljs-comment"># Accepts ImageFilter.BLUR/SHARPEN/FIND_EDGES/….</span> <Image> = <Enhance>.enhance(<float>) <span class="hljs-comment"># E.g. `ImageEnhance.Contrast/Color/…(<Image>)`.</span> </code></pre> <pre><code class="python language-python hljs"><array> = numpy.array(<Image>) <span class="hljs-comment"># Creates a 2d or 3d NumPy array from the image.</span> <Image> = Image.fromarray(<array>) <span class="hljs-comment"># Clip values with np.uint8(<arr>.clip(0, 255)).</span> </code></pre> <div><h3 id="modes-1">Modes</h3><ul> <li><strong><code class="python hljs"><span class="hljs-string">'L'</span></code> - Lightness (greyscale image). Each pixel is stored as an int between 0 and 255.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'RGB'</span></code> - Red, green, blue (true color image). Each pixel is a tuple of three integers.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'RGBA'</span></code> - RGB with alpha. Low alpha (i.e. fourth int) makes pixel more transparent.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'HSV'</span></code> - Hue, saturation, value. Three ints representing color in HSV color space.</strong></li> </ul><div><h3 id="examples">Examples</h3><div><h4 id="createsapngimageofarainbowgradient">Creates a PNG image of a rainbow gradient:</h4><pre><code class="python language-python hljs">W, H = <span class="hljs-number">100</span>, <span class="hljs-number">100</span> n_pixels = W * H hues = (<span class="hljs-number">255</span> * i/n_pixels <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(n_pixels)) img = Image.new(<span class="hljs-string">'HSV'</span>, (W, H)) img.putdata([(int(h), <span class="hljs-number">255</span>, <span class="hljs-number">255</span>) <span class="hljs-keyword">for</span> h <span class="hljs-keyword">in</span> hues]) img.convert(<span class="hljs-string">'RGB'</span>).save(<span class="hljs-string">'test.png'</span>) </code></pre></div></div></div> <div><h4 id="addsnoisetothepngimageanddisplaysit">Adds noise to the PNG image and displays it:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> randint add_noise = <span class="hljs-keyword">lambda</span> i: max(<span class="hljs-number">0</span>, min(<span class="hljs-number">255</span>, i + randint(<span class="hljs-number">-20</span>, <span class="hljs-number">20</span>))) img = Image.open(<span class="hljs-string">'test.png'</span>).convert(<span class="hljs-string">'HSV'</span>) img.putdata([(add_noise(h), s, v) <span class="hljs-keyword">for</span> h, s, v <span class="hljs-keyword">in</span> img.getdata()]) img.show() </code></pre></div> <div><h3 id="imagedraw">Image Draw</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> ImageDraw <Draw> = ImageDraw.Draw(<Image>) <span class="hljs-comment"># An object for adding 2D graphics to the image.</span> <Draw>.point((x, y)) <span class="hljs-comment"># Draws a point. Accepts `fill=<int/tuple/str>`.</span> <Draw>.line((x1, y1, x2, y2 [, ...])) <span class="hljs-comment"># To get anti-aliasing use <Img>.resize((w, h)).</span> <Draw>.arc((x1, y1, x2, y2), deg1, deg2) <span class="hljs-comment"># Draws arc of an ellipse in clockwise direction.</span> <Draw>.rectangle((x1, y1, x2, y2)) <span class="hljs-comment"># Also rounded_rectangle() and regular_polygon().</span> <Draw>.polygon((x1, y1, x2, y2, ...)) <span class="hljs-comment"># The last point gets connected to the first one.</span> <Draw>.ellipse((x1, y1, x2, y2)) <span class="hljs-comment"># To rotate it use <Image>.rotate(anticlock_deg).</span> <Draw>.text((x, y), <str>) <span class="hljs-comment"># Accepts `font=ImageFont.truetype(path, size)`.</span> </code></pre></div> <ul> <li><strong>Pass <code class="python hljs"><span class="hljs-string">'fill=<color>'</span></code> to set primary color of the figure.</strong></li> <li><strong>Pass <code class="python hljs"><span class="hljs-string">'width=<int>'</span></code> to set the width of lines or contours.</strong></li> <li><strong>Pass <code class="python hljs"><span class="hljs-string">'outline=<color>'</span></code> to set the color of the contours.</strong></li> <li><strong>Color can be an int, tuple, <code class="python hljs"><span class="hljs-string">'#rrggbb[aa]'</span></code> or color name.</strong></li> </ul> <div><h2 id="animation"><a href="#animation" name="animation">#</a>Animation</h2><div><h4 id="createsagifofabouncingball">Creates a GIF of a bouncing ball:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install imageio</span> <span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image, ImageDraw <span class="hljs-keyword">import</span> imageio W, H, R = <span class="hljs-number">126</span>, <span class="hljs-number">126</span>, <span class="hljs-number">10</span> <span class="hljs-comment"># Width, Height, Radius.</span> frames = [] <span class="hljs-keyword">for</span> velocity <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, <span class="hljs-number">16</span>): y = sum(range(velocity)) frame = Image.new(<span class="hljs-string">'L'</span>, (W, H)) draw = ImageDraw.Draw(frame) draw.ellipse((W/<span class="hljs-number">2</span>-R, y, W/<span class="hljs-number">2</span>+R, y+<span class="hljs-number">2</span>*R), fill=<span class="hljs-string">'white'</span>) frames.append(frame) frames += reversed(frames[<span class="hljs-number">1</span>:<span class="hljs-number">-1</span>]) imageio.mimsave(<span class="hljs-string">'test.gif'</span>, frames, duration=<span class="hljs-number">0.03</span>) </code></pre></div></div> <div><h2 id="audio"><a href="#audio" name="audio">#</a>Audio</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> wave </code></pre></div> <pre><code class="python language-python hljs"><Wave> = wave.open(<span class="hljs-string">'<path>'</span>) <span class="hljs-comment"># Opens specified WAV file for reading.</span> <int> = <Wave>.getframerate() <span class="hljs-comment"># Returns number of frames per second.</span> <int> = <Wave>.getnchannels() <span class="hljs-comment"># Returns number of samples per frame.</span> <int> = <Wave>.getsampwidth() <span class="hljs-comment"># Returns how many bytes are in sample.</span> <tuple> = <Wave>.getparams() <span class="hljs-comment"># Returns namedtuple of all parameters.</span> <bytes> = <Wave>.readframes(<int>) <span class="hljs-comment"># Returns all frames if `-1` is passed.</span> </code></pre> <pre><code class="python language-python hljs"><Wave> = wave.open(<span class="hljs-string">'<path>'</span>, <span class="hljs-string">'wb'</span>) <span class="hljs-comment"># Creates/truncates a file for writing.</span> <Wave>.setframerate(<int>) <span class="hljs-comment"># Pass 44100, or 48000 for video track.</span> <Wave>.setnchannels(<int>) <span class="hljs-comment"># Pass 1 for mono, 2 for stereo signal.</span> <Wave>.setsampwidth(<int>) <span class="hljs-comment"># Pass 2 for CD, 3 for hi-res quality.</span> <Wave>.setparams(<tuple>) <span class="hljs-comment"># Passed tuple must contain all params.</span> <Wave>.writeframes(<bytes>) <span class="hljs-comment"># Appends passed frames to audio file.</span> </code></pre> <ul> <li><strong>The bytes object contains a sequence of frames, each consisting of one or more samples.</strong></li> <li><strong>In stereo signal, first sample of a frame belongs to the left channel (second to the right).</strong></li> <li><strong>Each sample consists of one or more bytes (depending on sample width) that, when converted to an integer, indicate the displacement of a speaker membrane at that moment.</strong></li> <li><strong>Integers should be encoded unsigned if sample width is one byte. For other sample sizes they should be encoded signed with little-endian byte order (least significant byte first).</strong></li> </ul> <div><h3 id="samplevalues">Sample Values</h3><pre><code class="python hljs">┏━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━┯━━━━━━━━━━━┓ ┃ sampwidth │ min │ zero │ max ┃ ┠───────────┼───────────┼──────┼───────────┨ ┃ <span class="hljs-number">1</span> │ <span class="hljs-number">0</span> │ <span class="hljs-number">128</span> │ <span class="hljs-number">255</span> ┃ ┃ <span class="hljs-number">2</span> │ <span class="hljs-number">-32768</span> │ <span class="hljs-number">0</span> │ <span class="hljs-number">32767</span> ┃ ┃ <span class="hljs-number">3</span> │ <span class="hljs-number">-8388608</span> │ <span class="hljs-number">0</span> │ <span class="hljs-number">8388607</span> ┃ ┗━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━┷━━━━━━━━━━━┛ </code></pre></div> <div><h3 id="readfloatsamplesfromwavfile">Read Float Samples from WAV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_wav_file</span><span class="hljs-params">(filename)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_int</span><span class="hljs-params">(bytes_obj)</span>:</span> an_int = int.from_bytes(bytes_obj, <span class="hljs-string">'little'</span>, signed=(p.sampwidth != <span class="hljs-number">1</span>)) <span class="hljs-keyword">return</span> an_int - (<span class="hljs-number">128</span> * (p.sampwidth == <span class="hljs-number">1</span>)) <span class="hljs-keyword">with</span> wave.open(filename) <span class="hljs-keyword">as</span> file: p = file.getparams() frames = file.readframes(<span class="hljs-number">-1</span>) samples_b = (frames[i : i + p.sampwidth] <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>, len(frames), p.sampwidth)) <span class="hljs-keyword">return</span> [get_int(b) / pow(<span class="hljs-number">2</span>, (p.sampwidth * <span class="hljs-number">8</span>) - <span class="hljs-number">1</span>) <span class="hljs-keyword">for</span> b <span class="hljs-keyword">in</span> samples_b], p </code></pre></div> <div><h3 id="writefloatsamplestowavfile">Write Float Samples to WAV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_wav_file</span><span class="hljs-params">(filename, samples_f, p=<span class="hljs-keyword">None</span>, nchannels=<span class="hljs-number">1</span>, sampwidth=<span class="hljs-number">2</span>, fs=<span class="hljs-number">44100</span>)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_bytes</span><span class="hljs-params">(a_float)</span>:</span> a_float = max(<span class="hljs-number">-1</span>, min(<span class="hljs-number">1</span> - <span class="hljs-number">2e-16</span>, a_float)) + (p.sampwidth == <span class="hljs-number">1</span>) a_float *= pow(<span class="hljs-number">2</span>, (p.sampwidth * <span class="hljs-number">8</span>) - <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> int(a_float).to_bytes(p.sampwidth, <span class="hljs-string">'little'</span>, signed=(p.sampwidth != <span class="hljs-number">1</span>)) <span class="hljs-keyword">if</span> p <span class="hljs-keyword">is</span> <span class="hljs-keyword">None</span>: p = wave._wave_params(nchannels, sampwidth, fs, <span class="hljs-number">0</span>, <span class="hljs-string">'NONE'</span>, <span class="hljs-string">'not compressed'</span>) <span class="hljs-keyword">with</span> wave.open(filename, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> file: file.setparams(p) file.writeframes(<span class="hljs-string">b''</span>.join(get_bytes(f) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> samples_f)) </code></pre></div> <div><h3 id="examples-1">Examples</h3><div><h4 id="savesa440hzsinewavetoamonowavfile">Saves a 440 Hz sine wave to a mono WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> sin, pi get_sin = <span class="hljs-keyword">lambda</span> i: sin(<span class="hljs-number">440</span> * pi*<span class="hljs-number">2</span> * i/<span class="hljs-number">44100</span>) * <span class="hljs-number">0.2</span> write_to_wav_file(<span class="hljs-string">'test.wav'</span>, (get_sin(i) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">100_000</span>))) </code></pre></div></div> <div><h4 id="addsnoisetothewavfile">Adds noise to the WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> uniform samples_f, prms = read_wav_file(<span class="hljs-string">'test.wav'</span>) samples_f = (f + uniform(<span class="hljs-number">-0.02</span>, <span class="hljs-number">0.02</span>) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> samples_f) write_to_wav_file(<span class="hljs-string">'test.wav'</span>, samples_f, p=prms) </code></pre></div> <div><h3 id="audioplayer">Audio Player</h3><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install nava</span> <span class="hljs-keyword">from</span> nava <span class="hljs-keyword">import</span> play play(<span class="hljs-string">'test.wav'</span>) </code></pre></div> <div><h3 id="texttospeech">Text to Speech</h3><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install piper-tts sounddevice</span> <span class="hljs-keyword">import</span> os, piper, sounddevice os.system(<span class="hljs-string">'python3 -m piper.download_voices en_US-lessac-high'</span>) voice = piper.PiperVoice.load(<span class="hljs-string">'en_US-lessac-high.onnx'</span>) <span class="hljs-keyword">for</span> sentence <span class="hljs-keyword">in</span> voice.synthesize(<span class="hljs-string">'Sally sells seashells by the seashore.'</span>): sounddevice.wait() sounddevice.play(sentence.audio_float_array, sentence.sample_rate) sounddevice.wait() </code></pre></div> <div><h2 id="synthesizer"><a href="#synthesizer" name="synthesizer">#</a>Synthesizer</h2><div><h4 id="playspopcornbygershonkingsley">Plays Popcorn by Gershon Kingsley:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install numpy sounddevice</span> <span class="hljs-keyword">import</span> itertools <span class="hljs-keyword">as</span> it, math, numpy <span class="hljs-keyword">as</span> np, sounddevice <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">play_notes</span><span class="hljs-params">(notes, bpm=<span class="hljs-number">132</span>, fs=<span class="hljs-number">44100</span>, volume=<span class="hljs-number">0.1</span>)</span>:</span> beat_len = <span class="hljs-number">60</span>/bpm * fs get_pause = <span class="hljs-keyword">lambda</span> beats: it.repeat(<span class="hljs-number">0</span>, int(beats * beat_len)) get_sinus = <span class="hljs-keyword">lambda</span> hz, i: math.sin(hz * math.pi*<span class="hljs-number">2</span> * i/fs) * volume get_wave = <span class="hljs-keyword">lambda</span> hz, beats: (get_sinus(hz, i) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(int(beats * beat_len))) get_hertz = <span class="hljs-keyword">lambda</span> note: <span class="hljs-number">440</span> * <span class="hljs-number">2</span> ** ((int(note[:<span class="hljs-number">2</span>]) - <span class="hljs-number">69</span>) / <span class="hljs-number">12</span>) get_beats = <span class="hljs-keyword">lambda</span> note: <span class="hljs-number">1</span>/<span class="hljs-number">2</span> <span class="hljs-keyword">if</span> <span class="hljs-string">'♩'</span> <span class="hljs-keyword">in</span> note <span class="hljs-keyword">else</span> <span class="hljs-number">1</span>/<span class="hljs-number">4</span> <span class="hljs-keyword">if</span> <span class="hljs-string">'♪'</span> <span class="hljs-keyword">in</span> note <span class="hljs-keyword">else</span> <span class="hljs-number">1</span> get_samps = <span class="hljs-keyword">lambda</span> n: get_wave(get_hertz(n), get_beats(n)) <span class="hljs-keyword">if</span> n <span class="hljs-keyword">else</span> get_pause(<span class="hljs-number">1</span>/<span class="hljs-number">4</span>) samples_f = it.chain(get_pause(<span class="hljs-number">1</span>/<span class="hljs-number">2</span>), *(get_samps(n) <span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> notes.split(<span class="hljs-string">','</span>))) sounddevice.play(np.fromiter(samples_f, np.float32), fs, blocking=<span class="hljs-keyword">True</span>) play_notes(<span class="hljs-string">'83♩,81♪,,83♪,,78♪,,74♪,,78♪,,71♪,,,,83♪,,81♪,,83♪,,78♪,,74♪,,78♪,,71♪,,,,'</span> <span class="hljs-string">'83♩,85♪,,86♪,,85♪,,86♪,,83♪,,85♩,83♪,,85♪,,81♪,,83♪,,81♪,,83♪,,79♪,,83♪,,,,'</span>) </code></pre></div></div> <div><h2 id="pygame"><a href="#pygame" name="pygame">#</a>Pygame</h2><div><h4 id="opensawindowanddrawsasquarethatcanbemovedwitharrowkeys">Opens a window and draws a square that can be moved with arrow keys:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pygame</span> <span class="hljs-keyword">import</span> pygame <span class="hljs-keyword">as</span> pg pg.init() window = pg.display.set_mode((<span class="hljs-number">500</span>, <span class="hljs-number">500</span>)) rect = pg.Rect(<span class="hljs-number">240</span>, <span class="hljs-number">240</span>, <span class="hljs-number">20</span>, <span class="hljs-number">20</span>) <span class="hljs-keyword">while</span> <span class="hljs-keyword">not</span> pg.event.get(pg.QUIT): <span class="hljs-keyword">for</span> evt <span class="hljs-keyword">in</span> pg.event.get(pg.KEYDOWN): dx = (evt.key == pg.K_RIGHT) - (evt.key == pg.K_LEFT) dy = (evt.key == pg.K_DOWN) - (evt.key == pg.K_UP) rect = rect.move((dx * <span class="hljs-number">20</span>, dy * <span class="hljs-number">20</span>)) window.fill(pg.Color(<span class="hljs-string">'black'</span>)) pg.draw.rect(window, pg.Color(<span class="hljs-string">'white'</span>), rect) pg.display.flip() pg.quit() </code></pre></div></div> <div><h3 id="rect">Rect</h3><p><strong>Stores top-left corner, width and height.</strong></p><pre><code class="python language-python hljs"><Rect> = pg.Rect(x, y, width, height) <span class="hljs-comment"># Creates Rect object. Truncates passed floats.</span> <int> = <Rect>.x/y/centerx/centery <span class="hljs-comment"># Also `top`, `right`, etc. Allows assignments.</span> <tup.> = <Rect>.topleft/center <span class="hljs-comment"># Also `topright/bottomright/bottomleft/size`.</span> <Rect> = <Rect>.move((dx, dy)) <span class="hljs-comment"># Use move_ip() to move the rectangle in-place.</span> </code></pre></div> <pre><code class="python language-python hljs"><bool> = <Rect>.collidepoint((x, y)) <span class="hljs-comment"># Returns True if rectangle contains the point.</span> <bool> = <Rect>.colliderect(<Rect>) <span class="hljs-comment"># Returns True if the rectangles are colliding.</span> <int> = <Rect>.collidelist(<Rects>) <span class="hljs-comment"># Returns index of first colliding Rect or -1.</span> <list> = <Rect>.collidelistall(<Rects>) <span class="hljs-comment"># Returns indices of all colliding rectangles.</span> </code></pre> <div><h3 id="surface">Surface</h3><p><strong>Stores image or main window's surface.</strong></p><pre><code class="python language-python hljs"><Surf> = pg.Surface((w, h)) <span class="hljs-comment"># New RGB surface. RGBA if `flags=pg.SRCALPHA`.</span> <Surf> = pg.display.set_mode((w, h)) <span class="hljs-comment"># Opens new window and returns surface object.</span> <Surf> = pg.image.load(<path/file>) <span class="hljs-comment"># Loads the image. Also get_width/get_height().</span> <Surf> = <Surf>.subsurface(<Rect>) <span class="hljs-comment"># Creates a new surface object from the cutout.</span> <view> = <Surf>.get_view() <span class="hljs-comment"># Use <view>.write(<array>) to write to image.</span> </code></pre></div> <pre><code class="python language-python hljs"><Surf>.fill(color) <span class="hljs-comment"># Pass tuple of ints or pg.Color('<name/hex>').</span> <Surf>.set_at((x, y), color) <span class="hljs-comment"># Updates a pixel. Also <Surf>.get_at((x, y)).</span> <Surf>.blit(<Surf>, (x, y)) <span class="hljs-comment"># Draws passed surface at a specified location.</span> </code></pre> <pre><code class="python language-python hljs"><Surf> = tr.scale(<Surf>, (w, h)) <span class="hljs-comment"># Import with `import pygame.transform as tr`.</span> <Surf> = tr.rotate(<Surf>, degrees) <span class="hljs-comment"># Rotates the surface for counterclock degrees.</span> <Surf> = tr.flip(<Surf>, flip_x=<span class="hljs-keyword">True</span>) <span class="hljs-comment"># Mirrors over the y axis. Also `flip_y=True`.</span> </code></pre> <pre><code class="python language-python hljs">line(<Surf>, color, (x1, y1), (x2, y2)) <span class="hljs-comment"># Also aaline. Run `from pygame.draw import *`.</span> arc(<Surf>, color, <Rect>, rad1, rad2) <span class="hljs-comment"># Draws an arc of an ellipse counterclockwise.</span> rect(<Surf>, color, <Rect>, width=<span class="hljs-number">0</span>) <span class="hljs-comment"># Also polygon(<Surf>, color, points, width=0).</span> circle(<Surf>, color, (x, y), radius) <span class="hljs-comment"># Also ellipse(<Surf>, color, <Rect>, width=0).</span> </code></pre> <pre><code class="python language-python hljs"><Font> = pg.font.Font(<path/file>, size) <span class="hljs-comment"># Loads a TTF file. Pass None for default font.</span> <Surf> = <Font>.render(<str>, <span class="hljs-keyword">True</span>, color) <span class="hljs-comment"># Accepts background color via fourth argument.</span> </code></pre> <div><h3 id="sound">Sound</h3><pre><code class="python language-python hljs"><Sound> = pg.mixer.Sound(<path/file>) <span class="hljs-comment"># Accepts WAV file or array of short integers.</span> <Sound>.play/stop() <span class="hljs-comment"># Accepts `loops=-1`. Also set_volume(<float>).</span> </code></pre></div> <div><h3 id="basicmariobrothersexample">Basic Mario Brothers Example</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> pygame <span class="hljs-keyword">as</span> pg, dataclasses <span class="hljs-keyword">as</span> dc, enum, io, itertools, random <span class="hljs-keyword">as</span> r, urllib.request W, H, D = <span class="hljs-number">50</span>, <span class="hljs-number">50</span>, enum.Enum(<span class="hljs-string">'D'</span>, <span class="hljs-string">'n e s w'</span>) <span class="hljs-comment"># Width, Height, Direction.</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_window</span><span class="hljs-params">()</span>:</span> pg.init() <span class="hljs-keyword">return</span> pg.display.set_mode((W*<span class="hljs-number">16</span>, H*<span class="hljs-number">16</span>)) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_images</span><span class="hljs-params">()</span>:</span> url = <span class="hljs-string">'https://gto76.github.io/python-cheatsheet/web/mario_bros.png'</span> img = pg.image.load(io.BytesIO(urllib.request.urlopen(url).read())) <span class="hljs-keyword">return</span> [img.subsurface(get_rect(x, <span class="hljs-number">0</span>)) <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(<span class="hljs-number">20</span>)] <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_mario</span><span class="hljs-params">()</span>:</span> Mario = dc.make_dataclass(<span class="hljs-string">'Mario'</span>, [<span class="hljs-string">'rect'</span>, <span class="hljs-string">'vx'</span>, <span class="hljs-string">'vy'</span>, <span class="hljs-string">'dir'</span>, <span class="hljs-string">'img_i'</span>]) <span class="hljs-keyword">return</span> Mario(get_rect(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>), <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, D.e, itertools.cycle(range(<span class="hljs-number">3</span>))) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_tiles</span><span class="hljs-params">()</span>:</span> is_border = <span class="hljs-keyword">lambda</span> x, y: x <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span>, W-<span class="hljs-number">1</span>] <span class="hljs-keyword">or</span> y <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span>, H-<span class="hljs-number">1</span>] borders = [(x, y) <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> range(W) <span class="hljs-keyword">for</span> y <span class="hljs-keyword">in</span> range(H) <span class="hljs-keyword">if</span> is_border(x, y)] platforms = [(r.randint(<span class="hljs-number">1</span>, W-<span class="hljs-number">2</span>), r.randint(<span class="hljs-number">2</span>, H-<span class="hljs-number">2</span>)) <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(<span class="hljs-number">200</span>)] <span class="hljs-keyword">return</span> [get_rect(x, y) <span class="hljs-keyword">for</span> x, y <span class="hljs-keyword">in</span> borders + platforms] <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_rect</span><span class="hljs-params">(x, y)</span>:</span> <span class="hljs-keyword">return</span> pg.Rect(x*<span class="hljs-number">16</span>, y*<span class="hljs-number">16</span>, <span class="hljs-number">16</span>, <span class="hljs-number">16</span>) run(get_window(), get_images(), get_mario(), get_tiles()) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run</span><span class="hljs-params">(window, images, mario, tiles)</span>:</span> clock = pg.time.Clock() pressed = set() <span class="hljs-keyword">while</span> <span class="hljs-keyword">not</span> pg.event.get(pg.QUIT): clock.tick(<span class="hljs-number">28</span>) pressed |= {e.key <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> pg.event.get(pg.KEYDOWN)} pressed -= {e.key <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> pg.event.get(pg.KEYUP)} update_velocity(mario, tiles, pressed) update_position(mario, tiles) draw(window, images, mario, tiles) pg.quit() <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_velocity</span><span class="hljs-params">(mario, tiles, pressed)</span>:</span> mario.vx += <span class="hljs-number">2</span> * ((pg.K_RIGHT <span class="hljs-keyword">in</span> pressed) - (pg.K_LEFT <span class="hljs-keyword">in</span> pressed)) mario.vx += (mario.vx < <span class="hljs-number">0</span>) - (mario.vx > <span class="hljs-number">0</span>) mario.vx = max(<span class="hljs-number">-4</span>, min(<span class="hljs-number">4</span>, mario.vx)) mario.vy += <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> is_airborne(mario, tiles) <span class="hljs-keyword">else</span> (pg.K_UP <span class="hljs-keyword">in</span> pressed) * <span class="hljs-number">-10</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_position</span><span class="hljs-params">(mario, tiles)</span>:</span> x, y = mario.rect.topleft steps = max(abs(mario.vx), abs(mario.vy)) <span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(steps): bounds = get_boundaries(mario.rect, tiles) mario.vx, mario.vy = stop_on_collision(mario.vx, mario.vy, bounds) mario.rect.topleft = x, y = x + (mario.vx/steps), y + (mario.vy/steps) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">is_airborne</span><span class="hljs-params">(mario, tiles)</span>:</span> <span class="hljs-keyword">return</span> D.s <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> get_boundaries(mario.rect, tiles) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_boundaries</span><span class="hljs-params">(rect, tiles)</span>:</span> deltas = {D.n: (<span class="hljs-number">0</span>, <span class="hljs-number">-1</span>), D.e: (<span class="hljs-number">1</span>, <span class="hljs-number">0</span>), D.s: (<span class="hljs-number">0</span>, <span class="hljs-number">1</span>), D.w: (<span class="hljs-number">-1</span>, <span class="hljs-number">0</span>)} <span class="hljs-keyword">return</span> {d <span class="hljs-keyword">for</span> d <span class="hljs-keyword">in</span> D <span class="hljs-keyword">if</span> rect.move(deltas[d]).collidelist(tiles) != <span class="hljs-number">-1</span>} <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">stop_on_collision</span><span class="hljs-params">(vx, vy, bounds)</span>:</span> <span class="hljs-keyword">return</span> (<span class="hljs-number">0</span> <span class="hljs-keyword">if</span> (D.w <span class="hljs-keyword">in</span> bounds <span class="hljs-keyword">and</span> vx < <span class="hljs-number">0</span>) <span class="hljs-keyword">or</span> (D.e <span class="hljs-keyword">in</span> bounds <span class="hljs-keyword">and</span> vx > <span class="hljs-number">0</span>) <span class="hljs-keyword">else</span> vx, <span class="hljs-number">0</span> <span class="hljs-keyword">if</span> (D.n <span class="hljs-keyword">in</span> bounds <span class="hljs-keyword">and</span> vy < <span class="hljs-number">0</span>) <span class="hljs-keyword">or</span> (D.s <span class="hljs-keyword">in</span> bounds <span class="hljs-keyword">and</span> vy > <span class="hljs-number">0</span>) <span class="hljs-keyword">else</span> vy) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">draw</span><span class="hljs-params">(window, images, mario, tiles)</span>:</span> window.fill((<span class="hljs-number">85</span>, <span class="hljs-number">168</span>, <span class="hljs-number">255</span>)) mario.dir = mario.dir <span class="hljs-keyword">if</span> mario.vx == <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> D.w <span class="hljs-keyword">if</span> mario.vx < <span class="hljs-number">0</span> <span class="hljs-keyword">else</span> D.e img_i = <span class="hljs-number">4</span> <span class="hljs-keyword">if</span> is_airborne(mario, tiles) <span class="hljs-keyword">else</span> next(mario.img_i) <span class="hljs-keyword">if</span> mario.vx <span class="hljs-keyword">else</span> <span class="hljs-number">6</span> window.blit(images[img_i + ((mario.dir == D.w) * <span class="hljs-number">9</span>)], mario.rect) <span class="hljs-keyword">for</span> tile <span class="hljs-keyword">in</span> tiles: is_border = tile.x <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span>, (W-<span class="hljs-number">1</span>)*<span class="hljs-number">16</span>] <span class="hljs-keyword">or</span> tile.y <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span>, (H-<span class="hljs-number">1</span>)*<span class="hljs-number">16</span>] window.blit(images[<span class="hljs-number">18</span> <span class="hljs-keyword">if</span> is_border <span class="hljs-keyword">else</span> <span class="hljs-number">19</span>], tile) pg.display.flip() <span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>: main() </code></pre></div> <div><h2 id="pandas"><a href="#pandas" name="pandas">#</a>Pandas</h2><p><strong>Data analysis library. For examples see <a href="#plotly">Plotly</a>.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pandas matplotlib</span> <span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd, matplotlib.pyplot <span class="hljs-keyword">as</span> plt </code></pre></div> <div><h3 id="series">Series</h3><p><strong>Ordered dictionary with a name.</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>s = pd.Series([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], index=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>], name=<span class="hljs-string">'a'</span>); s x <span class="hljs-number">1</span> y <span class="hljs-number">2</span> Name: a, dtype: int64 </code></pre></div> <pre><code class="python language-python hljs"><S> = pd.Series(<list>) <span class="hljs-comment"># Returns a series. Uses indices for 'index'.</span> <S> = pd.Series(<dict>) <span class="hljs-comment"># Returns a series. Uses keys for 'index'.</span> </code></pre> <pre><code class="python language-python hljs"><el> = <S>.loc[key] <span class="hljs-comment"># Or: <S>.iloc[i]</span> <S> = <S>.loc[coll_of_keys] <span class="hljs-comment"># Or: <S>.iloc[coll_of_i]</span> <S> = <S>.loc[from_key : to_key_inc] <span class="hljs-comment"># Or: <S>.iloc[from_i : to_i_exc]</span> </code></pre> <pre><code class="python language-python hljs"><el> = <S>[key/i] <span class="hljs-comment"># Or: <S>.<key></span> <S> = <S>[coll_of_keys/coll_of_i] <span class="hljs-comment"># Or: <S>[key/i : key/i]</span> <S> = <S>[<S_of_bools>] <span class="hljs-comment"># Or: <S>.loc/iloc[<S_of_bools>]</span> </code></pre> <pre><code class="python language-python hljs"><S> = <S> > <el/S> <span class="hljs-comment"># Returns S of bools. For logic use &, |, ~.</span> <S> = <S> + <el/S> <span class="hljs-comment"># Items with non-matching keys get value NaN.</span> </code></pre> <pre><code class="python language-python hljs"><S> = <S>.head/describe/sort_values() <span class="hljs-comment"># Also <S>.unique/value_counts/round/dropna().</span> <S> = <S>.str.strip/lower/contains/replace() <span class="hljs-comment"># Also split().str[i] and split(expand=True).</span> <S> = <S>.dt.year/month/day/hour <span class="hljs-comment"># Use pd.to_datetime(<S>) to get S of datetimes.</span> <S> = <S>.dt.to_period(<span class="hljs-string">'y/m/d/h'</span>) <span class="hljs-comment"># Quantizes datetimes into S of Period objects.</span> </code></pre> <pre><code class="python language-python hljs"><S>.plot.line/area/bar/pie/hist() <span class="hljs-comment"># Generates a plot. Accepts `title=<str>` arg.</span> plt.show() <span class="hljs-comment"># Displays the plot. Also plt.savefig(<path>).</span> </code></pre> <ul> <li><strong>Use <code class="python hljs"><span class="hljs-string">'print(<S>.to_string())'</span></code> to print a Series that contains more than sixty items.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'<S>.index'</span></code> to get collection of keys and <code class="python hljs"><span class="hljs-string">'<S>.index = <coll>'</span></code> to update them.</strong></li> <li><strong>Only pass a list or Series to loc/iloc because <code class="python hljs"><span class="hljs-string">'obj[x, y]'</span></code> is converted to <code class="python hljs"><span class="hljs-string">'obj[(x, y)]'</span></code> and <code class="python hljs"><span class="hljs-string">'<S>.loc[key_1, key_2]'</span></code> is how you retrieve a value from a multi-indexed Series.</strong></li> <li><strong>Pandas uses NumPy types like <code class="python hljs"><span class="hljs-string">'np.int64'</span></code>. Series is converted to <code class="python hljs"><span class="hljs-string">'float64'</span></code> if np.nan is assigned to any item. Use <code class="python hljs"><span class="hljs-string">'<S>.astype(<str/type>)'</span></code> to get converted Series.</strong></li> </ul> <div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs"><el> = <S>.sum/max/mean/std/idxmax/count() <span class="hljs-comment"># Or: <S>.agg(lambda <S>: <el>)</span> <S> = <S>.rank/diff/cumsum/ffill/interpol…() <span class="hljs-comment"># Or: <S>.agg/transform(lambda <S>: <S>)</span> <S> = <S>.isna/fillna/isin([<el/coll>]) <span class="hljs-comment"># Or: <S>.agg/transform/map(lambda <el>: <el>)</span> </code></pre></div> <pre><code class="python hljs">┏━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ ┃ │ <span class="hljs-string">'sum'</span> │ [<span class="hljs-string">'sum'</span>] │ {<span class="hljs-string">'s'</span>: <span class="hljs-string">'sum'</span>} ┃ ┠──────────────┼─────────────┼─────────────┼───────────────┨ ┃ s.apply(…) │ <span class="hljs-number">3</span> │ sum <span class="hljs-number">3</span> │ s <span class="hljs-number">3</span> ┃ ┃ s.agg(…) │ │ │ ┃ ┗━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ ┏━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ ┃ │ <span class="hljs-string">'rank'</span> │ [<span class="hljs-string">'rank'</span>] │ {<span class="hljs-string">'r'</span>: <span class="hljs-string">'rank'</span>} ┃ ┠──────────────┼─────────────┼─────────────┼───────────────┨ ┃ s.apply(…) │ │ rank │ ┃ ┃ s.agg(…) │ x <span class="hljs-number">1.0</span> │ x <span class="hljs-number">1.0</span> │ r x <span class="hljs-number">1.0</span> ┃ ┃ │ y <span class="hljs-number">2.0</span> │ y <span class="hljs-number">2.0</span> │ y <span class="hljs-number">2.0</span> ┃ ┗━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ </code></pre> <div><h3 id="dataframe">DataFrame</h3><p><strong>Table with labeled rows and columns.</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>df = pd.DataFrame([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]], index=[<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>], columns=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>]); df x y a <span class="hljs-number">1</span> <span class="hljs-number">2</span> b <span class="hljs-number">3</span> <span class="hljs-number">4</span> </code></pre></div> <pre><code class="python language-python hljs"><DF> = pd.DataFrame(<list_of_rows>) <span class="hljs-comment"># Rows can be either lists, dicts or series.</span> <DF> = pd.DataFrame(<dict_of_columns>) <span class="hljs-comment"># Columns can be either lists, dicts or series.</span> </code></pre> <pre><code class="python language-python hljs"><el> = <DF>.loc[row_key, col_key] <span class="hljs-comment"># Or: <DF>.iloc[row_i, col_i]</span> <S/DF> = <DF>.loc[row_key/s] <span class="hljs-comment"># Or: <DF>.iloc[row_i/s]</span> <S/DF> = <DF>.loc[:, col_key/s] <span class="hljs-comment"># Or: <DF>.iloc[:, col_i/s]</span> <DF> = <DF>.loc[row_bools, col_bools] <span class="hljs-comment"># Or: <DF>.iloc[row_bools, col_bools]</span> </code></pre> <pre><code class="python language-python hljs"><S/DF> = <DF>[col_key/s] <span class="hljs-comment"># Or: <DF>.<col_key></span> <DF> = <DF>[<S_of_bools>] <span class="hljs-comment"># Filters rows. For example `df[df.x > 1]`.</span> <DF> = <DF>[<DF_of_bools>] <span class="hljs-comment"># Assigns NaN to items that are False in bools.</span> </code></pre> <pre><code class="python language-python hljs"><DF> = <DF> > <el/S/DF> <span class="hljs-comment"># Returns DF of bools. Treats series as a row.</span> <DF> = <DF> + <el/S/DF> <span class="hljs-comment"># Items with non-matching keys get value NaN.</span> </code></pre> <pre><code class="python language-python hljs"><DF> = <DF>.set_index(col_key) <span class="hljs-comment"># Replaces row keys with column's values.</span> <DF> = <DF>.reset_index(drop=<span class="hljs-keyword">False</span>) <span class="hljs-comment"># Drops or moves row keys to column named index.</span> <DF> = <DF>.sort_index(ascending=<span class="hljs-keyword">True</span>) <span class="hljs-comment"># Sorts rows by row keys. Use `axis=1` for cols.</span> <DF> = <DF>.sort_values(col_key/s) <span class="hljs-comment"># Sorts rows by passed column/s. Also `axis=1`.</span> </code></pre> <pre><code class="python language-python hljs"><DF> = <DF>.head/tail/sample(<int>) <span class="hljs-comment"># Returns first, last, or random n rows.</span> <DF> = <DF>.describe() <span class="hljs-comment"># Describes columns. Also info(), corr(), shape.</span> <DF> = <DF>.query(<span class="hljs-string">'<query>'</span>) <span class="hljs-comment"># Filters rows. For example `df.query('x > 1')`.</span> </code></pre> <pre><code class="python language-python hljs"><DF>.plot.line/area/bar/scatter(x=col_key, …) <span class="hljs-comment"># `y=col_key/s`. Also hist/box(column/by=col_k).</span> plt.show() <span class="hljs-comment"># Displays the plot. Also plt.savefig(<path>).</span> </code></pre> <div><h4 id="dataframemergejoinconcat">DataFrame — Merge, Join, Concat:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>df_2 = pd.DataFrame([[<span class="hljs-number">4</span>, <span class="hljs-number">5</span>], [<span class="hljs-number">6</span>, <span class="hljs-number">7</span>]], index=[<span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>], columns=[<span class="hljs-string">'y'</span>, <span class="hljs-string">'z'</span>]); df_2 y z b <span class="hljs-number">4</span> <span class="hljs-number">5</span> c <span class="hljs-number">6</span> <span class="hljs-number">7</span> </code></pre></div> <pre><code class="python hljs">┏━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ │ <span class="hljs-string">'outer'</span> │ <span class="hljs-string">'inner'</span> │ <span class="hljs-string">'left'</span> │ Description ┃ ┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨ ┃ df.merge(df_2, │ x y z │ x y z │ x y z │ Merges on column if 'on' ┃ ┃ on=<span class="hljs-string">'y'</span>, │ <span class="hljs-number">0</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span> . │ <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ <span class="hljs-number">1</span> <span class="hljs-number">2</span> . │ or 'left_on/right_on' are ┃ ┃ how=…) │ <span class="hljs-number">1</span> <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ │ <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ set, else on shared cols. ┃ ┃ │ <span class="hljs-number">2</span> . <span class="hljs-number">6</span> <span class="hljs-number">7</span> │ │ │ Uses <span class="hljs-string">'inner'</span> by default. ┃ ┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨ ┃ df.join(df_2, │ x yl yr z │ │ x yl yr z │ Merges on row keys. ┃ ┃ lsuffix=<span class="hljs-string">'l'</span>, │ a <span class="hljs-number">1</span> <span class="hljs-number">2</span> . . │ x yl yr z │ <span class="hljs-number">1</span> <span class="hljs-number">2</span> . . │ Uses <span class="hljs-string">'left'</span> by default. ┃ ┃ rsuffix=<span class="hljs-string">'r'</span>, │ b <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ If Series is passed, it ┃ ┃ how=…) │ c . . <span class="hljs-number">6</span> <span class="hljs-number">7</span> │ │ │ is treated as a column. ┃ ┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨ ┃ pd.concat([df, df_2], │ x y z │ y │ │ Adds rows at the bottom. ┃ ┃ axis=<span class="hljs-number">0</span>, │ a <span class="hljs-number">1</span> <span class="hljs-number">2</span> . │ <span class="hljs-number">2</span> │ │ Uses <span class="hljs-string">'outer'</span> by default. ┃ ┃ join=…) │ b <span class="hljs-number">3</span> <span class="hljs-number">4</span> . │ <span class="hljs-number">4</span> │ │ A Series is treated as a ┃ ┃ │ b . <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ <span class="hljs-number">4</span> │ │ column. To add a row use ┃ ┃ │ c . <span class="hljs-number">6</span> <span class="hljs-number">7</span> │ <span class="hljs-number">6</span> │ │ pd.concat([df, DF([s])]). ┃ ┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨ ┃ pd.concat([df, df_2], │ x y y z │ │ │ Adds columns at the ┃ ┃ axis=<span class="hljs-number">1</span>, │ a <span class="hljs-number">1</span> <span class="hljs-number">2</span> . . │ x y y z │ │ right end. Uses <span class="hljs-string">'outer'</span> ┃ ┃ join=…) │ b <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ │ by default. A Series is ┃ ┃ │ c . . <span class="hljs-number">6</span> <span class="hljs-number">7</span> │ │ │ treated as a column. ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ </code></pre> <div><h4 id="dataframeaggregatetransformmap">DataFrame — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs"><S> = <DF>.sum/max/mean/std/idxmax/count() <span class="hljs-comment"># Or: <DF>.apply/agg(lambda <S>: <el>)</span> <DF> = <DF>.rank/diff/cumsum/ffill/interpo…() <span class="hljs-comment"># Or: <DF>.apply/agg/transform(lambda <S>: <S>)</span> <DF> = <DF>.isna/fillna/isin([<el/coll>]) <span class="hljs-comment"># Or: <DF>.applymap(lambda <el>: <el>)</span> </code></pre></div> <pre><code class="python hljs">┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ ┃ │ <span class="hljs-string">'sum'</span> │ [<span class="hljs-string">'sum'</span>] │ {<span class="hljs-string">'x'</span>: <span class="hljs-string">'sum'</span>} ┃ ┠─────────────────┼───────────────┼───────────────┼───────────────┨ ┃ df.apply(…) │ x <span class="hljs-number">4</span> │ x y │ x <span class="hljs-number">4</span> ┃ ┃ df.agg(…) │ y <span class="hljs-number">6</span> │ sum <span class="hljs-number">4</span> <span class="hljs-number">6</span> │ ┃ ┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ ┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ ┃ │ <span class="hljs-string">'rank'</span> │ [<span class="hljs-string">'rank'</span>] │ {<span class="hljs-string">'x'</span>: <span class="hljs-string">'rank'</span>} ┃ ┠─────────────────┼───────────────┼───────────────┼───────────────┨ ┃ df.apply(…) │ │ x y │ ┃ ┃ df.agg(…) │ x y │ rank rank │ x ┃ ┃ df.transform(…) │ a <span class="hljs-number">1.0</span> <span class="hljs-number">1.0</span> │ a <span class="hljs-number">1.0</span> <span class="hljs-number">1.0</span> │ a <span class="hljs-number">1.0</span> ┃ ┃ │ b <span class="hljs-number">2.0</span> <span class="hljs-number">2.0</span> │ b <span class="hljs-number">2.0</span> <span class="hljs-number">2.0</span> │ b <span class="hljs-number">2.0</span> ┃ ┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ </code></pre> <ul> <li><strong>Listed methods process the columns unless they receive <code class="python hljs"><span class="hljs-string">'axis=1'</span></code>. Exceptions to this rule are <code class="python hljs"><span class="hljs-string">'<DF>.dropna()'</span></code>, <code class="python hljs"><span class="hljs-string">'<DF>.drop(row_key/s)'</span></code> and <code class="python hljs"><span class="hljs-string">'<DF>.rename(<dict/func>)'</span></code>.</strong></li> <li><strong>Fifth result's columns are indexed with a multi-index. This means we need a tuple of column keys to specify a column: <code class="python hljs"><span class="hljs-string">'<DF>.loc[row_key, (col_key_1, col_key_2)]'</span></code>.</strong></li> </ul> <div><h3 id="multiindex">Multi-Index</h3><pre><code class="python language-python hljs"><DF> = <DF>.loc[row_key_1] <span class="hljs-comment"># Also <DF>.loc[(slice(None), row_key_2), :].</span> <DF> = <DF>.loc[:, col_key_1] <span class="hljs-comment"># Same as <DF>.xs(col_key_1, axis=1, level=0).</span> <DF> = <DF>.set_index(col_key/s) <span class="hljs-comment"># Moves column/s to index. Also `append=True`.</span> <DF> = <DF>.pivot_table(index=col_key/s) <span class="hljs-comment"># `columns=key/s, values=k/s, aggfunc='mean'`.</span> <S> = <DF>.stack/unstack(level=<span class="hljs-number">-1</span>) <span class="hljs-comment"># Combines col. keys with index or vice versa.</span> </code></pre></div> <div><h3 id="fileformats">File Formats</h3><pre><code class="python language-python hljs"><S/DF> = pd.read_json/pickle(<path/url/file>) <span class="hljs-comment"># Also io.StringIO(<str>), io.BytesIO(<bytes>).</span> <DF> = pd.read_csv/excel(<path/url/file>) <span class="hljs-comment"># Also `header/index_col/dtype/usecols/…=<obj>`.</span> <list> = pd.read_html(<path/url/file>) <span class="hljs-comment"># Raises ImportError if webpage has zero tables.</span> <S/DF> = pd.read_parquet/feather/hdf(<path…>) <span class="hljs-comment"># Function read_hdf() accepts `key=<s/df_name>`.</span> <DF> = pd.read_sql(<span class="hljs-string">'<table/query>'</span>, <conn>) <span class="hljs-comment"># Pass SQLite3/Alchemy connection. See #SQLite.</span> </code></pre></div> <pre><code class="python language-python hljs"><DF>.to_json/csv/html/latex/parquet(<path>) <span class="hljs-comment"># Returns a string/bytes if path is omitted.</span> <DF>.to_pickle/excel/feather/hdf(<path>) <span class="hljs-comment"># Method to_hdf() requires `key=<s/df_name>`.</span> <DF>.to_sql(<span class="hljs-string">'<table_name>'</span>, <connection>) <span class="hljs-comment"># Also `if_exists='fail/replace/append'`.</span> </code></pre> <ul> <li><strong><code class="python hljs"><span class="hljs-string">'$ pip3 install "pandas[excel]" odfpy lxml pyarrow'</span></code> installs dependencies.</strong></li> <li><strong>Csv functions use the same dialect as standard library's csv module (e.g. <code class="python hljs"><span class="hljs-string">'sep=","'</span></code>).</strong></li> <li><strong>Read_csv() only parses dates of columns that are listed in 'parse_dates'. It automatically tries to detect the format, but it can be helped with 'date_format' or 'dayfirst' arguments.</strong></li> <li><strong>We get a dataframe with DatetimeIndex if 'parse_dates' argument includes 'index_col'. Its <code class="python hljs"><span class="hljs-string">'resample("y/m/d/h")'</span></code> method returns Resampler object that is similar to GroupBy.</strong></li> </ul> <div><h3 id="groupby">GroupBy</h3><p><strong>Object that groups together rows of a dataframe based on the value of the passed column.</strong></p><pre><code class="python language-python hljs"><GB> = <DF>.groupby(col_key/s) <span class="hljs-comment"># Splits DF into groups based on passed col.</span> <DF> = <GB>.apply/filter(<func>) <span class="hljs-comment"># Filter drops a group if func returns False.</span> <DF> = <GB>.get_group(<el>) <span class="hljs-comment"># Selects a group by grouping column's value.</span> <S> = <GB>.size() <span class="hljs-comment"># S of group sizes. Same keys as get_group().</span> <GB> = <GB>[col_key] <span class="hljs-comment"># Single column GB. All operations return S.</span> </code></pre></div> <pre><code class="python language-python hljs"><DF> = <GB>.sum/max/mean/std/idxmax/count() <span class="hljs-comment"># Or: <GB>.agg(lambda <S>: <el>)</span> <DF> = <GB>.rank/diff/cumsum/ffill() <span class="hljs-comment"># Or: <GB>.transform(lambda <S>: <S>)</span> <DF> = <GB>.fillna(<el>) <span class="hljs-comment"># Or: <GB>.transform(lambda <S>: <S>)</span> </code></pre> <div><h4 id="dividesrowsintogroupsandsumstheircolumnsresulthasanamedindexthatcreatescolumnzonreset_index">Divides rows into groups and sums their columns. Result has a named index that creates column <code class="python hljs"><span class="hljs-string">'z'</span></code> on reset_index():</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>df = pd.DataFrame([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>], [<span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">6</span>]], list(<span class="hljs-string">'abc'</span>), list(<span class="hljs-string">'xyz'</span>)) <span class="hljs-meta">>>> </span>gb = df.groupby(<span class="hljs-string">'z'</span>); gb.apply(print) x y z a <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span> x y z b <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span> c <span class="hljs-number">7</span> <span class="hljs-number">8</span> <span class="hljs-number">6</span> <span class="hljs-meta">>>> </span>gb.sum() x y z <span class="hljs-number">3</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">6</span> <span class="hljs-number">11</span> <span class="hljs-number">13</span></code></pre></div> <div><h3 id="rolling">Rolling</h3><p><strong>Object for rolling window calculations.</strong></p><pre><code class="python language-python hljs"><RS/RDF/RGB> = <S/DF/GB>.rolling(win_size) <span class="hljs-comment"># Also `min_periods=None, center=False`.</span> <RS/RDF/RGB> = <RDF/RGB>[col_key/s] <span class="hljs-comment"># Also <RDF/RGB>.<col_key> if key is str.</span> <S/DF> = <R>.mean/sum/max() <span class="hljs-comment"># Or: <R>.apply/agg(lambda <S>: <el>)</span> </code></pre></div> <div><h2 id="plotly"><a href="#plotly" name="plotly">#</a>Plotly</h2><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install plotly kaleido pandas</span> <span class="hljs-keyword">import</span> plotly.express <span class="hljs-keyword">as</span> px, pandas <span class="hljs-keyword">as</span> pd </code></pre></div> <pre><code class="python language-python hljs"><Fig> = px.line(<DF> [, y=col_key/s [, x=col_key]]) <span class="hljs-comment"># Also px.line(y=<list> [, x=<list>]).</span> <Fig>.update_layout(paper_bgcolor=<span class="hljs-string">'#rrggbb'</span>) <span class="hljs-comment"># Also `margin=dict(t=0, r=0, b=0, l=0)`.</span> <Fig>.write_html/json/image(<span class="hljs-string">'<path>'</span>) <span class="hljs-comment"># Use <Fig>.show() to display the plot.</span> </code></pre> <pre><code class="python language-python hljs"><Fig> = px.area/bar/box(<DF>, x=col_key, y=col_keys) <span class="hljs-comment"># Also `color=col_key`. All are optional.</span> <Fig> = px.scatter(<DF>, x=col_key, y=col_keys) <span class="hljs-comment"># Also `color/size/symbol=col_key`. Same.</span> <Fig> = px.scatter_3d(<DF>, x=col_key, y=col_key, …) <span class="hljs-comment"># `z=col_key`. Also color, size, symbol.</span> <Fig> = px.histogram(<DF>, x=col_keys, y=col_key) <span class="hljs-comment"># Also color, nbins. All are optional.</span> </code></pre> <div><h4 id="displaysalinechartoftotalcovid19deathspermilliongroupedbycontinent">Displays a line chart of total COVID-19 deaths per million grouped by continent:</h4><p></p><div id="2a950764-39fc-416d-97fe-0a6226a3095f" class="plotly-graph-div" style="height:312px; width:914px;"></div><pre><code class="python language-python hljs">covid = pd.read_csv(<span class="hljs-string">'https://raw.githubusercontent.com/owid/covid-19-data/8dde8ca49b'</span> <span class="hljs-string">'6e648c17dd420b2726ca0779402651/public/data/owid-covid-data.csv'</span>, usecols=[<span class="hljs-string">'iso_code'</span>, <span class="hljs-string">'date'</span>, <span class="hljs-string">'population'</span>, <span class="hljs-string">'total_deaths'</span>]) continents = pd.read_csv(<span class="hljs-string">'https://gto76.github.io/python-cheatsheet/web/continents.csv'</span>, usecols=[<span class="hljs-string">'Three_Letter_Country_Code'</span>, <span class="hljs-string">'Continent_Name'</span>]) df = pd.merge(covid, continents, left_on=<span class="hljs-string">'iso_code'</span>, right_on=<span class="hljs-string">'Three_Letter_Country_Code'</span>) df = df.groupby([<span class="hljs-string">'Continent_Name'</span>, <span class="hljs-string">'date'</span>]).sum().reset_index() df[<span class="hljs-string">'Total Deaths per Million'</span>] = df.total_deaths * <span class="hljs-number">1e6</span> / df.population df = df[df.date > <span class="hljs-string">'2020-03-14'</span>] df = df.rename({<span class="hljs-string">'date'</span>: <span class="hljs-string">'Date'</span>, <span class="hljs-string">'Continent_Name'</span>: <span class="hljs-string">'Continent'</span>}, axis=<span class="hljs-string">'columns'</span>) px.line(df, x=<span class="hljs-string">'Date'</span>, y=<span class="hljs-string">'Total Deaths per Million'</span>, color=<span class="hljs-string">'Continent'</span>) </code></pre></div> <div><h4 id="displaysamultiaxislinechartoftotalcovid19casesandchangesinpricesofbitcoindowjonesandgold">Displays a multi-axis line chart of total COVID-19 cases and changes in prices of Bitcoin, Dow Jones and gold:</h4><p></p><div id="e23ccacc-a456-478b-b467-7282a2165921" class="plotly-graph-div" style="height:285px; width:935px;"></div><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pandas lxml selenium plotly</span> <span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd, selenium.webdriver, io, plotly.graph_objects <span class="hljs-keyword">as</span> go <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>:</span> covid, (bitcoin, gold, dow) = get_covid_cases(), get_tickers() df = wrangle_data(covid, bitcoin, gold, dow) display_data(df) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_covid_cases</span><span class="hljs-params">()</span>:</span> url = <span class="hljs-string">'https://catalog.ourworldindata.org/garden/covid/latest/compact/compact.csv'</span> df = pd.read_csv(url, parse_dates=[<span class="hljs-string">'date'</span>]) df = df[df.country == <span class="hljs-string">'World'</span>] s = df.set_index(<span class="hljs-string">'date'</span>).total_cases <span class="hljs-keyword">return</span> s.rename(<span class="hljs-string">'Total Cases'</span>) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_tickers</span><span class="hljs-params">()</span>:</span> <span class="hljs-keyword">with</span> selenium.webdriver.Chrome() <span class="hljs-keyword">as</span> driver: driver.implicitly_wait(<span class="hljs-number">10</span>) symbols = {<span class="hljs-string">'Bitcoin'</span>: <span class="hljs-string">'BTC-USD'</span>, <span class="hljs-string">'Gold'</span>: <span class="hljs-string">'GC=F'</span>, <span class="hljs-string">'Dow Jones'</span>: <span class="hljs-string">'%5EDJI'</span>} <span class="hljs-keyword">return</span> [get_ticker(driver, name, symbol) <span class="hljs-keyword">for</span> name, symbol <span class="hljs-keyword">in</span> symbols.items()] <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_ticker</span><span class="hljs-params">(driver, name, symbol)</span>:</span> url = <span class="hljs-string">f'https://finance.yahoo.com/quote/<span class="hljs-subst">{symbol}</span>/history/'</span> driver.get(url + <span class="hljs-string">'?period1=1579651200&period2=9999999999'</span>) <span class="hljs-keyword">if</span> buttons := driver.find_elements(<span class="hljs-string">'xpath'</span>, <span class="hljs-string">'//button[@name="reject"]'</span>): buttons[<span class="hljs-number">0</span>].click() html = io.StringIO(driver.page_source) dataframes = pd.read_html(html, parse_dates=[<span class="hljs-string">'Date'</span>]) s = dataframes[<span class="hljs-number">0</span>].set_index(<span class="hljs-string">'Date'</span>).Open <span class="hljs-keyword">return</span> s.rename(name) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrangle_data</span><span class="hljs-params">(covid, bitcoin, gold, dow)</span>:</span> df = pd.concat([bitcoin, gold, dow], axis=<span class="hljs-number">1</span>) <span class="hljs-comment"># Creates DF by joining columns on dates.</span> df = df.sort_index().interpolate() <span class="hljs-comment"># Sorts rows by date, interpolates NaN-s.</span> df = df.loc[<span class="hljs-string">'2020-02-23'</span>:<span class="hljs-string">'2021-12-20'</span>] <span class="hljs-comment"># Keeps rows between the specified dates.</span> df = (df / df.iloc[<span class="hljs-number">0</span>]) * <span class="hljs-number">100</span> <span class="hljs-comment"># Divides all cells by first day's value.</span> df = df.join(covid) <span class="hljs-comment"># Adds column that contains covid cases.</span> <span class="hljs-keyword">return</span> df.sort_values(df.index[<span class="hljs-number">-1</span>], axis=<span class="hljs-number">1</span>) <span class="hljs-comment"># Sorts columns by the last day's value.</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">display_data</span><span class="hljs-params">(df)</span>:</span> figure = go.Figure() <span class="hljs-keyword">for</span> col_name <span class="hljs-keyword">in</span> reversed(df.columns): yaxis = <span class="hljs-string">'y1'</span> <span class="hljs-keyword">if</span> col_name == <span class="hljs-string">'Total Cases'</span> <span class="hljs-keyword">else</span> <span class="hljs-string">'y2'</span> trace = go.Scatter(x=df.index, y=df[col_name], yaxis=yaxis, name=col_name) figure.add_trace(trace) figure.update_layout( width=<span class="hljs-number">944</span>, height=<span class="hljs-number">423</span>, yaxis1=dict(title=<span class="hljs-string">'Total Cases'</span>, rangemode=<span class="hljs-string">'tozero'</span>), yaxis2=dict(title=<span class="hljs-string">'%'</span>, rangemode=<span class="hljs-string">'tozero'</span>, overlaying=<span class="hljs-string">'y'</span>, side=<span class="hljs-string">'right'</span>), colorway=[<span class="hljs-string">'#EF553B'</span>, <span class="hljs-string">'#636EFA'</span>, <span class="hljs-string">'#00CC96'</span>, <span class="hljs-string">'#FFA152'</span>], legend=dict(x=<span class="hljs-number">1.08</span>) ) figure.show() <span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>: main() </code></pre></div> <div><h2 id="appendix"><a href="#appendix" name="appendix">#</a>Appendix</h2><div><h3 id="cython">Cython</h3><p><strong>Library that compiles Python-like code into C.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install cython</span> <span class="hljs-keyword">import</span> pyximport; pyximport.install() <span class="hljs-comment"># Module that runs Cython scripts.</span> <span class="hljs-keyword">import</span> <cython_script> <span class="hljs-comment"># Script must have '.pyx' extension.</span> </code></pre></div></div> <div><h4 id="allcdefdefinitionsareoptionalbuttheycontributetothespeedup">All <code class="python hljs"><span class="hljs-string">'cdef'</span></code> definitions are optional, but they contribute to the speed-up:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <type> <var_name> [= <obj/var>] <span class="hljs-comment"># Either Python or C type variable.</span> <span class="hljs-keyword">cdef</span> <ctype> *<pointer_name> [= &<var>] <span class="hljs-comment"># Use <pointer>[0] to get the value.</span> <span class="hljs-keyword">cdef</span> <ctype>[size] <array_name> [= <coll/array>] <span class="hljs-comment"># Also `<ctype>[:] <mview> = <array>`.</span> <span class="hljs-keyword">cdef</span> <ctype> *<array_name> [= <coll/array/pointer>] <span class="hljs-comment"># E.g. `<<ctype> *> malloc(n_bytes)`.</span> </code></pre></div> <pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <type> <func_name>(<type> [*]<arg_name>): ... <span class="hljs-comment"># Omitted types default to `object`.</span> </code></pre> <pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <<span class="hljs-title">class_name</span>>:</span> <span class="hljs-comment"># Also `cdef struct <struct_name>:`.</span> <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> <type> [*]<attr_name> <span class="hljs-comment"># Also `... <ctype> [*]<field_name>`.</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, <type> <arg_name>)</span>:</span> <span class="hljs-comment"># Also `cdef __dealloc__(self):`.</span> self.<attr_name> = <arg_name> <span class="hljs-comment"># Also `... free(<array/pointer>)`.</span> </code></pre> <div><h3 id="virtualenvironments">Virtual Environments</h3><p><strong>System for installing libraries directly into project's directory.</strong></p><pre><code class="python hljs">$ python3 -m venv NAME <span class="hljs-comment"># Creates virtual environment in the current directory.</span> $ source NAME/bin/activate <span class="hljs-comment"># Activates it. On Windows run `NAME\Scripts\activate`.</span> $ pip3 install LIBRARY <span class="hljs-comment"># Installs the library into active virtual environment.</span> $ python3 FILE <span class="hljs-comment"># Runs the script in active environment. Also `./FILE`.</span> $ deactivate <span class="hljs-comment"># Deactivates the currently active virtual environment.</span> </code></pre></div> <div><h3 id="basicscripttemplate">Basic Script Template</h3><p><strong>Run the script with <code class="python hljs"><span class="hljs-string">'$ python3 FILE'</span></code> or <code class="python hljs"><span class="hljs-string">'$ chmod u+x FILE; ./FILE'</span></code>. To automatically start the debugger when uncaught exception occurs run <code class="python hljs"><span class="hljs-string">'$ python3 -m pdb -cc FILE'</span></code>.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment">#!/usr/bin/env python3</span> <span class="hljs-comment">#</span> <span class="hljs-comment"># Usage: .py</span> <span class="hljs-comment">#</span> <span class="hljs-keyword">from</span> sys <span class="hljs-keyword">import</span> argv, exit <span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> defaultdict, namedtuple <span class="hljs-keyword">from</span> dataclasses <span class="hljs-keyword">import</span> make_dataclass <span class="hljs-keyword">from</span> enum <span class="hljs-keyword">import</span> Enum <span class="hljs-keyword">import</span> functools <span class="hljs-keyword">as</span> ft, itertools <span class="hljs-keyword">as</span> it, operator <span class="hljs-keyword">as</span> op, re <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>:</span> <span class="hljs-keyword">pass</span> <span class="hljs-comment">###</span> <span class="hljs-comment">## UTIL</span> <span class="hljs-comment">#</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_file</span><span class="hljs-params">(filename)</span>:</span> <span class="hljs-keyword">with</span> open(filename, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> file: <span class="hljs-keyword">return</span> file.readlines() <span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">'__main__'</span>: main() </code></pre></div> <div><h2 id="index"><a href="#index" name="index">#</a>Index</h2><ul><li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li> <li><strong>Searching <code class="python hljs"><span class="hljs-string">'#<title>'</span></code> will limit the search to the titles.</strong></li> <li><strong>Click on the title's <code class="python hljs"><span class="hljs-string">'#'</span></code> to get a link to its section.</strong></li> </ul></div> <footer> <aside>July 27, 2026</aside> <a href="https://gto76.github.io" rel="author">Jure Šorn</a> </footer> <a href="javascript:" id="return-to-top"><i class="icon-chevron-up"></i></a> <script src="web/jquery-3.4.0.min.js"></script> <script src="web/script_2.js"></script> <script type="text/javascript" src="https://transactions.sendowl.com/assets/sendowl.js" ></script> <script src="web/plotly.min.js"></script> <script src="web/covid_deaths.js"></script> <script src="web/covid_cases.js"></script> </body> </html>