From 86e97e638cc9beb5df42ce3ed2585961c5b37586 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 13 Nov 2024 14:54:58 +0100
Subject: [PATCH 001/186] Numbers, Decorator, Class, Duck types

---
 README.md  | 12 ++++++------
 index.html | 17 +++++++++--------
 parse.js   |  2 +-
 3 files changed, 16 insertions(+), 15 deletions(-)

diff --git a/README.md b/README.md
index eaf4779ab..d61ef649d 100644
--- a/README.md
+++ b/README.md
@@ -493,7 +493,7 @@ Format
 Numbers
 -------
 ```python
-<int>      = int(<float/str/bool>)                # Or: math.floor(<float>)
+<int>      = int(<float/str/bool>)                # Or: math.trunc(<float>)
 <float>    = float(<int/str/bool>)                # Or: <int/float>e±<int>
 <complex>  = complex(real=0, imag=0)              # Or: <int/float> ± <int/float>j
 <Fraction> = fractions.Fraction(0, 1)             # Or: Fraction(numerator=0, denominator=1)
@@ -931,7 +931,7 @@ from functools import cache
 def fib(n):
     return n if n < 2 else fib(n-2) + fib(n-1)
 ```
-* **Potential problem with cache is that it can grow indefinitely. To clear its stored values run `'fib.cache_clear()'`, or use `'@lru_cache(maxsize=<int>)'` decorator instead.**
+* **Potential problem with cache is that it can grow indefinitely. To clear stored return values run `'fib.cache_clear()'`, or use `'@lru_cache(maxsize=<int>)'` decorator instead.**
 * **CPython interpreter limits recursion depth to 3000 by default. To increase it run `'sys.setrecursionlimit(<int>)'`.**
 
 ### Parametrized Decorator
@@ -1055,9 +1055,9 @@ class <class_name>:
 * **For attributes of arbitrary type use `'typing.Any'`.**
 
 ```python
-<class> = make_dataclass('<class_name>', <coll_of_attribute_names>)
-<class> = make_dataclass('<class_name>', <coll_of_tuples>)
-<tuple> = ('<attr_name>', <type> [, <default_value>])
+Point = make_dataclass('Point', ['x', 'y'])
+Point = make_dataclass('Point', [('x', float), ('y', float)])
+Point = make_dataclass('Point', [('x', float, 0), ('y', float, 0)])
 ```
 
 ### Property
@@ -1293,7 +1293,7 @@ class MySequence:
 ```
 
 #### Discrepancies between glossary definitions and abstract base classes:
-* **Glossary on Python's website defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.**
+* **Python's glossary defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.**
 * **Passing ABC Iterable to isinstance() or issubclass() checks whether object/class has method iter(), while ABC Collection checks for iter(), contains() and len().**
 
 ### ABC Sequence
diff --git a/index.html b/index.html
index 53210903f..21d034499 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 7, 2024</aside>
+    <aside>November 13, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -444,7 +444,7 @@
 {<span class="hljs-number">90</span>:X}                                   <span class="hljs-comment"># '5A'. Number 90 in uppercase hexadecimal.</span>
 </code></pre></div>
 
-<div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs">&lt;int&gt;      = int(&lt;float/str/bool&gt;)                <span class="hljs-comment"># Or: math.floor(&lt;float&gt;)</span>
+<div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs">&lt;int&gt;      = int(&lt;float/str/bool&gt;)                <span class="hljs-comment"># Or: math.trunc(&lt;float&gt;)</span>
 &lt;float&gt;    = float(&lt;int/str/bool&gt;)                <span class="hljs-comment"># Or: &lt;int/float&gt;e±&lt;int&gt;</span>
 &lt;complex&gt;  = complex(real=<span class="hljs-number">0</span>, imag=<span class="hljs-number">0</span>)              <span class="hljs-comment"># Or: &lt;int/float&gt; ± &lt;int/float&gt;j</span>
 &lt;Fraction&gt; = fractions.Fraction(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>)             <span class="hljs-comment"># Or: Fraction(numerator=0, denominator=1)</span>
@@ -778,7 +778,7 @@
 
 
 <ul>
-<li><strong>Potential problem with cache is that it can grow indefinitely. To clear its stored values run <code class="python hljs"><span class="hljs-string">'fib.cache_clear()'</span></code>, or use <code class="python hljs"><span class="hljs-string">'@lru_cache(maxsize=&lt;int&gt;)'</span></code> decorator instead.</strong></li>
+<li><strong>Potential problem with cache is that it can grow indefinitely. To clear stored return values run <code class="python hljs"><span class="hljs-string">'fib.cache_clear()'</span></code>, or use <code class="python hljs"><span class="hljs-string">'@lru_cache(maxsize=&lt;int&gt;)'</span></code> decorator instead.</strong></li>
 <li><strong>CPython interpreter limits recursion depth to 3000 by default. To increase it run <code class="python hljs"><span class="hljs-string">'sys.setrecursionlimit(&lt;int&gt;)'</span></code>.</strong></li>
 </ul>
 <div><h3 id="parametrizeddecorator">Parametrized Decorator</h3><p><strong>A decorator that accepts arguments and returns a normal decorator that accepts a function.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps
@@ -886,9 +886,10 @@
 <li><strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">'&lt;attr_name&gt;: list = []'</span></code> would make a list that is shared among all instances. Its 'default_factory' argument can be any <a href="#callable">callable</a>.</strong></li>
 <li><strong>For attributes of arbitrary type use <code class="python hljs"><span class="hljs-string">'typing.Any'</span></code>.</strong></li>
 </ul>
-<pre><code class="python language-python hljs">&lt;class&gt; = make_dataclass(<span class="hljs-string">'&lt;class_name&gt;'</span>, &lt;coll_of_attribute_names&gt;)
-&lt;class&gt; = make_dataclass(<span class="hljs-string">'&lt;class_name&gt;'</span>, &lt;coll_of_tuples&gt;)
-&lt;tuple&gt; = (<span class="hljs-string">'&lt;attr_name&gt;'</span>, &lt;type&gt; [, &lt;default_value&gt;])</code></pre>
+<pre><code class="python language-python hljs">Point = make_dataclass(<span class="hljs-string">'Point'</span>, [<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>])
+Point = make_dataclass(<span class="hljs-string">'Point'</span>, [(<span class="hljs-string">'x'</span>, float), (<span class="hljs-string">'y'</span>, float)])
+Point = make_dataclass(<span class="hljs-string">'Point'</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><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>
@@ -1098,7 +1099,7 @@
 
 
 <div><h4 id="discrepanciesbetweenglossarydefinitionsandabstractbaseclasses">Discrepancies between glossary definitions and abstract base classes:</h4><ul>
-<li><strong>Glossary on Python's website defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.</strong></li>
+<li><strong>Python's glossary defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.</strong></li>
 <li><strong>Passing ABC Iterable to isinstance() or issubclass() checks whether object/class has method iter(), while ABC Collection checks for iter(), contains() and len().</strong></li>
 </ul></div>
 
@@ -2923,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>November 7, 2024</aside>
+    <aside>November 13, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 50c4790cb..e93279869 100755
--- a/parse.js
+++ b/parse.js
@@ -842,7 +842,7 @@ function fixHighlights() {
   $(`code:contains(@debug(print_result=True))`).html(PARAMETRIZED_DECORATOR);
   $(`code:contains(print/str/repr([<obj>]))`).html(REPR_USE_CASES);
   $(`code:contains((self, a=None):)`).html(CONSTRUCTOR_OVERLOADING);
-  $(`code:contains(make_dataclass(\'<class_name>\')`).html(DATACLASS);
+  //$(`code:contains(make_dataclass(\'<class_name>\')`).html(DATACLASS);
   $(`code:contains(shutil.copy)`).html(SHUTIL_COPY);
   $(`code:contains(os.rename)`).html(OS_RENAME);
   $(`code:contains(\'<n>s\')`).html(STRUCT_FORMAT);

From ed30a30b7a801e3d364e56e0e86adbd5d4f52abf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 14 Nov 2024 13:57:51 +0100
Subject: [PATCH 002/186] List, Datetime, Operator

---
 README.md           | 18 +++++++++---------
 index.html          | 21 ++++++++++-----------
 pdf/remove_links.py |  2 +-
 3 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/README.md b/README.md
index d61ef649d..16b5295a3 100644
--- a/README.md
+++ b/README.md
@@ -50,15 +50,17 @@ List
 ```
 
 ```python
-sum_of_elements  = sum(<collection>)
+<el>  = max(<collection>)       # Returns largest element. Also max(<el_1>, ...).
+<num> = sum(<collection>)       # Returns sum of elements. Also math.prod(<coll>).
+```
+
+```python
 elementwise_sum  = [sum(pair) for pair in zip(list_a, list_b)]
 sorted_by_second = sorted(<collection>, key=lambda el: el[1])
 sorted_by_both   = sorted(<collection>, key=lambda el: (el[1], el[0]))
 flatter_list     = list(itertools.chain.from_iterable(<list>))
-product_of_elems = functools.reduce(lambda out, el: out * el, <collection>)
-list_of_chars    = list(<str>)
 ```
-* **For details about sorted(), min() and max() see [sortable](#sortable).**
+* **For details about sort(), sorted(), max() and min() see [sortable](#sortable).**
 * **Module [operator](#operator) provides functions itemgetter() and mul() that offer the same functionality as [lambda](#lambda) expressions above.**
 
 ```python
@@ -388,7 +390,6 @@ import re
 '\w' == '[a-zA-Z0-9_]'                            # Also [ª²³…]. Matches an alphanumeric or _.
 '\s' == '[ \t\n\r\f\v]'                           # Also [\x1c-\x1f…]. Matches a whitespace.
 ```
-
 * **By default, decimal characters, alphanumerics and whitespaces from all alphabets are matched unless `'flags=re.ASCII'` argument is used.**
 * **It restricts special sequence matches to `'[\x00-\x7f]'` (the first 128 characters) and also prevents `'\s'` from accepting `'[\x1c-\x1f]'` (file, table, row, and field separators).**
 * **Use a capital letter for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).**
@@ -605,7 +606,7 @@ import zoneinfo, dateutil.tz
 <DT> = datetime(year, month, day, hour=0)   # Also: `minute=0, second=0, microsecond=0, …`.
 <TD> = timedelta(weeks=0, days=0, hours=0)  # Also: `minutes=0, seconds=0, microseconds=0`.
 ```
-* **Aware `<a>` time and datetime objects have defined timezone, while naive `<n>` don't. If object is naive, it is presumed to be in the system's timezone!**
+* **Aware times and datetimes have defined timezone, while naive don't. If object is naive, it is presumed to be in the system's timezone!**
 * **`'fold=1'` means the second pass in case of time jumping back for one hour.**
 * **Timedelta normalizes arguments to ±days, seconds (< 86 400) and microseconds (< 1M). Its str() method returns `'[±D, ]H:MM:SS[.…]'` and total_seconds() a float of all seconds.**
 * **Use `'<D/DT>.weekday()'` to get the day of the week as an int, with Monday being 0.**
@@ -2185,9 +2186,8 @@ import operator as op
 
 ```python
 elementwise_sum  = map(op.add, list_a, list_b)
-sorted_by_second = sorted(<coll.>, key=op.itemgetter(1))
-sorted_by_both   = sorted(<coll.>, key=op.itemgetter(1, 0))
-product_of_elems = functools.reduce(op.mul, <collection>)
+sorted_by_second = sorted(<coll>, key=op.itemgetter(1))
+sorted_by_both   = sorted(<coll>, key=op.itemgetter(1, 0))
 first_element    = op.methodcaller('pop', 0)(<list>)
 ```
 * **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().**
diff --git a/index.html b/index.html
index 21d034499..74c262cec 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 13, 2024</aside>
+    <aside>November 14, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -114,16 +114,16 @@
 &lt;list&gt; = sorted(&lt;collection&gt;)   <span class="hljs-comment"># Returns new list with sorted elements.</span>
 &lt;iter&gt; = reversed(&lt;list&gt;)       <span class="hljs-comment"># Returns reversed iterator of elements.</span>
 </code></pre>
-<pre><code class="python language-python hljs">sum_of_elements  = sum(&lt;collection&gt;)
-elementwise_sum  = [sum(pair) <span class="hljs-keyword">for</span> pair <span class="hljs-keyword">in</span> zip(list_a, list_b)]
+<pre><code class="python language-python hljs">&lt;el&gt;  = max(&lt;collection&gt;)       <span class="hljs-comment"># Returns largest element. Also max(&lt;el_1&gt;, ...).</span>
+&lt;num&gt; = sum(&lt;collection&gt;)       <span class="hljs-comment"># Returns sum of elements. Also math.prod(&lt;coll&gt;).</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(&lt;collection&gt;, key=<span class="hljs-keyword">lambda</span> el: el[<span class="hljs-number">1</span>])
 sorted_by_both   = sorted(&lt;collection&gt;, key=<span class="hljs-keyword">lambda</span> el: (el[<span class="hljs-number">1</span>], el[<span class="hljs-number">0</span>]))
 flatter_list     = list(itertools.chain.from_iterable(&lt;list&gt;))
-product_of_elems = functools.reduce(<span class="hljs-keyword">lambda</span> out, el: out * el, &lt;collection&gt;)
-list_of_chars    = list(&lt;str&gt;)
 </code></pre>
 <ul>
-<li><strong>For details about sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong></li>
+<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> provides functions itemgetter() and mul() that offer the same functionality as <a href="#lambda">lambda</a> expressions above.</strong></li>
 </ul>
 <pre><code class="python language-python hljs">&lt;int&gt; = len(&lt;list&gt;)             <span class="hljs-comment"># Returns number of items. Also works on other collections.</span>
@@ -527,7 +527,7 @@
 &lt;TD&gt; = 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"># Also: `minutes=0, seconds=0, microseconds=0`.</span>
 </code></pre>
 <ul>
-<li><strong>Aware <code class="apache hljs"><span class="hljs-section">&lt;a&gt;</span></code> time and datetime objects have defined timezone, while naive <code class="apache hljs"><span class="hljs-section">&lt;n&gt;</span></code> don't. If object is naive, it is presumed to be in the system's timezone!</strong></li>
+<li><strong>Aware times and datetimes have defined timezone, while naive don't. If 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 for one hour.</strong></li>
 <li><strong>Timedelta normalizes arguments to ±days, seconds (&lt; 86 400) and microseconds (&lt; 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 all seconds.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'&lt;D/DT&gt;.weekday()'</span></code> to get the day of the week as an int, with Monday being 0.</strong></li>
@@ -1789,9 +1789,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;func&gt; = op.itemgetter/attrgetter/methodcaller(&lt;obj&gt; [, ...])  <span class="hljs-comment"># [index/key], .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(&lt;coll.&gt;, key=op.itemgetter(<span class="hljs-number">1</span>))
-sorted_by_both   = sorted(&lt;coll.&gt;, key=op.itemgetter(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>))
-product_of_elems = functools.reduce(op.mul, &lt;collection&gt;)
+sorted_by_second = sorted(&lt;coll&gt;, key=op.itemgetter(<span class="hljs-number">1</span>))
+sorted_by_both   = sorted(&lt;coll&gt;, key=op.itemgetter(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>))
 first_element    = op.methodcaller(<span class="hljs-string">'pop'</span>, <span class="hljs-number">0</span>)(&lt;list&gt;)
 </code></pre>
 <ul>
@@ -2924,7 +2923,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>November 13, 2024</aside>
+    <aside>November 14, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index 527d8d533..747ffb34d 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -7,7 +7,7 @@
 
 
 MATCHES = {
-    '<strong>For details about sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong>': '<strong>For details about sorted(), min() and max() see sortable (p. 16).</strong>',
+    '<strong>For details about sort(), sorted(), max() and min() see <a href="#sortable">sortable</a>.</strong>': '<strong>For details about sort(), sorted(), max() and min() see sortable (p. 16).</strong>',
     '<strong>Module <a href="#operator">operator</a> provides functions itemgetter() and mul() that offer the same functionality as <a href="#lambda">lambda</a> expressions above.</strong>': '<strong>Module \'operator\' (p. 31) provides functions itemgetter() and mul() that offer the same functionality as lambda expressions (p. 11) above.</strong>',
     '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its <a href="#class">repr()</a> method.</strong>': '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its repr() method.</strong>',
     '<strong>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>': '<strong>It can be any callable, but is usually implemented as a function that returns a closure.</strong>',

From fc564585d493f20ff8cd92f4445cd06175ea22d5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 14 Nov 2024 14:06:28 +0100
Subject: [PATCH 003/186] Updated pdf/README.md

---
 pdf/README.md | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pdf/README.md b/pdf/README.md
index 1a56493b0..6e806f125 100644
--- a/pdf/README.md
+++ b/pdf/README.md
@@ -14,8 +14,8 @@ Printing to PDF
 ### Normal PDF
 * Open `index.html` in text editor and first remove element `<p><br></p>` before the `<h1>Libraries</h1>`.
 * Then replace the index and footer with contents of `pdf/index_for_pdf.html` file and save.
-* Disable internet connection and open the file in Chromium version 108.0.5328.0 (later versions will render the site incorrectly after index is added) with 'Cache killer' extension enabled.
-* Right click on the border of the site and select inspect. Select `<body>` element under 'Elements' tab and change top margin from 16 to 0 and top padding from 16 to 5 in 'Styles' tab.
+* Disable internet connection and open Chromium version 108.0.5328.0 (later versions will render the site incorrectly after index is added). Right click anywhere in the window and choose 'inspect'. Go to 'Network' tab and check 'Disable Cache'. Open the `index.html` file while keeping the inspect window open.
+* Right click on the border of the site and select inspect. Select `<body>` element under 'Elements' tab and change top margin and top padding from 16 to 0 in 'Styles' tab.
 * Change brightness of comments by right clicking on one of them and selecting inspect. Then click on the rectangle that represents color and toggle the color space to HSLA by clicking on the button with two vertical arrows. Change lightness (L) percentage to 77%.
 * Change the brightness of text to 13%.
 * Select 'Print...' with destination 'Save as PDF', paper size 'A4', 'Default' margins (top 10mm, right 9.5mm, bottom 8mm and left 10mm), 'Default' scale and no headers and footers and save (the document should be 51 pages long with last page empty).
@@ -26,8 +26,8 @@ Printing to PDF
 * Change all links in text to normal text and add a page number in brackets like that: '(p. <page_num>)' by running './pdf/remove_links.py' (Links can be found with this regex: `<strong>.*a href.*</strong>`).
 * Open `index.html` in text editor and first remove element `<p><br></p>` before the `<h1>Libraries</h1>`.
 * Then replace the index and footer with contents of `pdf/index_for_pdf_print.html` file and save.
-* Disable internet connection and open the file in Chromium version 108.0.5328.0 (later versions will render the site incorrectly after index is added) with 'Cache killer' extension enabled.
-* Right click on the border of the site and select inspect. Select `<body>` element under 'Elements' tab and change top margin from 16 to 0 and top padding from 16 to 5 in 'Styles' tab.
+* Disable internet connection and open Chromium version 108.0.5328.0 (later versions will render the site incorrectly after index is added). Right click anywhere in the window and choose 'inspect'. Go to 'Network' tab and check 'Disable Cache'. Open the `index.html` file while keeping the inspect window open.
+* Right click on the border of the site and select inspect. Select `<body>` element under 'Elements' tab and change top margin and top padding from 16 to 0 in 'Styles' tab.
 * Change brightness of elements by right clicking on them and selecting inspect. Then click on the rectangle that represents color and toggle the color space to HSLA by clicking on the button with two vertical arrows.
 * Change lightness (L) percentage to:
 * 0% for the text.

From 523c5791172ae547c565a1056fa2cb71f75ebe5f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 14 Nov 2024 15:31:02 +0100
Subject: [PATCH 004/186] List

---
 README.md           | 2 +-
 index.html          | 2 +-
 pdf/remove_links.py | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 16b5295a3..e252bd4ac 100644
--- a/README.md
+++ b/README.md
@@ -60,7 +60,7 @@ sorted_by_second = sorted(<collection>, key=lambda el: el[1])
 sorted_by_both   = sorted(<collection>, key=lambda el: (el[1], el[0]))
 flatter_list     = list(itertools.chain.from_iterable(<list>))
 ```
-* **For details about sort(), sorted(), max() and min() see [sortable](#sortable).**
+* **For details about sort(), sorted(), min() and max() see [sortable](#sortable).**
 * **Module [operator](#operator) provides functions itemgetter() and mul() that offer the same functionality as [lambda](#lambda) expressions above.**
 
 ```python
diff --git a/index.html b/index.html
index 74c262cec..916bc4dea 100644
--- a/index.html
+++ b/index.html
@@ -123,7 +123,7 @@
 flatter_list     = list(itertools.chain.from_iterable(&lt;list&gt;))
 </code></pre>
 <ul>
-<li><strong>For details about sort(), sorted(), max() and min() see <a href="#sortable">sortable</a>.</strong></li>
+<li><strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong></li>
 <li><strong>Module <a href="#operator">operator</a> provides functions itemgetter() and mul() that offer the same functionality as <a href="#lambda">lambda</a> expressions above.</strong></li>
 </ul>
 <pre><code class="python language-python hljs">&lt;int&gt; = len(&lt;list&gt;)             <span class="hljs-comment"># Returns number of items. Also works on other collections.</span>
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index 747ffb34d..984c53a7e 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -7,7 +7,7 @@
 
 
 MATCHES = {
-    '<strong>For details about sort(), sorted(), max() and min() see <a href="#sortable">sortable</a>.</strong>': '<strong>For details about sort(), sorted(), max() and min() see sortable (p. 16).</strong>',
+    '<strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong>': '<strong>For details about sort(), sorted(), min() and max() see sortable (p. 16).</strong>',
     '<strong>Module <a href="#operator">operator</a> provides functions itemgetter() and mul() that offer the same functionality as <a href="#lambda">lambda</a> expressions above.</strong>': '<strong>Module \'operator\' (p. 31) provides functions itemgetter() and mul() that offer the same functionality as lambda expressions (p. 11) above.</strong>',
     '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its <a href="#class">repr()</a> method.</strong>': '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its repr() method.</strong>',
     '<strong>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>': '<strong>It can be any callable, but is usually implemented as a function that returns a closure.</strong>',

From 8292bc981e723bc1322312031c51aee0f9df2c64 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 17 Nov 2024 04:22:48 +0100
Subject: [PATCH 005/186] List

---
 README.md           |  7 ++++---
 index.html          | 11 ++++++-----
 pdf/remove_links.py |  3 ++-
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/README.md b/README.md
index e252bd4ac..561a24163 100644
--- a/README.md
+++ b/README.md
@@ -50,7 +50,7 @@ List
 ```
 
 ```python
-<el>  = max(<collection>)       # Returns largest element. Also max(<el_1>, ...).
+<el>  = max(<collection>)       # Returns largest element. Also min(<el_1>, ...).
 <num> = sum(<collection>)       # Returns sum of elements. Also math.prod(<coll>).
 ```
 
@@ -61,10 +61,11 @@ sorted_by_both   = sorted(<collection>, key=lambda el: (el[1], el[0]))
 flatter_list     = list(itertools.chain.from_iterable(<list>))
 ```
 * **For details about sort(), sorted(), min() and max() see [sortable](#sortable).**
-* **Module [operator](#operator) provides functions itemgetter() and mul() that offer the same functionality as [lambda](#lambda) expressions above.**
+* **Module [operator](#operator) has function itemgetter() that can replace listed [lambdas](#lambda).**
+* **This text uses the term 'collection' instead of 'iterable'. For rationale see [collection](#collection).**
 
 ```python
-<int> = len(<list>)             # Returns number of items. Also works on other collections.
+<int> = len(<list>)             # Returns number of items. Also works on dict, set and string.
 <int> = <list>.count(<el>)      # Returns number of occurrences. Also `if <el> in <coll>: ...`.
 <int> = <list>.index(<el>)      # Returns index of the first occurrence or raises ValueError.
 <el>  = <list>.pop()            # Removes and returns item from the end or at index if passed.
diff --git a/index.html b/index.html
index 916bc4dea..d086a8113 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 14, 2024</aside>
+    <aside>November 17, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -114,7 +114,7 @@
 &lt;list&gt; = sorted(&lt;collection&gt;)   <span class="hljs-comment"># Returns new list with sorted elements.</span>
 &lt;iter&gt; = reversed(&lt;list&gt;)       <span class="hljs-comment"># Returns reversed iterator of elements.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;el&gt;  = max(&lt;collection&gt;)       <span class="hljs-comment"># Returns largest element. Also max(&lt;el_1&gt;, ...).</span>
+<pre><code class="python language-python hljs">&lt;el&gt;  = max(&lt;collection&gt;)       <span class="hljs-comment"># Returns largest element. Also min(&lt;el_1&gt;, ...).</span>
 &lt;num&gt; = sum(&lt;collection&gt;)       <span class="hljs-comment"># Returns sum of elements. Also math.prod(&lt;coll&gt;).</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)]
@@ -124,9 +124,10 @@
 </code></pre>
 <ul>
 <li><strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong></li>
-<li><strong>Module <a href="#operator">operator</a> provides functions itemgetter() and mul() that offer the same functionality as <a href="#lambda">lambda</a> expressions above.</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 'iterable'. For rationale see <a href="#collection">collection</a>.</strong></li>
 </ul>
-<pre><code class="python language-python hljs">&lt;int&gt; = len(&lt;list&gt;)             <span class="hljs-comment"># Returns number of items. Also works on other collections.</span>
+<pre><code class="python language-python hljs">&lt;int&gt; = len(&lt;list&gt;)             <span class="hljs-comment"># Returns number of items. Also works on dict, set and string.</span>
 &lt;int&gt; = &lt;list&gt;.count(&lt;el&gt;)      <span class="hljs-comment"># Returns number of occurrences. Also `if &lt;el&gt; in &lt;coll&gt;: ...`.</span>
 &lt;int&gt; = &lt;list&gt;.index(&lt;el&gt;)      <span class="hljs-comment"># Returns index of the first occurrence or raises ValueError.</span>
 &lt;el&gt;  = &lt;list&gt;.pop()            <span class="hljs-comment"># Removes and returns item from the end or at index if passed.</span>
@@ -2923,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>November 14, 2024</aside>
+    <aside>November 17, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index 984c53a7e..e31507ed8 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -8,7 +8,8 @@
 
 MATCHES = {
     '<strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong>': '<strong>For details about sort(), sorted(), min() and max() see sortable (p. 16).</strong>',
-    '<strong>Module <a href="#operator">operator</a> provides functions itemgetter() and mul() that offer the same functionality as <a href="#lambda">lambda</a> expressions above.</strong>': '<strong>Module \'operator\' (p. 31) provides functions itemgetter() and mul() that offer the same functionality as lambda expressions (p. 11) above.</strong>',
+    '<strong>Module <a href="#operator">operator</a> has function itemgetter() that can replace listed <a href="#lambda">lambdas</a>.</strong>': '<strong>Module \'operator\' has function itemgetter() that can replace listed lambdas (p. 11, 31).</strong>',
+    '<strong>This text uses the term \'collection\' instead of \'iterable\'. For rationale see <a href="#collection">collection</a>.</strong>': '<strong>This text uses the term \'collection\' instead of \'iterable\'. For rationale see collection (p. 18).</strong>',
     '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its <a href="#class">repr()</a> method.</strong>': '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its repr() method.</strong>',
     '<strong>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>': '<strong>It can be any callable, but is usually implemented as a function that returns a closure.</strong>',
     '<strong>Hints are used by type checkers like <a href="https://pypi.org/project/mypy/">mypy</a>, data validation libraries such as <a href="https://pypi.org/project/pydantic/">Pydantic</a> and lately also by <a href="https://pypi.org/project/Cython/">Cython</a> compiler. However, they are not enforced by CPython interpreter.</strong>': '<strong>Hints are used by type checkers like mypy, data validation libraries such as Pydantic and lately also by Cython compiler. However, they are not enforced by CPython interpreter.</strong>',

From 81e02255db713d48e5c15cdd0b422231096f2c7c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 18 Nov 2024 22:34:50 +0100
Subject: [PATCH 006/186] Regex

---
 README.md  | 3 +--
 index.html | 7 +++----
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 561a24163..4cadf9b4c 100644
--- a/README.md
+++ b/README.md
@@ -391,8 +391,7 @@ import re
 '\w' == '[a-zA-Z0-9_]'                            # Also [ª²³…]. Matches an alphanumeric or _.
 '\s' == '[ \t\n\r\f\v]'                           # Also [\x1c-\x1f…]. Matches a whitespace.
 ```
-* **By default, decimal characters, alphanumerics and whitespaces from all alphabets are matched unless `'flags=re.ASCII'` argument is used.**
-* **It restricts special sequence matches to `'[\x00-\x7f]'` (the first 128 characters) and also prevents `'\s'` from accepting `'[\x1c-\x1f]'` (file, table, row, and field separators).**
+* **By default, decimal characters and alphanumerics from all alphabets are matched unless `'flags=re.ASCII'` is used. It restricts special sequence matches to the first 128 Unicode characters and also prevents `'\s'` from accepting `'\x1c'`, `'\x1d'`, `'\x1e'` and `'\x1f'` (the so-called information separators that divide text into files, tables, rows and fields).**
 * **Use a capital letter for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).**
 
 
diff --git a/index.html b/index.html
index d086a8113..efbc68d3b 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 17, 2024</aside>
+    <aside>November 18, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -360,8 +360,7 @@
 </code></pre></div>
 
 <ul>
-<li><strong>By default, decimal characters, alphanumerics and whitespaces from all alphabets are matched unless <code class="python hljs"><span class="hljs-string">'flags=re.ASCII'</span></code> argument is used.</strong></li>
-<li><strong>It restricts special sequence matches to <code class="python hljs"><span class="hljs-string">'[\x00-\x7f]'</span></code> (the first 128 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-\x1f]'</span></code> (file, table, row, and field separators).</strong></li>
+<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> (the so-called information separators that divide text into files, tables, rows and fields).</strong></li>
 <li><strong>Use a capital letter for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).</strong></li>
 </ul>
 <div><h2 id="format"><a href="#format" name="format">#</a>Format</h2><pre><code class="python hljs">&lt;str&gt; = <span class="hljs-string">f'<span class="hljs-subst">{&lt;el_1&gt;}</span>, <span class="hljs-subst">{&lt;el_2&gt;}</span>'</span>            <span class="hljs-comment"># Curly brackets can also contain expressions.</span>
@@ -2924,7 +2923,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>November 17, 2024</aside>
+    <aside>November 18, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 6974f6adc7bef663e6fcab2dfd9fa52179495513 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 19 Nov 2024 23:07:02 +0100
Subject: [PATCH 007/186] Paths, fixed two links

---
 README.md       |  6 +++---
 index.html      | 12 ++++++------
 parse.js        |  3 ++-
 web/script_2.js |  4 ++--
 4 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
index 4cadf9b4c..14617837f 100644
--- a/README.md
+++ b/README.md
@@ -14,7 +14,7 @@ Contents
 **&nbsp;&nbsp;&nbsp;** **4. System:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`Exit`](#exit)**__,__ **[`Print`](#print)**__,__ **[`Input`](#input)**__,__ **[`Command_Line_Arguments`](#command-line-arguments)**__,__ **[`Open`](#open)**__,__ **[`Path`](#paths)**__,__ **[`OS_Commands`](#os-commands)**__.__  
 **&nbsp;&nbsp;&nbsp;** **5. Data:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`JSON`](#json)**__,__ **[`Pickle`](#pickle)**__,__ **[`CSV`](#csv)**__,__ **[`SQLite`](#sqlite)**__,__ **[`Bytes`](#bytes)**__,__ **[`Struct`](#struct)**__,__ **[`Array`](#array)**__,__ **[`Memory_View`](#memory-view)**__,__ **[`Deque`](#deque)**__.__  
 **&nbsp;&nbsp;&nbsp;** **6. Advanced:** **&nbsp;&nbsp;&nbsp;**  **[`Threading`](#threading)**__,__ **[`Operator`](#operator)**__,__ **[`Match_Stmt`](#match-statement)**__,__ **[`Logging`](#logging)**__,__ **[`Introspection`](#introspection)**__,__ **[`Coroutines`](#coroutines)**__.__  
-**&nbsp;&nbsp;&nbsp;** **7. Libraries:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`Progress_Bar`](#progress-bar)**__,__ **[`Plot`](#plot)**__,__ **[`Table`](#table)**__,__ **[`Console_App`](#console-app)**__,__ **[`GUI`](#gui-app)**__,__ **[`Scraping`](#scraping)**__,__ **[`Web`](#web)**__,__ **[`Profile`](#profiling)**__.__  
+**&nbsp;&nbsp;&nbsp;** **7. Libraries:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`Progress_Bar`](#progress-bar)**__,__ **[`Plot`](#plot)**__,__ **[`Table`](#table)**__,__ **[`Console_App`](#console-app)**__,__ **[`GUI`](#gui-app)**__,__ **[`Scraping`](#scraping)**__,__ **[`Web`](#web-app)**__,__ **[`Profile`](#profiling)**__.__  
 **&nbsp;&nbsp;&nbsp;** **8. Multimedia:** **&nbsp;&nbsp;**  **[`NumPy`](#numpy)**__,__ **[`Image`](#image)**__,__ **[`Animation`](#animation)**__,__ **[`Audio`](#audio)**__,__ **[`Synthesizer`](#synthesizer)**__,__ **[`Pygame`](#pygame)**__,__ **[`Pandas`](#pandas)**__,__ **[`Plotly`](#plotly)**__.__
 
 
@@ -1583,7 +1583,7 @@ Open
 * **`'w+'` - Read and write. Deletes existing contents.**
 * **`'r+'` - Read and write from the start.**
 * **`'a+'` - Read and write from the end.**
-* **`'b'`  - Binary mode (`'rb'`, `'wb'`, `'xb'`, …)**
+* **`'b'`  - Binary mode (`'rb'`, `'wb'`, `'xb'`, …).**
 
 ### Exceptions
 * **`'FileNotFoundError'` can be raised when reading with `'r'` or `'r+'`.**
@@ -1661,7 +1661,7 @@ from pathlib import Path
 
 ```python
 <stat> = os.stat(<path>)            # Or: <DirEntry/Path>.stat()
-<num>  = <stat>.st_mtime/st_size/…  # Modification time, size in bytes, ...
+<num>  = <stat>.st_mtime/st_size/…  # Modification time, size in bytes, etc.
 ```
 
 ### DirEntry
diff --git a/index.html b/index.html
index efbc68d3b..bf6a0745f 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 18, 2024</aside>
+    <aside>November 19, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -87,7 +87,7 @@
     <strong><span class="hljs-string"><span class="hljs-string">'4. System'</span></span></strong>:      [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">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'</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. Advanced'</span></span></strong>:    [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],
-    <strong><span class="hljs-string"><span class="hljs-string">'7. Libraries'</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="#web">Web</a>, <a href="#profiling">Profile</a>],
+    <strong><span class="hljs-string"><span class="hljs-string">'7. Libraries'</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>
@@ -1340,7 +1340,7 @@
 <li><strong><code class="python hljs"><span class="hljs-string">'w+'</span></code> - Read and write. Deletes existing contents.</strong></li>
 <li><strong><code class="python hljs"><span class="hljs-string">'r+'</span></code> - Read and write from the start.</strong></li>
 <li><strong><code class="python hljs"><span class="hljs-string">'a+'</span></code> - Read and write from the end.</strong></li>
-<li><strong><code class="python hljs"><span class="hljs-string">'b'</span></code>  - Binary mode (<code class="python hljs"><span class="hljs-string">'rb'</span></code>, <code class="python hljs"><span class="hljs-string">'wb'</span></code>, <code class="python hljs"><span class="hljs-string">'xb'</span></code>, …)</strong></li>
+<li><strong><code class="python hljs"><span class="hljs-string">'b'</span></code>  - Binary mode (<code class="python hljs"><span class="hljs-string">'rb'</span></code>, <code class="python hljs"><span class="hljs-string">'wb'</span></code>, <code class="python hljs"><span class="hljs-string">'xb'</span></code>, …).</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> can be raised when writing with <code class="python hljs"><span class="hljs-string">'x'</span></code>.</strong></li>
@@ -1399,7 +1399,7 @@
 &lt;bool&gt; = os.path.isdir(&lt;path&gt;)      <span class="hljs-comment"># Or: &lt;DirEntry/Path&gt;.is_dir()</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;stat&gt; = os.stat(&lt;path&gt;)            <span class="hljs-comment"># Or: &lt;DirEntry/Path&gt;.stat()</span>
-&lt;num&gt;  = &lt;stat&gt;.st_mtime/st_size/…  <span class="hljs-comment"># Modification time, size in bytes, ...</span>
+&lt;num&gt;  = &lt;stat&gt;.st_mtime/st_size/…  <span class="hljs-comment"># Modification time, size in bytes, etc.</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">&lt;iter&gt; = os.scandir(path=<span class="hljs-string">'.'</span>)       <span class="hljs-comment"># Returns DirEntry objects located at the path.</span>
 &lt;str&gt;  = &lt;DirEntry&gt;.path            <span class="hljs-comment"># Returns the whole path as a string.</span>
@@ -2568,7 +2568,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     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="#displays-a-line-chart-of-total-coronavirus-deaths-per-million-grouped-by-continent">Plotly</a>.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pandas matplotlib</span>
+<div><h2 id="pandas"><a href="#pandas" name="pandas">#</a>Pandas</h2><p><strong>Data analysis library. For examples see <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">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>
 
@@ -2923,7 +2923,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>November 18, 2024</aside>
+    <aside>November 19, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index e93279869..2cd9e96e8 100755
--- a/parse.js
+++ b/parse.js
@@ -37,7 +37,7 @@ const TOC =
   '    <strong><span class="hljs-string">\'4. System\'</span></strong>:      [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">Command_Line_Arguments</a>, <a href="#open">Open</a>, <a href="#paths">Path</a>, <a href="#oscommands">OS_Commands</a>],\n' +
   '    <strong><span class="hljs-string">\'5. Data\'</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>],\n' +
   '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],\n' +
-  '    <strong><span class="hljs-string">\'7. Libraries\'</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="#web">Web</a>, <a href="#profiling">Profile</a>],\n' +
+  '    <strong><span class="hljs-string">\'7. Libraries\'</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>],\n' +
   '    <strong><span class="hljs-string">\'8. Multimedia\'</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>]\n' +
   '}\n' +
   '</code></pre>\n';
@@ -716,6 +716,7 @@ function getMd() {
   var readme = readme.replace("#semaphore-event-barrier", "#semaphoreeventbarrier");
   var readme = readme.replace("#semaphore-event-barrier", "#semaphoreeventbarrier");
   var readme = readme.replace("#dataframe-plot-encode-decode", "#dataframeplotencodedecode");
+  var readme = readme.replace("#displays-a-line-chart-of-total-coronavirus-deaths-per-million-grouped-by-continent", "#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent");
   const converter = new showdown.Converter();
   return converter.makeHtml(readme);
 }
diff --git a/web/script_2.js b/web/script_2.js
index 7484625a2..be1c1c7bf 100644
--- a/web/script_2.js
+++ b/web/script_2.js
@@ -6,7 +6,7 @@ const TOC =
   '    <strong><span class="hljs-string">\'4. System\'</span></strong>:      [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">Command_Line_Arguments</a>, <a href="#open">Open</a>, <a href="#paths">Path</a>, <a href="#oscommands">OS_Commands</a>],\n' +
   '    <strong><span class="hljs-string">\'5. Data\'</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>],\n' +
   '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],\n' +
-  '    <strong><span class="hljs-string">\'7. Libraries\'</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="#web">Web</a>, <a href="#profiling">Profile</a>],\n' +
+  '    <strong><span class="hljs-string">\'7. Libraries\'</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>],\n' +
   '    <strong><span class="hljs-string">\'8. Multimedia\'</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>]\n' +
   '}\n';
 
@@ -32,7 +32,7 @@ const TOC_MOBILE =
   '                       <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],\n' +
   '    <strong><span class="hljs-string">\'7. Libraries\'</span></strong>:   [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>,\n' +
   '                       <a href="#consoleapp">Console_App</a>, <a href="#guiapp">GUI_App</a>,\n' +
-  '                       <a href="#scraping">Scraping</a>, <a href="#web">Web</a>, <a href="#profiling">Profiling</a>],\n' +
+  '                       <a href="#scraping">Scraping</a>, <a href="#webapp">Web</a>, <a href="#profiling">Profiling</a>],\n' +
   '    <strong><span class="hljs-string">\'8. Multimedia\'</span></strong>:  [<a href="#numpy">NumPy</a>, <a href="#image">Image</a>, <a href="#animation">Animation</a>,\n' +
   '                       <a href="#audio">Audio</a>, <a href="#synthesizer">Synthesizer</a>,\n' +
   '                       <a href="#pygame">Pygame</a>, <a href="#pandas">Pandas</a>, <a href="#plotly">Plotly</a>]\n' +

From 4214842fe7aa9d1fcaaf70f20320c556a9cbe4cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 23 Nov 2024 18:37:26 +0100
Subject: [PATCH 008/186] Class, Json, SQLite, Image, Pandas

---
 README.md  | 64 ++++++++++++++++++++++++-------------------------
 index.html | 70 +++++++++++++++++++++++++++---------------------------
 2 files changed, 67 insertions(+), 67 deletions(-)

diff --git a/README.md b/README.md
index 14617837f..003051944 100644
--- a/README.md
+++ b/README.md
@@ -975,15 +975,15 @@ class MyClass:
     def get_class_name(cls):
         return cls.__name__
 ```
-* **Return value of str() should be readable and of repr() unambiguous.**
-* **If only repr() is defined, it will also be used for str().**
-* **Methods decorated with `'@staticmethod'` do not receive 'self' nor 'cls' as their first arg.**
 
 ```python
 >>> obj = MyClass(1)
 >>> obj.a, str(obj), repr(obj)
 (1, '1', 'MyClass(1)')
 ```
+* **Return value of str() should be readable and of repr() unambiguous.**
+* **If only repr() is defined, it will also be used for str().**
+* **Methods decorated with `'@staticmethod'` do not receive 'self' nor 'cls' as their first argument.**
 
 #### Expressions that call the str() method:
 ```python
@@ -1769,22 +1769,22 @@ JSON
 
 ```python
 import json
-<str>    = json.dumps(<object>)     # Converts object to JSON string.
-<object> = json.loads(<str>)        # Converts JSON string to object.
+<str>  = json.dumps(<list/dict>)    # Converts collection to JSON string.
+<coll> = json.loads(<str>)          # Converts JSON string to collection.
 ```
 
-### Read Object from JSON File
+### Read Collection from JSON File
 ```python
 def read_json_file(filename):
     with open(filename, encoding='utf-8') as file:
         return json.load(file)
 ```
 
-### Write Object to JSON File
+### Write Collection to JSON File
 ```python
-def write_to_json_file(filename, an_object):
+def write_to_json_file(filename, list_or_dict):
     with open(filename, 'w', encoding='utf-8') as file:
-        json.dump(an_object, file, ensure_ascii=False, indent=2)
+        json.dump(list_or_dict, file, ensure_ascii=False, indent=2)
 ```
 
 
@@ -1884,41 +1884,41 @@ def write_to_csv_file(filename, rows, mode='w', **csv_params):
 
 SQLite
 ------
-**A server-less database engine that stores each database into a separate file.**
+**A server-less database engine that stores each database into its own file.**
 
 ```python
 import sqlite3
-<conn> = sqlite3.connect(<path>)                # Opens existing or new file. Also ':memory:'.
-<conn>.close()                                  # Closes connection. Discards uncommitted data.
+<conn> = sqlite3.connect(<path>)               # Opens existing or new file. Also ':memory:'.
+<conn>.close()                                 # Closes connection. Discards uncommitted data.
 ```
 
 ### Read
 ```python
-<cursor> = <conn>.execute('<query>')            # Can raise a subclass of sqlite3.Error.
-<tuple>  = <cursor>.fetchone()                  # Returns next row. Also next(<cursor>).
-<list>   = <cursor>.fetchall()                  # Returns remaining rows. Also list(<cursor>).
+<cursor> = <conn>.execute('<query>')           # Can raise a subclass of sqlite3.Error.
+<tuple>  = <cursor>.fetchone()                 # Returns next row. Also next(<cursor>).
+<list>   = <cursor>.fetchall()                 # Returns remaining rows. Also list(<cursor>).
 ```
 
 ### Write
 ```python
-<conn>.execute('<query>')                       # Can raise a subclass of sqlite3.Error.
-<conn>.commit()                                 # Saves all changes since the last commit.
-<conn>.rollback()                               # Discards all changes since the last commit.
+<conn>.execute('<query>')                      # Can raise a subclass of sqlite3.Error.
+<conn>.commit()                                # Saves all changes since the last commit.
+<conn>.rollback()                              # Discards all changes since the last commit.
 ```
 
 #### Or:
 ```python
-with <conn>:                                    # Exits the block with commit() or rollback(),
-    <conn>.execute('<query>')                   # depending on whether any exception occurred.
+with <conn>:                                   # Exits the block with commit() or rollback(),
+    <conn>.execute('<query>')                  # depending on whether any exception occurred.
 ```
 
 ### Placeholders
 ```python
-<conn>.execute('<query>', <list/tuple>)         # Replaces '?'s in query with values.
-<conn>.execute('<query>', <dict/namedtuple>)    # Replaces ':<key>'s with values.
-<conn>.executemany('<query>', <coll_of_above>)  # Runs execute() multiple times.
+<conn>.execute('<query>', <list/tuple>)        # Replaces '?'s in query with values.
+<conn>.execute('<query>', <dict/namedtuple>)   # Replaces ':<key>'s with values.
+<conn>.executemany('<query>', <coll_of_coll>)  # Runs execute() multiple times.
 ```
-* **Passed values can be of type str, int, float, bytes, None or bool (stored as 1 or 0).**
+* **Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).**
 
 ### Example
 **Values are not actually saved in this example because `'conn.commit()'` is omitted!**
@@ -1936,10 +1936,10 @@ with <conn>:                                    # Exits the block with commit()
 ```python
 # $ pip3 install sqlalchemy
 from sqlalchemy import create_engine, text
-<engine> = create_engine('<url>')               # Url: 'dialect://user:password@host/dbname'.
-<conn>   = <engine>.connect()                   # Creates a connection. Also <conn>.close().
-<cursor> = <conn>.execute(text('<query>'), …)   # Replaces ':<key>'s with keyword arguments.
-with <conn>.begin(): ...                        # Exits the block with commit or rollback.
+<engine> = create_engine('<url>')              # Url: 'dialect://user:password@host/dbname'.
+<conn>   = <engine>.connect()                  # Creates a connection. Also <conn>.close().
+<cursor> = <conn>.execute(text('<query>'), …)  # Replaces ':<key>'s with keyword arguments.
+with <conn>.begin(): ...                       # Exits the block with commit or rollback.
 ```
 
 ```text
@@ -2832,9 +2832,9 @@ from PIL import ImageDraw
 <Draw>.point((x, y))                            # Draws a point. Truncates floats into ints.
 <Draw>.line((x1, y1, x2, y2 [, ...]))           # To get anti-aliasing use Image's resize().
 <Draw>.arc((x1, y1, x2, y2), deg1, deg2)        # Draws in clockwise dir. Also pieslice().
-<Draw>.rectangle((x1, y1, x2, y2))              # To rotate use Image's rotate() and paste().
+<Draw>.rectangle((x1, y1, x2, y2))              # Also rounded_rectangle(), regular_polygon().
 <Draw>.polygon((x1, y1, x2, y2, ...))           # Last point gets connected to the first.
-<Draw>.ellipse((x1, y1, x2, y2))                # Also rounded_rectangle(), regular_polygon().
+<Draw>.ellipse((x1, y1, x2, y2))                # To rotate use Image's rotate() and paste().
 <Draw>.text((x, y), <str>, font=<Font>)         # `<Font> = ImageFont.truetype(<path>, size)`
 ```
 * **Use `'fill=<color>'` to set the primary color.**
@@ -3340,7 +3340,7 @@ c  6  7
 +----------------+---------------+---------------+---------------+
 ```
 * **All methods operate on columns by default. Pass `'axis=1'` to process the rows instead.**
-* **Fifth result's columns are indexed with a multi-index. This means we need a tuple of column keys to specify a single column: `'<DF>.loc[row_k, (col_k_1, col_k_2)]'`.**
+* **Fifth result's columns are indexed with a multi-index. This means we need a tuple of column keys to specify a column: `'<DF>.loc[row_key, (col_key_1, col_key_2)]'`.**
 
 #### DataFrame — Multi-Index:
 ```python
@@ -3348,7 +3348,7 @@ c  6  7
 <DF>   = <DF>.xs(row_keys, level=<ints>)       # Rows that have first key on first level, etc.
 <DF>   = <DF>.set_index(col_keys)              # Combines multiple columns into a multi-index.
 <S/DF> = <DF>.stack/unstack(level=-1)          # Combines col keys with row keys or vice versa.
-<DF>   = <DF>.pivot_table(index=col_key/s, …)  # `columns=col_key/s, values=col_key/s`.
+<DF>   = <DF>.pivot_table(index=col_key/s, …)  # `columns=key/s, values=key/s, aggfunc='mean'`.
 ```
 
 #### DataFrame — Encode, Decode:
diff --git a/index.html b/index.html
index bf6a0745f..dd5177179 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 19, 2024</aside>
+    <aside>November 23, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -817,15 +817,15 @@
 </code></pre></div>
 
 
-<ul>
-<li><strong>Return value of str() should be readable and of repr() unambiguous.</strong></li>
-<li><strong>If only repr() is defined, it will also be used for str().</strong></li>
-<li><strong>Methods decorated with <code class="python hljs"><span class="hljs-string">'@staticmethod'</span></code> do not receive 'self' nor 'cls' as their first arg.</strong></li>
-</ul>
 <pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>obj = MyClass(<span class="hljs-number">1</span>)
 <span class="hljs-meta">&gt;&gt;&gt; </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>Return value of str() should be readable and of repr() unambiguous.</strong></li>
+<li><strong>If only repr() is defined, it will also be used for str().</strong></li>
+<li><strong>Methods decorated with <code class="python hljs"><span class="hljs-string">'@staticmethod'</span></code> do not receive 'self' nor 'cls' as their first argument.</strong></li>
+</ul>
 <div><h4 id="expressionsthatcallthestrmethod">Expressions that call the str() method:</h4><pre><code class="python language-python hljs">print(&lt;obj&gt;)
 <span class="hljs-string">f'<span class="hljs-subst">{&lt;obj&gt;}</span>'</span>
 logging.warning(&lt;obj&gt;)
@@ -1471,19 +1471,19 @@
 </code></pre></div>
 
 <div><h2 id="json"><a href="#json" name="json">#</a>JSON</h2><p><strong>Text file format for storing collections of strings and numbers.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> json
-&lt;str&gt;    = json.dumps(&lt;object&gt;)     <span class="hljs-comment"># Converts object to JSON string.</span>
-&lt;object&gt; = json.loads(&lt;str&gt;)        <span class="hljs-comment"># Converts JSON string to object.</span>
+&lt;str&gt;  = json.dumps(&lt;list/dict&gt;)    <span class="hljs-comment"># Converts collection to JSON string.</span>
+&lt;coll&gt; = json.loads(&lt;str&gt;)          <span class="hljs-comment"># Converts JSON string to collection.</span>
 </code></pre></div>
 
 
-<div><h3 id="readobjectfromjsonfile">Read Object 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>
+<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="writeobjecttojsonfile">Write Object 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, an_object)</span>:</span>
+<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, list_or_dict)</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(an_object, file, ensure_ascii=<span class="hljs-keyword">False</span>, indent=<span class="hljs-number">2</span>)
+        json.dump(list_or_dict, 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><p><strong>Binary file format for storing Python objects.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> pickle
@@ -1561,33 +1561,33 @@
         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 a separate file.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> sqlite3
-&lt;conn&gt; = sqlite3.connect(&lt;path&gt;)                <span class="hljs-comment"># Opens existing or new file. Also ':memory:'.</span>
-&lt;conn&gt;.close()                                  <span class="hljs-comment"># Closes connection. Discards uncommitted data.</span>
+<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
+&lt;conn&gt; = sqlite3.connect(&lt;path&gt;)               <span class="hljs-comment"># Opens existing or new file. Also ':memory:'.</span>
+&lt;conn&gt;.close()                                 <span class="hljs-comment"># Closes connection. Discards uncommitted data.</span>
 </code></pre></div>
 
 
-<div><h3 id="read-1">Read</h3><pre><code class="python language-python hljs">&lt;cursor&gt; = &lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)            <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span>
-&lt;tuple&gt;  = &lt;cursor&gt;.fetchone()                  <span class="hljs-comment"># Returns next row. Also next(&lt;cursor&gt;).</span>
-&lt;list&gt;   = &lt;cursor&gt;.fetchall()                  <span class="hljs-comment"># Returns remaining rows. Also list(&lt;cursor&gt;).</span>
+<div><h3 id="read-1">Read</h3><pre><code class="python language-python hljs">&lt;cursor&gt; = &lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)           <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span>
+&lt;tuple&gt;  = &lt;cursor&gt;.fetchone()                 <span class="hljs-comment"># Returns next row. Also next(&lt;cursor&gt;).</span>
+&lt;list&gt;   = &lt;cursor&gt;.fetchall()                 <span class="hljs-comment"># Returns remaining rows. Also list(&lt;cursor&gt;).</span>
 </code></pre></div>
 
-<div><h3 id="write-1">Write</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)                       <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span>
-&lt;conn&gt;.commit()                                 <span class="hljs-comment"># Saves all changes since the last commit.</span>
-&lt;conn&gt;.rollback()                               <span class="hljs-comment"># Discards all changes since the last commit.</span>
+<div><h3 id="write-1">Write</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)                      <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span>
+&lt;conn&gt;.commit()                                <span class="hljs-comment"># Saves all changes since the last commit.</span>
+&lt;conn&gt;.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> &lt;conn&gt;:                                    <span class="hljs-comment"># Exits the block with commit() or rollback(),</span>
-    &lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)                   <span class="hljs-comment"># depending on whether any exception occurred.</span>
+<div><h4 id="or">Or:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">with</span> &lt;conn&gt;:                                   <span class="hljs-comment"># Exits the block with commit() or rollback(),</span>
+    &lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)                  <span class="hljs-comment"># depending on whether any exception occurred.</span>
 </code></pre></div>
 
-<div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)         <span class="hljs-comment"># Replaces '?'s in query with values.</span>
-&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)    <span class="hljs-comment"># Replaces ':&lt;key&gt;'s with values.</span>
-&lt;conn&gt;.executemany(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;coll_of_above&gt;)  <span class="hljs-comment"># Runs execute() multiple times.</span>
+<div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)        <span class="hljs-comment"># Replaces '?'s in query with values.</span>
+&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces ':&lt;key&gt;'s with values.</span>
+&lt;conn&gt;.executemany(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;coll_of_coll&gt;)  <span class="hljs-comment"># Runs execute() multiple times.</span>
 </code></pre></div>
 
 <ul>
-<li><strong>Passed values can be of type str, int, float, bytes, None or bool (stored as 1 or 0).</strong></li>
+<li><strong>Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).</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">'conn.commit()'</span></code> is omitted!</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>conn = sqlite3.connect(<span class="hljs-string">'test.db'</span>)
 <span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height)'</span>)
@@ -1600,10 +1600,10 @@
 
 <div><h3 id="sqlalchemy">SQLAlchemy</h3><p><strong>Library for interacting with various DB systems via SQL, method chaining, or ORM.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install sqlalchemy</span>
 <span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> create_engine, text
-&lt;engine&gt; = create_engine(<span class="hljs-string">'&lt;url&gt;'</span>)               <span class="hljs-comment"># Url: 'dialect://user:password@host/dbname'.</span>
-&lt;conn&gt;   = &lt;engine&gt;.connect()                   <span class="hljs-comment"># Creates a connection. Also &lt;conn&gt;.close().</span>
-&lt;cursor&gt; = &lt;conn&gt;.execute(text(<span class="hljs-string">'&lt;query&gt;'</span>), …)   <span class="hljs-comment"># Replaces ':&lt;key&gt;'s with keyword arguments.</span>
-<span class="hljs-keyword">with</span> &lt;conn&gt;.begin(): ...                        <span class="hljs-comment"># Exits the block with commit or rollback.</span>
+&lt;engine&gt; = create_engine(<span class="hljs-string">'&lt;url&gt;'</span>)              <span class="hljs-comment"># Url: 'dialect://user:password@host/dbname'.</span>
+&lt;conn&gt;   = &lt;engine&gt;.connect()                  <span class="hljs-comment"># Creates a connection. Also &lt;conn&gt;.close().</span>
+&lt;cursor&gt; = &lt;conn&gt;.execute(text(<span class="hljs-string">'&lt;query&gt;'</span>), …)  <span class="hljs-comment"># Replaces ':&lt;key&gt;'s with keyword arguments.</span>
+<span class="hljs-keyword">with</span> &lt;conn&gt;.begin(): ...                       <span class="hljs-comment"># Exits the block with commit or rollback.</span>
 </code></pre></div>
 
 
@@ -2305,9 +2305,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;Draw&gt;.point((x, y))                            <span class="hljs-comment"># Draws a point. Truncates floats into ints.</span>
 &lt;Draw&gt;.line((x1, y1, x2, y2 [, ...]))           <span class="hljs-comment"># To get anti-aliasing use Image's resize().</span>
 &lt;Draw&gt;.arc((x1, y1, x2, y2), deg1, deg2)        <span class="hljs-comment"># Draws in clockwise dir. Also pieslice().</span>
-&lt;Draw&gt;.rectangle((x1, y1, x2, y2))              <span class="hljs-comment"># To rotate use Image's rotate() and paste().</span>
+&lt;Draw&gt;.rectangle((x1, y1, x2, y2))              <span class="hljs-comment"># Also rounded_rectangle(), regular_polygon().</span>
 &lt;Draw&gt;.polygon((x1, y1, x2, y2, ...))           <span class="hljs-comment"># Last point gets connected to the first.</span>
-&lt;Draw&gt;.ellipse((x1, y1, x2, y2))                <span class="hljs-comment"># Also rounded_rectangle(), regular_polygon().</span>
+&lt;Draw&gt;.ellipse((x1, y1, x2, y2))                <span class="hljs-comment"># To rotate use Image's rotate() and paste().</span>
 &lt;Draw&gt;.text((x, y), &lt;str&gt;, font=&lt;Font&gt;)         <span class="hljs-comment"># `&lt;Font&gt; = ImageFont.truetype(&lt;path&gt;, size)`</span>
 </code></pre></div>
 
@@ -2720,13 +2720,13 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <ul>
 <li><strong>All methods operate on columns by default. Pass <code class="python hljs"><span class="hljs-string">'axis=1'</span></code> to process the rows instead.</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 single column: <code class="python hljs"><span class="hljs-string">'&lt;DF&gt;.loc[row_k, (col_k_1, col_k_2)]'</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">'&lt;DF&gt;.loc[row_key, (col_key_1, col_key_2)]'</span></code>.</strong></li>
 </ul>
 <div><h4 id="dataframemultiindex">DataFrame — Multi-Index:</h4><pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt;.xs(row_key, level=&lt;int&gt;)         <span class="hljs-comment"># Rows with key on passed level of multi-index.</span>
 &lt;DF&gt;   = &lt;DF&gt;.xs(row_keys, level=&lt;ints&gt;)       <span class="hljs-comment"># Rows that have first key on first level, etc.</span>
 &lt;DF&gt;   = &lt;DF&gt;.set_index(col_keys)              <span class="hljs-comment"># Combines multiple columns into a multi-index.</span>
 &lt;S/DF&gt; = &lt;DF&gt;.stack/unstack(level=<span class="hljs-number">-1</span>)          <span class="hljs-comment"># Combines col keys with row keys or vice versa.</span>
-&lt;DF&gt;   = &lt;DF&gt;.pivot_table(index=col_key/s, …)  <span class="hljs-comment"># `columns=col_key/s, values=col_key/s`.</span>
+&lt;DF&gt;   = &lt;DF&gt;.pivot_table(index=col_key/s, …)  <span class="hljs-comment"># `columns=key/s, values=key/s, aggfunc='mean'`.</span>
 </code></pre></div>
 
 <div><h4 id="dataframeencodedecode">DataFrame — Encode, Decode:</h4><pre><code class="python language-python hljs">&lt;DF&gt; = pd.read_json/html(<span class="hljs-string">'&lt;str/path/url&gt;'</span>)     <span class="hljs-comment"># Run `$ pip3 install beautifulsoup4 lxml`.</span>
@@ -2923,7 +2923,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>November 19, 2024</aside>
+    <aside>November 23, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From e8d514bcc263583fbb657eb4049ec07e15285505 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 26 Nov 2024 13:11:03 +0100
Subject: [PATCH 009/186] Array

---
 README.md  | 10 +++++-----
 index.html | 14 +++++++-------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
index 003051944..f9225644f 100644
--- a/README.md
+++ b/README.md
@@ -2046,15 +2046,15 @@ from array import array
 ```
 
 ```python
-<array> = array('<typecode>', <coll_of_nums>)  # Array from collection of numbers.
-<array> = array('<typecode>', <bytes>)         # Copies bytes to array's memory.
-<array> = array('<typecode>', <array>)         # Treats array as a sequence of numbers.
-<array>.fromfile(<file>, n_items)              # Appends items from the binary file.
+<array> = array('<typecode>', <coll_of_nums>)  # Creates array from collection of numbers.
+<array> = array('<typecode>', <bytes>)         # Writes passed bytes to array's memory.
+<array> = array('<typecode>', <array>)         # Treats passed array as a sequence of numbers.
+<array>.fromfile(<file>, n_items)              # Appends file's contents to array's memory.
 ```
 
 ```python
 <bytes> = bytes(<array>)                       # Returns a copy of array's memory.
-<file>.write(<array>)                          # Writes array's memory to binary file.
+<file>.write(<array>)                          # Writes array's memory to the binary file.
 ```
 
 
diff --git a/index.html b/index.html
index dd5177179..6efb6735f 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 23, 2024</aside>
+    <aside>November 26, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1689,13 +1689,13 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 
-<pre><code class="python language-python hljs">&lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;coll_of_nums&gt;)  <span class="hljs-comment"># Array from collection of numbers.</span>
-&lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;bytes&gt;)         <span class="hljs-comment"># Copies bytes to array's memory.</span>
-&lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;array&gt;)         <span class="hljs-comment"># Treats array as a sequence of numbers.</span>
-&lt;array&gt;.fromfile(&lt;file&gt;, n_items)              <span class="hljs-comment"># Appends items from the binary file.</span>
+<pre><code class="python language-python hljs">&lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;coll_of_nums&gt;)  <span class="hljs-comment"># Creates array from collection of numbers.</span>
+&lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;bytes&gt;)         <span class="hljs-comment"># Writes passed bytes to array's memory.</span>
+&lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;array&gt;)         <span class="hljs-comment"># Treats passed array as a sequence of numbers.</span>
+&lt;array&gt;.fromfile(&lt;file&gt;, n_items)              <span class="hljs-comment"># Appends file's contents to array's memory.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;bytes&gt; = bytes(&lt;array&gt;)                       <span class="hljs-comment"># Returns a copy of array's memory.</span>
-&lt;file&gt;.write(&lt;array&gt;)                          <span class="hljs-comment"># Writes array's memory to binary file.</span>
+&lt;file&gt;.write(&lt;array&gt;)                          <span class="hljs-comment"># Writes array's memory to the 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">&lt;mview&gt; = memoryview(&lt;bytes/bytearray/array&gt;)  <span class="hljs-comment"># Immutable if bytes is passed, else mutable.</span>
 &lt;obj&gt;   = &lt;mview&gt;[index]                       <span class="hljs-comment"># Returns int or float. Bytes if format is 'c'.</span>
@@ -2923,7 +2923,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>November 23, 2024</aside>
+    <aside>November 26, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 9488b1dfa774b054f5e7d3bf65fe14e364da3d3a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 26 Nov 2024 13:23:32 +0100
Subject: [PATCH 010/186] Pandas

---
 README.md  | 6 +++---
 index.html | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index f9225644f..32661666f 100644
--- a/README.md
+++ b/README.md
@@ -1918,7 +1918,7 @@ with <conn>:                                   # Exits the block with commit() o
 <conn>.execute('<query>', <dict/namedtuple>)   # Replaces ':<key>'s with values.
 <conn>.executemany('<query>', <coll_of_coll>)  # Runs execute() multiple times.
 ```
-* **Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).**
+* **Passed values can be of type str, int, float, bytes, None, or bool (stored as 0 or 1).**
 
 ### Example
 **Values are not actually saved in this example because `'conn.commit()'` is omitted!**
@@ -2835,7 +2835,7 @@ from PIL import ImageDraw
 <Draw>.rectangle((x1, y1, x2, y2))              # Also rounded_rectangle(), regular_polygon().
 <Draw>.polygon((x1, y1, x2, y2, ...))           # Last point gets connected to the first.
 <Draw>.ellipse((x1, y1, x2, y2))                # To rotate use Image's rotate() and paste().
-<Draw>.text((x, y), <str>, font=<Font>)         # `<Font> = ImageFont.truetype(<path>, size)`
+<Draw>.text((x, y), <str>, font=<Font>)         # `<Font> = ImageFont.truetype(<path>, size)`.
 ```
 * **Use `'fill=<color>'` to set the primary color.**
 * **Use `'width=<int>'` to set the width of lines or contours.**
@@ -3348,7 +3348,7 @@ c  6  7
 <DF>   = <DF>.xs(row_keys, level=<ints>)       # Rows that have first key on first level, etc.
 <DF>   = <DF>.set_index(col_keys)              # Combines multiple columns into a multi-index.
 <S/DF> = <DF>.stack/unstack(level=-1)          # Combines col keys with row keys or vice versa.
-<DF>   = <DF>.pivot_table(index=col_key/s, …)  # `columns=key/s, values=key/s, aggfunc='mean'`.
+<DF>   = <DF>.pivot_table(index=col_key/s)     # `columns=key/s, values=key/s, aggfunc='mean'`.
 ```
 
 #### DataFrame — Encode, Decode:
diff --git a/index.html b/index.html
index 6efb6735f..f206fa810 100644
--- a/index.html
+++ b/index.html
@@ -1587,7 +1587,7 @@
 </code></pre></div>
 
 <ul>
-<li><strong>Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).</strong></li>
+<li><strong>Passed values can be of type str, int, float, bytes, None, or bool (stored as 0 or 1).</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">'conn.commit()'</span></code> is omitted!</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>conn = sqlite3.connect(<span class="hljs-string">'test.db'</span>)
 <span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height)'</span>)
@@ -2308,7 +2308,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;Draw&gt;.rectangle((x1, y1, x2, y2))              <span class="hljs-comment"># Also rounded_rectangle(), regular_polygon().</span>
 &lt;Draw&gt;.polygon((x1, y1, x2, y2, ...))           <span class="hljs-comment"># Last point gets connected to the first.</span>
 &lt;Draw&gt;.ellipse((x1, y1, x2, y2))                <span class="hljs-comment"># To rotate use Image's rotate() and paste().</span>
-&lt;Draw&gt;.text((x, y), &lt;str&gt;, font=&lt;Font&gt;)         <span class="hljs-comment"># `&lt;Font&gt; = ImageFont.truetype(&lt;path&gt;, size)`</span>
+&lt;Draw&gt;.text((x, y), &lt;str&gt;, font=&lt;Font&gt;)         <span class="hljs-comment"># `&lt;Font&gt; = ImageFont.truetype(&lt;path&gt;, size)`.</span>
 </code></pre></div>
 
 <ul>
@@ -2726,7 +2726,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;DF&gt;   = &lt;DF&gt;.xs(row_keys, level=&lt;ints&gt;)       <span class="hljs-comment"># Rows that have first key on first level, etc.</span>
 &lt;DF&gt;   = &lt;DF&gt;.set_index(col_keys)              <span class="hljs-comment"># Combines multiple columns into a multi-index.</span>
 &lt;S/DF&gt; = &lt;DF&gt;.stack/unstack(level=<span class="hljs-number">-1</span>)          <span class="hljs-comment"># Combines col keys with row keys or vice versa.</span>
-&lt;DF&gt;   = &lt;DF&gt;.pivot_table(index=col_key/s, …)  <span class="hljs-comment"># `columns=key/s, values=key/s, aggfunc='mean'`.</span>
+&lt;DF&gt;   = &lt;DF&gt;.pivot_table(index=col_key/s)     <span class="hljs-comment"># `columns=key/s, values=key/s, aggfunc='mean'`.</span>
 </code></pre></div>
 
 <div><h4 id="dataframeencodedecode">DataFrame — Encode, Decode:</h4><pre><code class="python language-python hljs">&lt;DF&gt; = pd.read_json/html(<span class="hljs-string">'&lt;str/path/url&gt;'</span>)     <span class="hljs-comment"># Run `$ pip3 install beautifulsoup4 lxml`.</span>

From 04e5b869bad49f5f7a877bd1b158af0d5ac65c47 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 26 Nov 2024 16:48:25 +0100
Subject: [PATCH 011/186] Introspection

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 32661666f..926e2c42a 100644
--- a/README.md
+++ b/README.md
@@ -2294,7 +2294,7 @@ CRITICAL:my_module:Running out of disk space.
 Introspection
 -------------
 ```python
-<list> = dir()                      # List of of local names (including functions and classes).
+<list> = dir()                      # List of local names (variables, funcs, classes, modules).
 <dict> = vars()                     # Dict of local names and their objects. Also locals().
 <dict> = globals()                  # Dict of global names (for instance '__builtin__' module).
 ```
@@ -2304,7 +2304,7 @@ Introspection
 <dict> = vars(<obj>)                # Returns dict of writable attributes. Also <obj>.__dict__.
 <bool> = hasattr(<obj>, '<name>')   # Checks if object possesses attribute with passed name.
 value  = getattr(<obj>, '<name>')   # Returns object's attribute or raises AttributeError.
-setattr(<obj>, '<name>', value)     # Sets attribute. Only works on objects with __dict__.
+setattr(<obj>, '<name>', value)     # Sets attribute. Only works on objects with __dict__ attr.
 delattr(<obj>, '<name>')            # Deletes attribute from __dict__. Also `del <obj>.<name>`.
 ```
 
diff --git a/index.html b/index.html
index f206fa810..56e24fc4a 100644
--- a/index.html
+++ b/index.html
@@ -1877,7 +1877,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 2023-02-07 23:21:01,430 CRITICAL:my_module:Running out of disk space.
 </code></pre></div>
 
-<div><h2 id="introspection"><a href="#introspection" name="introspection">#</a>Introspection</h2><pre><code class="python language-python hljs">&lt;list&gt; = dir()                      <span class="hljs-comment"># List of of local names (including functions and classes).</span>
+<div><h2 id="introspection"><a href="#introspection" name="introspection">#</a>Introspection</h2><pre><code class="python language-python hljs">&lt;list&gt; = dir()                      <span class="hljs-comment"># List of local names (variables, funcs, classes, modules).</span>
 &lt;dict&gt; = vars()                     <span class="hljs-comment"># Dict of local names and their objects. Also locals().</span>
 &lt;dict&gt; = globals()                  <span class="hljs-comment"># Dict of global names (for instance '__builtin__' module).</span>
 </code></pre></div>
@@ -1886,7 +1886,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;dict&gt; = vars(&lt;obj&gt;)                <span class="hljs-comment"># Returns dict of writable attributes. Also &lt;obj&gt;.__dict__.</span>
 &lt;bool&gt; = hasattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>)   <span class="hljs-comment"># Checks if object possesses attribute with passed name.</span>
 value  = getattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>)   <span class="hljs-comment"># Returns object's attribute or raises AttributeError.</span>
-setattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>, value)     <span class="hljs-comment"># Sets attribute. Only works on objects with __dict__.</span>
+setattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>, value)     <span class="hljs-comment"># Sets attribute. Only works on objects with __dict__ attr.</span>
 delattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>)            <span class="hljs-comment"># Deletes attribute from __dict__. Also `del &lt;obj&gt;.&lt;name&gt;`.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Sig&gt;  = inspect.signature(&lt;func&gt;)  <span class="hljs-comment"># Returns function's Signature object. Can accept a class.</span>

From 37d367ce4e316176c3b5ab644490e5c1d5bfcbb0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 27 Nov 2024 02:27:50 +0100
Subject: [PATCH 012/186] Introspection

---
 README.md  | 4 ++--
 index.html | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 926e2c42a..460fce69f 100644
--- a/README.md
+++ b/README.md
@@ -2296,7 +2296,7 @@ Introspection
 ```python
 <list> = dir()                      # List of local names (variables, funcs, classes, modules).
 <dict> = vars()                     # Dict of local names and their objects. Also locals().
-<dict> = globals()                  # Dict of global names (for instance '__builtin__' module).
+<dict> = globals()                  # Dict of global names and their objects, e.g. __builtin__.
 ```
 
 ```python
@@ -2309,7 +2309,7 @@ delattr(<obj>, '<name>')            # Deletes attribute from __dict__. Also `del
 ```
 
 ```python
-<Sig>  = inspect.signature(<func>)  # Returns function's Signature object. Can accept a class.
+<Sig>  = inspect.signature(<func>)  # Returns a Signature object of the passed function.
 <dict> = <Sig>.parameters           # Returns dict of Parameters. Also <Sig>.return_annotation.
 <memb> = <Param>.kind               # Returns ParameterKind member (Parameter.KEYWORD_ONLY, …).
 <type> = <Param>.annotation         # Returns Parameter.empty if missing. Also <Param>.default.
diff --git a/index.html b/index.html
index 56e24fc4a..47e63ce1b 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 26, 2024</aside>
+    <aside>November 27, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1879,7 +1879,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <div><h2 id="introspection"><a href="#introspection" name="introspection">#</a>Introspection</h2><pre><code class="python language-python hljs">&lt;list&gt; = dir()                      <span class="hljs-comment"># List of local names (variables, funcs, classes, modules).</span>
 &lt;dict&gt; = vars()                     <span class="hljs-comment"># Dict of local names and their objects. Also locals().</span>
-&lt;dict&gt; = globals()                  <span class="hljs-comment"># Dict of global names (for instance '__builtin__' module).</span>
+&lt;dict&gt; = globals()                  <span class="hljs-comment"># Dict of global names and their objects, e.g. __builtin__.</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs">&lt;list&gt; = dir(&lt;obj&gt;)                 <span class="hljs-comment"># Returns names of all object's attributes (incl. methods).</span>
@@ -1889,7 +1889,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 setattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>, value)     <span class="hljs-comment"># Sets attribute. Only works on objects with __dict__ attr.</span>
 delattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>)            <span class="hljs-comment"># Deletes attribute from __dict__. Also `del &lt;obj&gt;.&lt;name&gt;`.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;Sig&gt;  = inspect.signature(&lt;func&gt;)  <span class="hljs-comment"># Returns function's Signature object. Can accept a class.</span>
+<pre><code class="python language-python hljs">&lt;Sig&gt;  = inspect.signature(&lt;func&gt;)  <span class="hljs-comment"># Returns a Signature object of the passed function.</span>
 &lt;dict&gt; = &lt;Sig&gt;.parameters           <span class="hljs-comment"># Returns dict of Parameters. Also &lt;Sig&gt;.return_annotation.</span>
 &lt;memb&gt; = &lt;Param&gt;.kind               <span class="hljs-comment"># Returns ParameterKind member (Parameter.KEYWORD_ONLY, …).</span>
 &lt;type&gt; = &lt;Param&gt;.annotation         <span class="hljs-comment"># Returns Parameter.empty if missing. Also &lt;Param&gt;.default.</span>
@@ -2923,7 +2923,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>November 26, 2024</aside>
+    <aside>November 27, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 5be47abfb0719460f38d55b676f6e48a5899df7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 27 Nov 2024 04:03:09 +0100
Subject: [PATCH 013/186] Image, Plotly

---
 README.md  | 6 +++---
 index.html | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 460fce69f..ddb7db00f 100644
--- a/README.md
+++ b/README.md
@@ -2777,7 +2777,7 @@ from PIL import Image
 <Image> = Image.open(<path>)                    # Identifies format based on file's contents.
 <Image> = <Image>.convert('<mode>')             # Converts image to the new mode (see Modes).
 <Image>.save(<path>)                            # Selects format based on extension (PNG/JPG…).
-<Image>.show()                                  # Opens image in the default preview app.
+<Image>.show()                                  # Displays image in default preview app.
 ```
 
 ```python
@@ -2795,7 +2795,7 @@ from PIL import Image
 
 ```python
 <array> = np.array(<Image>)                     # Creates a 2d/3d NumPy array from the image.
-<Image> = Image.fromarray(np.uint8(<array>))    # Use `<array>.clip(0, 255)` to clip values.
+<Image> = Image.fromarray(np.uint8(<array>))    # Use <array>.clip(0, 255) to clip the values.
 ```
 
 ### Modes
@@ -3422,7 +3422,7 @@ import plotly.express as px, pandas as pd
 ```python
 <Fig> = px.line(<DF>, x=col_key, y=col_key)            # Or: px.line(x=<list>, y=<list>)
 <Fig>.update_layout(margin=dict(t=0, r=0, b=0, l=0))   # Also `paper_bgcolor='rgb(0, 0, 0)'`.
-<Fig>.write_html/json/image('<path>')                  # Also <Fig>.show().
+<Fig>.write_html/json/image('<path>')                  # <Fig>.show() displays the plot.
 ```
 
 ```python
diff --git a/index.html b/index.html
index 47e63ce1b..40a99063a 100644
--- a/index.html
+++ b/index.html
@@ -2263,7 +2263,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;Image&gt; = Image.open(&lt;path&gt;)                    <span class="hljs-comment"># Identifies format based on file's contents.</span>
 &lt;Image&gt; = &lt;Image&gt;.convert(<span class="hljs-string">'&lt;mode&gt;'</span>)             <span class="hljs-comment"># Converts image to the new mode (see Modes).</span>
 &lt;Image&gt;.save(&lt;path&gt;)                            <span class="hljs-comment"># Selects format based on extension (PNG/JPG…).</span>
-&lt;Image&gt;.show()                                  <span class="hljs-comment"># Opens image in the default preview app.</span>
+&lt;Image&gt;.show()                                  <span class="hljs-comment"># Displays image in default preview app.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;int/tup&gt; = &lt;Image&gt;.getpixel((x, y))            <span class="hljs-comment"># Returns pixel's value (its color).</span>
 &lt;ImgCore&gt; = &lt;Image&gt;.getdata()                   <span class="hljs-comment"># Returns a flattened view of pixel values.</span>
@@ -2275,7 +2275,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;Image&gt; = &lt;Enhance&gt;.enhance(&lt;float&gt;)            <span class="hljs-comment"># Use ImageEnhance.&lt;name&gt;(&lt;Image&gt;) for Enhance.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;array&gt; = np.array(&lt;Image&gt;)                     <span class="hljs-comment"># Creates a 2d/3d NumPy array from the image.</span>
-&lt;Image&gt; = Image.fromarray(np.uint8(&lt;array&gt;))    <span class="hljs-comment"># Use `&lt;array&gt;.clip(0, 255)` to clip values.</span>
+&lt;Image&gt; = Image.fromarray(np.uint8(&lt;array&gt;))    <span class="hljs-comment"># Use &lt;array&gt;.clip(0, 255) to clip the values.</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 an int between 0 and 255.</strong></li>
@@ -2782,7 +2782,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <pre><code class="python language-python hljs">&lt;Fig&gt; = px.line(&lt;DF&gt;, x=col_key, y=col_key)            <span class="hljs-comment"># Or: px.line(x=&lt;list&gt;, y=&lt;list&gt;)</span>
 &lt;Fig&gt;.update_layout(margin=dict(t=<span class="hljs-number">0</span>, r=<span class="hljs-number">0</span>, b=<span class="hljs-number">0</span>, l=<span class="hljs-number">0</span>))   <span class="hljs-comment"># Also `paper_bgcolor='rgb(0, 0, 0)'`.</span>
-&lt;Fig&gt;.write_html/json/image(<span class="hljs-string">'&lt;path&gt;'</span>)                  <span class="hljs-comment"># Also &lt;Fig&gt;.show().</span>
+&lt;Fig&gt;.write_html/json/image(<span class="hljs-string">'&lt;path&gt;'</span>)                  <span class="hljs-comment"># &lt;Fig&gt;.show() displays the plot.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Fig&gt; = px.area/bar/box(&lt;DF&gt;, x=col_key, y=col_key)    <span class="hljs-comment"># Also `color=col_key`.</span>
 &lt;Fig&gt; = px.scatter(&lt;DF&gt;, x=col_key, y=col_key)         <span class="hljs-comment"># Also `color/size/symbol=col_key`.</span>

From bfb81f191a62a96d0333c02ecd477835f846bfac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 27 Nov 2024 16:10:47 +0100
Subject: [PATCH 014/186] Dictionary

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index ddb7db00f..e3e7817f5 100644
--- a/README.md
+++ b/README.md
@@ -82,8 +82,8 @@ Dictionary
 ```
 
 ```python
-<view> = <dict>.keys()                          # Coll. of keys that reflects changes.
-<view> = <dict>.values()                        # Coll. of values that reflects changes.
+<view> = <dict>.keys()                          # Collection of keys that reflects changes.
+<view> = <dict>.values()                        # Collection of values that reflects changes.
 <view> = <dict>.items()                         # Coll. of key-value tuples that reflects chgs.
 ```
 
diff --git a/index.html b/index.html
index 40a99063a..fd0294084 100644
--- a/index.html
+++ b/index.html
@@ -138,8 +138,8 @@
 <div><h2 id="dictionary"><a href="#dictionary" name="dictionary">#</a>Dictionary</h2><pre><code class="python language-python hljs">&lt;dict&gt; = {key_1: val_1, key_2: val_2, ...}      <span class="hljs-comment"># Use `&lt;dict&gt;[key]` to get or set the value.</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs">&lt;view&gt; = &lt;dict&gt;.keys()                          <span class="hljs-comment"># Coll. of keys that reflects changes.</span>
-&lt;view&gt; = &lt;dict&gt;.values()                        <span class="hljs-comment"># Coll. of values that reflects changes.</span>
+<pre><code class="python language-python hljs">&lt;view&gt; = &lt;dict&gt;.keys()                          <span class="hljs-comment"># Collection of keys that reflects changes.</span>
+&lt;view&gt; = &lt;dict&gt;.values()                        <span class="hljs-comment"># Collection of values that reflects changes.</span>
 &lt;view&gt; = &lt;dict&gt;.items()                         <span class="hljs-comment"># Coll. of key-value tuples that reflects chgs.</span>
 </code></pre>
 <pre><code class="python language-python hljs">value  = &lt;dict&gt;.get(key, default=<span class="hljs-keyword">None</span>)          <span class="hljs-comment"># Returns default if key is missing.</span>

From 5b21977ac1032d918d5ab76eed3d2f58c9b8b3af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 27 Nov 2024 17:55:32 +0100
Subject: [PATCH 015/186] Operator, Plot, Audio

---
 README.md  | 14 +++++++-------
 index.html | 14 +++++++-------
 parse.js   |  8 +-------
 3 files changed, 15 insertions(+), 21 deletions(-)

diff --git a/README.md b/README.md
index e3e7817f5..f5dc7ee1c 100644
--- a/README.md
+++ b/README.md
@@ -2168,7 +2168,7 @@ with <lock>:                                   # Enters the block by calling acq
 
 Operator
 --------
-**Module of functions that provide the functionality of operators. Functions are ordered by operator precedence, starting with least binding.**
+**Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.**
 ```python
 import operator as op
 ```
@@ -2419,9 +2419,9 @@ import matplotlib.pyplot as plt
 plt.plot/bar/scatter(x_data, y_data [, label=<str>])  # Also plt.plot(y_data).
 plt.legend()                                          # Adds a legend.
 plt.title/xlabel/ylabel(<str>)                        # Adds a title or label.
-plt.savefig(<path>)                                   # Saves the figure.
-plt.show()                                            # Displays the figure.
-plt.clf()                                             # Clears the figure.
+plt.savefig(<path>)                                   # Saves the plot.
+plt.show()                                            # Displays the plot.
+plt.clf()                                             # Clears the plot.
 ```
 
 
@@ -2876,7 +2876,7 @@ import wave
 <int>   = <Wave>.getnchannels()       # Returns number of samples per frame.
 <int>   = <Wave>.getsampwidth()       # Returns number of bytes per sample.
 <tuple> = <Wave>.getparams()          # Returns namedtuple of all parameters.
-<bytes> = <Wave>.readframes(nframes)  # Returns next n frames. All if -1.
+<bytes> = <Wave>.readframes(nframes)  # Returns next n frames (-1 returns all).
 ```
 
 ```python
@@ -2913,7 +2913,7 @@ def read_wav_file(filename):
         p = file.getparams()
         frames = file.readframes(-1)
     bytes_samples = (frames[i : i + p.sampwidth] for i in range(0, len(frames), p.sampwidth))
-    return [get_int(b) / pow(2, p.sampwidth * 8 - 1) for b in bytes_samples], p
+    return [get_int(b) / pow(2, (p.sampwidth * 8) - 1) for b in bytes_samples], p
 ```
 
 ### Write Float Samples to WAV File
@@ -2922,7 +2922,7 @@ def write_to_wav_file(filename, samples_f, p=None, nchannels=1, sampwidth=2, fra
     def get_bytes(a_float):
         a_float = max(-1, min(1 - 2e-16, a_float))
         a_float += p.sampwidth == 1
-        a_float *= pow(2, p.sampwidth * 8 - 1)
+        a_float *= pow(2, (p.sampwidth * 8) - 1)
         return int(a_float).to_bytes(p.sampwidth, 'little', signed=(p.sampwidth != 1))
     if p is None:
         p = wave._wave_params(nchannels, sampwidth, framerate, 0, 'NONE', 'not compressed')
diff --git a/index.html b/index.html
index fd0294084..307c470b7 100644
--- a/index.html
+++ b/index.html
@@ -1775,7 +1775,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.</strong></li>
 <li><strong>ProcessPoolExecutor provides true parallelism but: everything sent to/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="operator"><a href="#operator" name="operator">#</a>Operator</h2><p><strong>Module of functions that provide the functionality of operators. Functions are ordered by operator precedence, starting with least binding.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> operator <span class="hljs-keyword">as</span> op
+<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 ordered and grouped by operator precedence from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.</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>
 
 
@@ -1979,9 +1979,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 plt.plot/bar/scatter(x_data, y_data [, label=&lt;str&gt;])  <span class="hljs-comment"># Also plt.plot(y_data).</span>
 plt.legend()                                          <span class="hljs-comment"># Adds a legend.</span>
 plt.title/xlabel/ylabel(&lt;str&gt;)                        <span class="hljs-comment"># Adds a title or label.</span>
-plt.savefig(&lt;path&gt;)                                   <span class="hljs-comment"># Saves the figure.</span>
-plt.show()                                            <span class="hljs-comment"># Displays the figure.</span>
-plt.clf()                                             <span class="hljs-comment"># Clears the figure.</span>
+plt.savefig(&lt;path&gt;)                                   <span class="hljs-comment"># Saves the plot.</span>
+plt.show()                                            <span class="hljs-comment"># Displays the plot.</span>
+plt.clf()                                             <span class="hljs-comment"># Clears the plot.</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>
@@ -2342,7 +2342,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;int&gt;   = &lt;Wave&gt;.getnchannels()       <span class="hljs-comment"># Returns number of samples per frame.</span>
 &lt;int&gt;   = &lt;Wave&gt;.getsampwidth()       <span class="hljs-comment"># Returns number of bytes per sample.</span>
 &lt;tuple&gt; = &lt;Wave&gt;.getparams()          <span class="hljs-comment"># Returns namedtuple of all parameters.</span>
-&lt;bytes&gt; = &lt;Wave&gt;.readframes(nframes)  <span class="hljs-comment"># Returns next n frames. All if -1.</span>
+&lt;bytes&gt; = &lt;Wave&gt;.readframes(nframes)  <span class="hljs-comment"># Returns next n frames (-1 returns all).</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Wave&gt; = wave.open(<span class="hljs-string">'&lt;path&gt;'</span>, <span class="hljs-string">'wb'</span>)    <span class="hljs-comment"># Creates/truncates a file for writing.</span>
 &lt;Wave&gt;.setframerate(&lt;int&gt;)            <span class="hljs-comment"># Pass 44100 for CD, 48000 for video.</span>
@@ -2374,14 +2374,14 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
         p = file.getparams()
         frames = file.readframes(<span class="hljs-number">-1</span>)
     bytes_samples = (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> bytes_samples], p
+    <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> bytes_samples], 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>, framerate=<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))
         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>)
+        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, framerate, <span class="hljs-number">0</span>, <span class="hljs-string">'NONE'</span>, <span class="hljs-string">'not compressed'</span>)
diff --git a/parse.js b/parse.js
index 2cd9e96e8..cc1725ef6 100755
--- a/parse.js
+++ b/parse.js
@@ -84,11 +84,6 @@ const CONSTRUCTOR_OVERLOADING =
   '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a=<span class="hljs-keyword">None</span>)</span>:</span>\n' +
   '        self.a = a\n';
 
-const DATACLASS =
-  '&lt;class&gt; = make_dataclass(<span class="hljs-string">\'&lt;class_name&gt;\'</span>, &lt;coll_of_attribute_names&gt;)\n' +
-  '&lt;class&gt; = make_dataclass(<span class="hljs-string">\'&lt;class_name&gt;\'</span>, &lt;coll_of_tuples&gt;)\n' +
-  '&lt;tuple&gt; = (<span class="hljs-string">\'&lt;attr_name&gt;\'</span>, &lt;type&gt; [, &lt;default_value&gt;])';
-
 const SHUTIL_COPY =
   'shutil.copy(from, to)               <span class="hljs-comment"># Copies the file. \'to\' can exist or be a dir.</span>\n' +
   'shutil.copy2(from, to)              <span class="hljs-comment"># Also copies creation and modification time.</span>\n' +
@@ -221,7 +216,7 @@ const AUDIO_1 =
   '    <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>\n' +
   '        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))\n' +
   '        a_float += p.sampwidth == <span class="hljs-number">1</span>\n' +
-  '        a_float *= pow(<span class="hljs-number">2</span>, p.sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>)\n' +
+  '        a_float *= pow(<span class="hljs-number">2</span>, (p.sampwidth * <span class="hljs-number">8</span>) - <span class="hljs-number">1</span>)\n' +
   '        <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>))\n' +
   '    <span class="hljs-keyword">if</span> p <span class="hljs-keyword">is</span> <span class="hljs-keyword">None</span>:\n' +
   '        p = wave._wave_params(nchannels, sampwidth, framerate, <span class="hljs-number">0</span>, <span class="hljs-string">\'NONE\'</span>, <span class="hljs-string">\'not compressed\'</span>)\n' +
@@ -843,7 +838,6 @@ function fixHighlights() {
   $(`code:contains(@debug(print_result=True))`).html(PARAMETRIZED_DECORATOR);
   $(`code:contains(print/str/repr([<obj>]))`).html(REPR_USE_CASES);
   $(`code:contains((self, a=None):)`).html(CONSTRUCTOR_OVERLOADING);
-  //$(`code:contains(make_dataclass(\'<class_name>\')`).html(DATACLASS);
   $(`code:contains(shutil.copy)`).html(SHUTIL_COPY);
   $(`code:contains(os.rename)`).html(OS_RENAME);
   $(`code:contains(\'<n>s\')`).html(STRUCT_FORMAT);

From 3d9699ce336f0e8e3dc75d192a2d3faab777f4e5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 27 Nov 2024 19:54:47 +0100
Subject: [PATCH 016/186] Moved Threading in front of Coroutines

---
 README.md                    | 138 +++++++++++++++++------------------
 index.html                   | 110 ++++++++++++++--------------
 parse.js                     |   3 +-
 pdf/index_for_pdf.html       |  26 +++----
 pdf/index_for_pdf_print.html |  26 +++----
 pdf/remove_links.py          |   5 +-
 web/script_2.js              |   8 +-
 7 files changed, 157 insertions(+), 159 deletions(-)

diff --git a/README.md b/README.md
index f5dc7ee1c..81a9f2d06 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ Contents
 **&nbsp;&nbsp;&nbsp;** **3. Syntax:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`Args`](#arguments)**__,__ **[`Inline`](#inline)**__,__ **[`Import`](#imports)**__,__ **[`Decorator`](#decorator)**__,__ **[`Class`](#class)**__,__ **[`Duck_Types`](#duck-types)**__,__ **[`Enum`](#enum)**__,__ **[`Exception`](#exceptions)**__.__  
 **&nbsp;&nbsp;&nbsp;** **4. System:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`Exit`](#exit)**__,__ **[`Print`](#print)**__,__ **[`Input`](#input)**__,__ **[`Command_Line_Arguments`](#command-line-arguments)**__,__ **[`Open`](#open)**__,__ **[`Path`](#paths)**__,__ **[`OS_Commands`](#os-commands)**__.__  
 **&nbsp;&nbsp;&nbsp;** **5. Data:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`JSON`](#json)**__,__ **[`Pickle`](#pickle)**__,__ **[`CSV`](#csv)**__,__ **[`SQLite`](#sqlite)**__,__ **[`Bytes`](#bytes)**__,__ **[`Struct`](#struct)**__,__ **[`Array`](#array)**__,__ **[`Memory_View`](#memory-view)**__,__ **[`Deque`](#deque)**__.__  
-**&nbsp;&nbsp;&nbsp;** **6. Advanced:** **&nbsp;&nbsp;&nbsp;**  **[`Threading`](#threading)**__,__ **[`Operator`](#operator)**__,__ **[`Match_Stmt`](#match-statement)**__,__ **[`Logging`](#logging)**__,__ **[`Introspection`](#introspection)**__,__ **[`Coroutines`](#coroutines)**__.__  
+**&nbsp;&nbsp;&nbsp;** **6. Advanced:** **&nbsp;&nbsp;&nbsp;**  **[`Operator`](#operator)**__,__ **[`Match_Stmt`](#match-statement)**__,__ **[`Logging`](#logging)**__,__ **[`Introspection`](#introspection)**__,__ **[`Threading`](#threading)**__,__ **[`Coroutines`](#coroutines)**__.__  
 **&nbsp;&nbsp;&nbsp;** **7. Libraries:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`Progress_Bar`](#progress-bar)**__,__ **[`Plot`](#plot)**__,__ **[`Table`](#table)**__,__ **[`Console_App`](#console-app)**__,__ **[`GUI`](#gui-app)**__,__ **[`Scraping`](#scraping)**__,__ **[`Web`](#web-app)**__,__ **[`Profile`](#profiling)**__.__  
 **&nbsp;&nbsp;&nbsp;** **8. Multimedia:** **&nbsp;&nbsp;**  **[`NumPy`](#numpy)**__,__ **[`Image`](#image)**__,__ **[`Animation`](#animation)**__,__ **[`Audio`](#audio)**__,__ **[`Synthesizer`](#synthesizer)**__,__ **[`Pygame`](#pygame)**__,__ **[`Pandas`](#pandas)**__,__ **[`Plotly`](#plotly)**__.__
 
@@ -2086,7 +2086,7 @@ Memory View
 
 Deque
 -----
-**A thread-safe list with efficient appends and pops from either side. Pronounced "deck".**
+**List with efficient appends and pops from either side. Pronounced "deck".**
 
 ```python
 from collections import deque
@@ -2101,71 +2101,6 @@ from collections import deque
 ```
 
 
-Threading
----------
-**CPython interpreter can only run a single thread at a time. Using multiple threads won't result in a faster execution, unless at least one of the threads contains an I/O operation.**
-```python
-from threading import Thread, Lock, RLock, Semaphore, Event, Barrier
-from concurrent.futures import ThreadPoolExecutor, as_completed
-```
-
-### Thread
-```python
-<Thread> = Thread(target=<function>)           # Use `args=<collection>` to set the arguments.
-<Thread>.start()                               # Starts the thread. Also <Thread>.is_alive().
-<Thread>.join()                                # Waits for the thread to finish.
-```
-* **Use `'kwargs=<dict>'` to pass keyword arguments to the function.**
-* **Use `'daemon=True'`, or the program will not be able to exit while the thread is alive.**
-
-### Lock
-```python
-<lock> = Lock/RLock()                          # RLock can only be released by acquirer.
-<lock>.acquire()                               # Waits for the lock to be available.
-<lock>.release()                               # Makes the lock available again.
-```
-
-#### Or:
-```python
-with <lock>:                                   # Enters the block by calling acquire() and
-    ...                                        # exits it with release(), even on error.
-```
-
-### Semaphore, Event, Barrier
-```python
-<Semaphore> = Semaphore(value=1)               # Lock that can be acquired by 'value' threads.
-<Event>     = Event()                          # Method wait() blocks until set() is called.
-<Barrier>   = Barrier(n_times)                 # Wait() blocks until it's called n_times.
-```
-
-### Queue
-```python
-<Queue> = queue.Queue(maxsize=0)               # A thread-safe first-in-first-out queue.
-<Queue>.put(<el>)                              # Blocks until queue stops being full.
-<Queue>.put_nowait(<el>)                       # Raises queue.Full exception if full.
-<el> = <Queue>.get()                           # Blocks until queue stops being empty.
-<el> = <Queue>.get_nowait()                    # Raises queue.Empty exception if empty.
-```
-
-### Thread Pool Executor
-```python
-<Exec> = ThreadPoolExecutor(max_workers=None)  # Or: `with ThreadPoolExecutor() as <name>: ...`
-<iter> = <Exec>.map(<func>, <args_1>, ...)     # Multithreaded and non-lazy map(). Keeps order.
-<Futr> = <Exec>.submit(<func>, <arg_1>, ...)   # Creates a thread and returns its Future obj.
-<Exec>.shutdown()                              # Blocks until all threads finish executing.
-```
-
-```python
-<bool> = <Future>.done()                       # Checks if the thread has finished executing.
-<obj>  = <Future>.result(timeout=None)         # Waits for thread to finish and returns result.
-<bool> = <Future>.cancel()                     # Cancels or returns False if running/finished.
-<iter> = as_completed(<coll_of_Futures>)       # `next(<iter>)` returns next completed Future.
-```
-* **Map() and as\_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called/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 threads are done.**
-* **Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.**
-* **ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be [pickable](#pickle), queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via `'if __name__ == "__main__": ...'`.**
-
-
 Operator
 --------
 **Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.**
@@ -2316,6 +2251,71 @@ delattr(<obj>, '<name>')            # Deletes attribute from __dict__. Also `del
 ```
 
 
+Threading
+---------
+**CPython interpreter can only run a single thread at a time. Using multiple threads won't result in a faster execution, unless at least one of the threads contains an I/O operation.**
+```python
+from threading import Thread, Lock, RLock, Semaphore, Event, Barrier
+from concurrent.futures import ThreadPoolExecutor, as_completed
+```
+
+### Thread
+```python
+<Thread> = Thread(target=<function>)           # Use `args=<collection>` to set the arguments.
+<Thread>.start()                               # Starts the thread. Also <Thread>.is_alive().
+<Thread>.join()                                # Waits for the thread to finish.
+```
+* **Use `'kwargs=<dict>'` to pass keyword arguments to the function.**
+* **Use `'daemon=True'`, or the program will not be able to exit while the thread is alive.**
+
+### Lock
+```python
+<lock> = Lock/RLock()                          # RLock can only be released by acquirer.
+<lock>.acquire()                               # Waits for the lock to be available.
+<lock>.release()                               # Makes the lock available again.
+```
+
+#### Or:
+```python
+with <lock>:                                   # Enters the block by calling acquire() and
+    ...                                        # exits it with release(), even on error.
+```
+
+### Semaphore, Event, Barrier
+```python
+<Semaphore> = Semaphore(value=1)               # Lock that can be acquired by 'value' threads.
+<Event>     = Event()                          # Method wait() blocks until set() is called.
+<Barrier>   = Barrier(n_times)                 # Wait() blocks until it's called n_times.
+```
+
+### Queue
+```python
+<Queue> = queue.Queue(maxsize=0)               # A thread-safe first-in-first-out queue.
+<Queue>.put(<el>)                              # Blocks until queue stops being full.
+<Queue>.put_nowait(<el>)                       # Raises queue.Full exception if full.
+<el> = <Queue>.get()                           # Blocks until queue stops being empty.
+<el> = <Queue>.get_nowait()                    # Raises queue.Empty exception if empty.
+```
+
+### Thread Pool Executor
+```python
+<Exec> = ThreadPoolExecutor(max_workers=None)  # Or: `with ThreadPoolExecutor() as <name>: ...`
+<iter> = <Exec>.map(<func>, <args_1>, ...)     # Multithreaded and non-lazy map(). Keeps order.
+<Futr> = <Exec>.submit(<func>, <arg_1>, ...)   # Creates a thread and returns its Future obj.
+<Exec>.shutdown()                              # Blocks until all threads finish executing.
+```
+
+```python
+<bool> = <Future>.done()                       # Checks if the thread has finished executing.
+<obj>  = <Future>.result(timeout=None)         # Waits for thread to finish and returns result.
+<bool> = <Future>.cancel()                     # Cancels or returns False if running/finished.
+<iter> = as_completed(<coll_of_Futures>)       # `next(<iter>)` returns next completed Future.
+```
+* **Map() and as\_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called/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 threads are done.**
+* **Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.**
+* **ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be [pickable](#pickle), queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via `'if __name__ == "__main__": ...'`.**
+
+
 Coroutines
 ----------
 * **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 use as much memory.**
@@ -2553,7 +2553,7 @@ import flask as fl
 
 ```python
 app = fl.Flask(__name__)                   # Returns the app object. Put at the top.
-app.run(host=None, port=None, debug=None)  # Or: $ flask --app FILE run [--ARG[=VAL] …]
+app.run(host=None, port=None, debug=None)  # Or: $ flask --app FILE run [--ARG[=VAL]]…
 ```
 * **Starts the app at `'http://localhost:5000'`. Use `'host="0.0.0.0"'` to run externally.**
 * **Install a WSGI server like [Waitress](https://flask.palletsprojects.com/en/latest/deploying/waitress/) and a HTTP server such as [Nginx](https://flask.palletsprojects.com/en/latest/deploying/nginx/) for better security.**
@@ -3146,7 +3146,7 @@ if __name__ == '__main__':
 
 Pandas
 ------
-**Data analysis library. For examples see [Plotly](#displays-a-line-chart-of-total-coronavirus-deaths-per-million-grouped-by-continent).**
+**Data analysis library. For examples see [Plotly](#plotly).**
 
 ```python
 # $ pip3 install pandas matplotlib
diff --git a/index.html b/index.html
index 307c470b7..75852dcb6 100644
--- a/index.html
+++ b/index.html
@@ -86,7 +86,7 @@
     <strong><span class="hljs-string"><span class="hljs-string">'3. Syntax'</span></span></strong>:      [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>],
     <strong><span class="hljs-string"><span class="hljs-string">'4. System'</span></span></strong>:      [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">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'</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. Advanced'</span></span></strong>:    [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],
+    <strong><span class="hljs-string"><span class="hljs-string">'6. Advanced'</span></span></strong>:    [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],
     <strong><span class="hljs-string"><span class="hljs-string">'7. Libraries'</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>]
 }
@@ -1714,7 +1714,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;str&gt;   = str(&lt;mview&gt;, <span class="hljs-string">'utf-8'</span>)                <span class="hljs-comment"># Treats memoryview as a bytes object.</span>
 &lt;str&gt;   = &lt;mview&gt;.hex()                        <span class="hljs-comment"># Returns hex pairs. Accepts `sep=&lt;str&gt;`.</span>
 </code></pre>
-<div><h2 id="deque"><a href="#deque" name="deque">#</a>Deque</h2><p><strong>A thread-safe list with efficient appends and pops from either side. Pronounced "deck".</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> deque
+<div><h2 id="deque"><a href="#deque" name="deque">#</a>Deque</h2><p><strong>List with efficient appends and pops from either side. Pronounced "deck".</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>
 
 
@@ -1724,57 +1724,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;deque&gt;.rotate(n=<span class="hljs-number">1</span>)                            <span class="hljs-comment"># Last element becomes first.</span>
 &lt;el&gt; = &lt;deque&gt;.popleft()                       <span class="hljs-comment"># Raises IndexError if deque is empty.</span>
 </code></pre>
-<div><h2 id="threading"><a href="#threading" name="threading">#</a>Threading</h2><p><strong>CPython interpreter can only run a single thread at a time. Using multiple threads won't result in a faster execution, unless at least one of the threads contains an I/O operation.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> threading <span class="hljs-keyword">import</span> Thread, Lock, RLock, Semaphore, Event, Barrier
-<span class="hljs-keyword">from</span> concurrent.futures <span class="hljs-keyword">import</span> ThreadPoolExecutor, as_completed
-</code></pre></div>
-
-
-<div><h3 id="thread">Thread</h3><pre><code class="python language-python hljs">&lt;Thread&gt; = Thread(target=&lt;function&gt;)           <span class="hljs-comment"># Use `args=&lt;collection&gt;` to set the arguments.</span>
-&lt;Thread&gt;.start()                               <span class="hljs-comment"># Starts the thread. Also &lt;Thread&gt;.is_alive().</span>
-&lt;Thread&gt;.join()                                <span class="hljs-comment"># Waits for the thread to finish.</span>
-</code></pre></div>
-
-<ul>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'kwargs=&lt;dict&gt;'</span></code> to pass keyword arguments to the function.</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'daemon=True'</span></code>, or the program will not be able to exit while the thread is alive.</strong></li>
-</ul>
-<div><h3 id="lock">Lock</h3><pre><code class="python language-python hljs">&lt;lock&gt; = Lock/RLock()                          <span class="hljs-comment"># RLock can only be released by acquirer.</span>
-&lt;lock&gt;.acquire()                               <span class="hljs-comment"># Waits for the lock to be available.</span>
-&lt;lock&gt;.release()                               <span class="hljs-comment"># Makes the lock available 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> &lt;lock&gt;:                                   <span class="hljs-comment"># Enters the block by calling acquire() and</span>
-    ...                                        <span class="hljs-comment"># exits it with release(), even on error.</span>
-</code></pre></div>
-
-<div><h3 id="semaphoreeventbarrier">Semaphore, Event, Barrier</h3><pre><code class="python language-python hljs">&lt;Semaphore&gt; = Semaphore(value=<span class="hljs-number">1</span>)               <span class="hljs-comment"># Lock that can be acquired by 'value' threads.</span>
-&lt;Event&gt;     = Event()                          <span class="hljs-comment"># Method wait() blocks until set() is called.</span>
-&lt;Barrier&gt;   = Barrier(n_times)                 <span class="hljs-comment"># Wait() blocks until it's called n_times.</span>
-</code></pre></div>
-
-<div><h3 id="queue">Queue</h3><pre><code class="python language-python hljs">&lt;Queue&gt; = queue.Queue(maxsize=<span class="hljs-number">0</span>)               <span class="hljs-comment"># A thread-safe first-in-first-out queue.</span>
-&lt;Queue&gt;.put(&lt;el&gt;)                              <span class="hljs-comment"># Blocks until queue stops being full.</span>
-&lt;Queue&gt;.put_nowait(&lt;el&gt;)                       <span class="hljs-comment"># Raises queue.Full exception if full.</span>
-&lt;el&gt; = &lt;Queue&gt;.get()                           <span class="hljs-comment"># Blocks until queue stops being empty.</span>
-&lt;el&gt; = &lt;Queue&gt;.get_nowait()                    <span class="hljs-comment"># Raises queue.Empty exception if empty.</span>
-</code></pre></div>
-
-<div><h3 id="threadpoolexecutor">Thread Pool Executor</h3><pre><code class="python language-python hljs">&lt;Exec&gt; = ThreadPoolExecutor(max_workers=<span class="hljs-keyword">None</span>)  <span class="hljs-comment"># Or: `with ThreadPoolExecutor() as &lt;name&gt;: ...`</span>
-&lt;iter&gt; = &lt;Exec&gt;.map(&lt;func&gt;, &lt;args_1&gt;, ...)     <span class="hljs-comment"># Multithreaded and non-lazy map(). Keeps order.</span>
-&lt;Futr&gt; = &lt;Exec&gt;.submit(&lt;func&gt;, &lt;arg_1&gt;, ...)   <span class="hljs-comment"># Creates a thread and returns its Future obj.</span>
-&lt;Exec&gt;.shutdown()                              <span class="hljs-comment"># Blocks until all threads finish executing.</span>
-</code></pre></div>
-
-<pre><code class="python language-python hljs">&lt;bool&gt; = &lt;Future&gt;.done()                       <span class="hljs-comment"># Checks if the thread has finished executing.</span>
-&lt;obj&gt;  = &lt;Future&gt;.result(timeout=<span class="hljs-keyword">None</span>)         <span class="hljs-comment"># Waits for thread to finish and returns result.</span>
-&lt;bool&gt; = &lt;Future&gt;.cancel()                     <span class="hljs-comment"># Cancels or returns False if running/finished.</span>
-&lt;iter&gt; = as_completed(&lt;coll_of_Futures&gt;)       <span class="hljs-comment"># `next(&lt;iter&gt;)` returns next completed Future.</span>
-</code></pre>
-<ul>
-<li><strong>Map() and as_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called/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 threads are done.</strong></li>
-<li><strong>Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.</strong></li>
-<li><strong>ProcessPoolExecutor provides true parallelism but: everything sent to/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="operator"><a href="#operator" name="operator">#</a>Operator</h2><p><strong>Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.</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>
 
@@ -1894,6 +1843,57 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;memb&gt; = &lt;Param&gt;.kind               <span class="hljs-comment"># Returns ParameterKind member (Parameter.KEYWORD_ONLY, …).</span>
 &lt;type&gt; = &lt;Param&gt;.annotation         <span class="hljs-comment"># Returns Parameter.empty if missing. Also &lt;Param&gt;.default.</span>
 </code></pre>
+<div><h2 id="threading"><a href="#threading" name="threading">#</a>Threading</h2><p><strong>CPython interpreter can only run a single thread at a time. Using multiple threads won't result in a faster execution, unless at least one of the threads contains an I/O operation.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> threading <span class="hljs-keyword">import</span> Thread, Lock, RLock, Semaphore, Event, Barrier
+<span class="hljs-keyword">from</span> concurrent.futures <span class="hljs-keyword">import</span> ThreadPoolExecutor, as_completed
+</code></pre></div>
+
+
+<div><h3 id="thread">Thread</h3><pre><code class="python language-python hljs">&lt;Thread&gt; = Thread(target=&lt;function&gt;)           <span class="hljs-comment"># Use `args=&lt;collection&gt;` to set the arguments.</span>
+&lt;Thread&gt;.start()                               <span class="hljs-comment"># Starts the thread. Also &lt;Thread&gt;.is_alive().</span>
+&lt;Thread&gt;.join()                                <span class="hljs-comment"># Waits for the thread to finish.</span>
+</code></pre></div>
+
+<ul>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'kwargs=&lt;dict&gt;'</span></code> to pass keyword arguments to the function.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'daemon=True'</span></code>, or the program will not be able to exit while the thread is alive.</strong></li>
+</ul>
+<div><h3 id="lock">Lock</h3><pre><code class="python language-python hljs">&lt;lock&gt; = Lock/RLock()                          <span class="hljs-comment"># RLock can only be released by acquirer.</span>
+&lt;lock&gt;.acquire()                               <span class="hljs-comment"># Waits for the lock to be available.</span>
+&lt;lock&gt;.release()                               <span class="hljs-comment"># Makes the lock available 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> &lt;lock&gt;:                                   <span class="hljs-comment"># Enters the block by calling acquire() and</span>
+    ...                                        <span class="hljs-comment"># exits it with release(), even on error.</span>
+</code></pre></div>
+
+<div><h3 id="semaphoreeventbarrier">Semaphore, Event, Barrier</h3><pre><code class="python language-python hljs">&lt;Semaphore&gt; = Semaphore(value=<span class="hljs-number">1</span>)               <span class="hljs-comment"># Lock that can be acquired by 'value' threads.</span>
+&lt;Event&gt;     = Event()                          <span class="hljs-comment"># Method wait() blocks until set() is called.</span>
+&lt;Barrier&gt;   = Barrier(n_times)                 <span class="hljs-comment"># Wait() blocks until it's called n_times.</span>
+</code></pre></div>
+
+<div><h3 id="queue">Queue</h3><pre><code class="python language-python hljs">&lt;Queue&gt; = queue.Queue(maxsize=<span class="hljs-number">0</span>)               <span class="hljs-comment"># A thread-safe first-in-first-out queue.</span>
+&lt;Queue&gt;.put(&lt;el&gt;)                              <span class="hljs-comment"># Blocks until queue stops being full.</span>
+&lt;Queue&gt;.put_nowait(&lt;el&gt;)                       <span class="hljs-comment"># Raises queue.Full exception if full.</span>
+&lt;el&gt; = &lt;Queue&gt;.get()                           <span class="hljs-comment"># Blocks until queue stops being empty.</span>
+&lt;el&gt; = &lt;Queue&gt;.get_nowait()                    <span class="hljs-comment"># Raises queue.Empty exception if empty.</span>
+</code></pre></div>
+
+<div><h3 id="threadpoolexecutor">Thread Pool Executor</h3><pre><code class="python language-python hljs">&lt;Exec&gt; = ThreadPoolExecutor(max_workers=<span class="hljs-keyword">None</span>)  <span class="hljs-comment"># Or: `with ThreadPoolExecutor() as &lt;name&gt;: ...`</span>
+&lt;iter&gt; = &lt;Exec&gt;.map(&lt;func&gt;, &lt;args_1&gt;, ...)     <span class="hljs-comment"># Multithreaded and non-lazy map(). Keeps order.</span>
+&lt;Futr&gt; = &lt;Exec&gt;.submit(&lt;func&gt;, &lt;arg_1&gt;, ...)   <span class="hljs-comment"># Creates a thread and returns its Future obj.</span>
+&lt;Exec&gt;.shutdown()                              <span class="hljs-comment"># Blocks until all threads finish executing.</span>
+</code></pre></div>
+
+<pre><code class="python language-python hljs">&lt;bool&gt; = &lt;Future&gt;.done()                       <span class="hljs-comment"># Checks if the thread has finished executing.</span>
+&lt;obj&gt;  = &lt;Future&gt;.result(timeout=<span class="hljs-keyword">None</span>)         <span class="hljs-comment"># Waits for thread to finish and returns result.</span>
+&lt;bool&gt; = &lt;Future&gt;.cancel()                     <span class="hljs-comment"># Cancels or returns False if running/finished.</span>
+&lt;iter&gt; = as_completed(&lt;coll_of_Futures&gt;)       <span class="hljs-comment"># `next(&lt;iter&gt;)` returns next completed Future.</span>
+</code></pre>
+<ul>
+<li><strong>Map() and as_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called/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 threads are done.</strong></li>
+<li><strong>Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.</strong></li>
+<li><strong>ProcessPoolExecutor provides true parallelism but: everything sent to/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="coroutines"><a href="#coroutines" name="coroutines">#</a>Coroutines</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 use as much memory.</strong></li>
 <li><strong>Coroutine definition starts with <code class="python hljs"><span class="hljs-string">'async'</span></code> and its call with <code class="python hljs"><span class="hljs-string">'await'</span></code>.</strong></li>
@@ -2087,7 +2087,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 <pre><code class="python language-python hljs">app = fl.Flask(__name__)                   <span class="hljs-comment"># Returns the 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[=VAL] …]</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[=VAL]]…</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>
@@ -2568,7 +2568,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     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="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">Plotly</a>.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pandas matplotlib</span>
+<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>
 
diff --git a/parse.js b/parse.js
index cc1725ef6..3f8261722 100755
--- a/parse.js
+++ b/parse.js
@@ -36,7 +36,7 @@ const TOC =
   '    <strong><span class="hljs-string">\'3. Syntax\'</span></strong>:      [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>],\n' +
   '    <strong><span class="hljs-string">\'4. System\'</span></strong>:      [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">Command_Line_Arguments</a>, <a href="#open">Open</a>, <a href="#paths">Path</a>, <a href="#oscommands">OS_Commands</a>],\n' +
   '    <strong><span class="hljs-string">\'5. Data\'</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>],\n' +
-  '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],\n' +
+  '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],\n' +
   '    <strong><span class="hljs-string">\'7. Libraries\'</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>],\n' +
   '    <strong><span class="hljs-string">\'8. Multimedia\'</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>]\n' +
   '}\n' +
@@ -711,7 +711,6 @@ function getMd() {
   var readme = readme.replace("#semaphore-event-barrier", "#semaphoreeventbarrier");
   var readme = readme.replace("#semaphore-event-barrier", "#semaphoreeventbarrier");
   var readme = readme.replace("#dataframe-plot-encode-decode", "#dataframeplotencodedecode");
-  var readme = readme.replace("#displays-a-line-chart-of-total-coronavirus-deaths-per-million-grouped-by-continent", "#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent");
   const converter = new showdown.Converter();
   return converter.makeHtml(readme);
 }
diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html
index 54f6747f0..44050adcc 100644
--- a/pdf/index_for_pdf.html
+++ b/pdf/index_for_pdf.html
@@ -14,7 +14,7 @@ <h3 id="a">A</h3>
 <h3 id="b">B</h3>
 <p><strong>beautifulsoup library, <a href="#scrapespythonsurlandlogofromitswikipediapage">35</a></strong><br>
 <strong>binary representation, <a href="#ints">7</a>, <a href="#binhex">8</a></strong><br>
-<strong>bitwise operators, <a href="#bitwiseoperators">8</a>, <a href="#operator">31</a></strong><br>
+<strong>bitwise operators, <a href="#bitwiseoperators">8</a>, <a href="#operator">30</a></strong><br>
 <strong>bytes, <a href="#open">22</a>-<a href="#modes">23</a>, <a href="#pickle">25</a>, <a href="#bytes">28</a>-<a href="#memoryview">29</a></strong>  </p>
 <h3 id="c">C</h3>
 <p><strong>cache, <a href="#cache">13</a></strong><br>
@@ -26,7 +26,7 @@ <h3 id="c">C</h3>
 <strong>combinatorics, <a href="#combinatorics">8</a></strong><br>
 <strong>command line arguments, <a href="#commandlinearguments">22</a></strong><br>
 <strong>comprehensions, <a href="#comprehensions">11</a></strong><br>
-<strong>context manager, <a href="#contextmanager">17</a>, <a href="#readtextfromfile">23</a>, <a href="#or">27</a>, <a href="#or-1">30</a></strong><br>
+<strong>context manager, <a href="#contextmanager">17</a>, <a href="#readtextfromfile">23</a>, <a href="#or">27</a>, <a href="#or-1">32</a></strong><br>
 <strong>copy function, <a href="#copy">15</a></strong><br>
 <strong>coroutine, <a href="#coroutines">33</a></strong><br>
 <strong>counter, <a href="#counter">2</a>, <a href="#generator">4</a>, <a href="#nonlocal">12</a>, <a href="#iterator-1">17</a></strong><br>
@@ -44,7 +44,7 @@ <h3 id="e">E</h3>
 <p><strong>enum module, <a href="#enum">19</a>-<a href="#inline-1">20</a></strong><br>
 <strong>enumerate function, <a href="#enumerate">3</a></strong><br>
 <strong>excel, <a href="#dataframeencodedecode">46</a></strong><br>
-<strong>exceptions, <a href="#exceptions">20</a>-<a href="#exceptionobject">21</a>, <a href="#exceptions-1">23</a>, <a href="#logging">32</a></strong><br>
+<strong>exceptions, <a href="#exceptions">20</a>-<a href="#exceptionobject">21</a>, <a href="#exceptions-1">23</a>, <a href="#logging">31</a></strong><br>
 <strong>exit function, <a href="#exit">21</a></strong>  </p>
 <h3 id="f">F</h3>
 <p><strong>files, <a href="#print">22</a>-<a href="#memoryview">29</a>, <a href="#runsabasicfileexplorerintheconsole">34</a>, <a href="#dataframeencodedecode">46</a></strong><br>
@@ -66,9 +66,9 @@ <h3 id="i">I</h3>
 <strong>imports, <a href="#imports">12</a></strong><br>
 <strong>inline, <a href="#otheruses">11</a>, <a href="#dataclass">15</a>, <a href="#inline-1">20</a></strong><br>
 <strong>input function, <a href="#input">22</a></strong><br>
-<strong>introspection,  <a href="#exceptionobject">21</a>, <a href="#introspection">32</a></strong><br>
+<strong>introspection,  <a href="#exceptionobject">21</a>, <a href="#introspection">31</a></strong><br>
 <strong>ints, <a href="#abstractbaseclasses">4</a>, <a href="#ints">7</a>, <a href="#random">8</a>, <a href="#encode-1">28</a></strong><br>
-<strong>is operator, <a href="#comparable">16</a>, <a href="#operator">31</a></strong><br>
+<strong>is operator, <a href="#comparable">16</a>, <a href="#operator">30</a></strong><br>
 <strong>iterable, <a href="#abstractbaseclasses">4</a>, <a href="#iterable">18</a>, <a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a></strong><br>
 <strong>iterator, <a href="#enumerate">3</a>-<a href="#generator">4</a>, <a href="#comprehensions">11</a>, <a href="#iterator-1">17</a></strong><br>
 <strong>itertools module, <a href="#itertools">3</a>, <a href="#combinatorics">8</a></strong>  </p>
@@ -78,12 +78,12 @@ <h3 id="l">L</h3>
 <p><strong>lambda, <a href="#lambda">11</a></strong><br>
 <strong>lists, <a href="#list">1</a>-<a href="#list">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
 <strong>locale module, <a href="#sortable">16</a></strong><br>
-<strong>logging, <a href="#logging">32</a></strong>  </p>
+<strong>logging, <a href="#logging">31</a></strong>  </p>
 <h3 id="m">M</h3>
 <p><strong>main function, <a href="#main">1</a>, <a href="#basicscripttemplate">49</a></strong><br>
-<strong>match statement, <a href="#matchstatement">31</a></strong><br>
+<strong>match statement, <a href="#matchstatement">30</a></strong><br>
 <strong>matplotlib library, <a href="#plot">34</a>, <a href="#series">44</a>, <a href="#dataframeencodedecode">46</a></strong><br>
-<strong>map function, <a href="#mapfilterreduce">11</a>, <a href="#operator">31</a></strong><br>
+<strong>map function, <a href="#mapfilterreduce">11</a>, <a href="#operator">30</a></strong><br>
 <strong>math module, <a href="#numbers">7</a></strong><br>
 <strong>memoryviews, <a href="#memoryview">29</a></strong><br>
 <strong>module, <a href="#imports">12</a></strong>  </p>
@@ -94,7 +94,7 @@ <h3 id="n">N</h3>
 <strong>numpy library, <a href="#numpy">37</a>-<a href="#indexing">38</a></strong>  </p>
 <h3 id="o">O</h3>
 <p><strong>open function, <a href="#contextmanager">17</a>, <a href="#open">22</a>-<a href="#modes">23</a>, <a href="#readobjectfromjsonfile">25</a>, <a href="#readrowsfromcsvfile">26</a>, <a href="#readbytesfromfile">28</a></strong><br>
-<strong>operator module, <a href="#operator">31</a></strong><br>
+<strong>operator module, <a href="#operator">30</a></strong><br>
 <strong>os commands, <a href="#paths">23</a>-<a href="#shellcommands">25</a>, <a href="#runsabasicfileexplorerintheconsole">34</a></strong>  </p>
 <h3 id="p">P</h3>
 <p><strong>pandas library, <a href="#pandas">44</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
@@ -109,12 +109,12 @@ <h3 id="p">P</h3>
 <strong>property decorator, <a href="#property">15</a></strong><br>
 <strong>pygame library, <a href="#pygame">42</a>-<a href="#basicmariobrothersexample">43</a></strong>  </p>
 <h3 id="q">Q</h3>
-<p><strong>queues, <a href="#deque">29</a>, <a href="#queue">30</a>, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a></strong>  </p>
+<p><strong>queues, <a href="#deque">29</a>, <a href="#queue">32</a>, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a></strong>  </p>
 <h3 id="r">R</h3>
 <p><strong>random module, <a href="#random">8</a></strong><br>
 <strong>ranges, <a href="#range">3</a>, <a href="#abstractbaseclasses">4</a></strong><br>
 <strong>recursion, <a href="#cache">13</a>, <a href="#builtinexceptions">21</a></strong><br>
-<strong>reduce function, <a href="#mapfilterreduce">11</a>, <a href="#operator">31</a></strong><br>
+<strong>reduce function, <a href="#mapfilterreduce">11</a></strong><br>
 <strong>regular expressions, <a href="#regex">5</a>-<a href="#specialsequences">6</a></strong><br>
 <strong>requests library, <a href="#scrapespythonsurlandlogofromitswikipediapage">35</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong>  </p>
 <h3 id="s">S</h3>
@@ -136,11 +136,11 @@ <h3 id="s">S</h3>
 <h3 id="t">T</h3>
 <p><strong>table, <a href="#csv">26</a>, <a href="#example-1">27</a>, <a href="#table">34</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#dataframe">45</a>-<a href="#dataframeaggregatetransformmap">46</a></strong><br>
 <strong>template, <a href="#format">6</a>, <a href="#dynamicrequest">36</a></strong><br>
-<strong>threading module, <a href="#threading">30</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong><br>
+<strong>threading module, <a href="#threading">32</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong><br>
 <strong>time module, <a href="#progressbar">34</a>, <a href="#profiling">36</a></strong><br>
 <strong>tuples, <a href="#tuple">3</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a></strong><br>
 <strong>type, <a href="#type">4</a></strong><br>
-<strong>type annotations, <a href="#typeannotations">15</a>, <a href="#introspection">32</a></strong>  </p>
+<strong>type annotations, <a href="#typeannotations">15</a>, <a href="#introspection">31</a></strong>  </p>
 <h3 id="w">W</h3>
 <p><strong>wave module, <a href="#audio">40</a>-<a href="#writefloatsamplestowavfile">41</a></strong><br>
 <strong>web, <a href="#webapp">36</a></strong>  </p> 
diff --git a/pdf/index_for_pdf_print.html b/pdf/index_for_pdf_print.html
index e7bdcfeb7..126dbf0ec 100644
--- a/pdf/index_for_pdf_print.html
+++ b/pdf/index_for_pdf_print.html
@@ -14,7 +14,7 @@ <h3 id="a">A</h3>
 <h3 id="b">B</h3>
 <p><strong>beautifulsoup library, 35</strong><br>
 <strong>binary representation, 7, 8</strong><br>
-<strong>bitwise operators, 8, 31</strong><br>
+<strong>bitwise operators, 8, 30</strong><br>
 <strong>bytes, 22-23, 25, 28-29</strong>  </p>
 <h3 id="c">C</h3>
 <p><strong>cache, 13</strong><br>
@@ -26,7 +26,7 @@ <h3 id="c">C</h3>
 <strong>combinatorics, 8</strong><br>
 <strong>command line arguments, 22</strong><br>
 <strong>comprehensions, 11</strong><br>
-<strong>context manager, 17, 23, 27, 30</strong><br>
+<strong>context manager, 17, 23, 27, 32</strong><br>
 <strong>copy function, 15</strong><br>
 <strong>coroutine, 33</strong><br>
 <strong>counter, 2, 4, 12, 17</strong><br>
@@ -44,7 +44,7 @@ <h3 id="e">E</h3>
 <p><strong>enum module, 19-20</strong><br>
 <strong>enumerate function, 3</strong><br>
 <strong>excel, 46</strong><br>
-<strong>exceptions, 20-21, 23, 32</strong><br>
+<strong>exceptions, 20-21, 23, 31</strong><br>
 <strong>exit function, 21</strong>  </p>
 <h3 id="f">F</h3>
 <p><strong>files, 22-29, 34, 46</strong><br>
@@ -66,9 +66,9 @@ <h3 id="i">I</h3>
 <strong>imports, 12</strong><br>
 <strong>inline, 11, 15, 20</strong><br>
 <strong>input function, 22</strong><br>
-<strong>introspection, 21, 32</strong><br>
+<strong>introspection, 21, 31</strong><br>
 <strong>ints, 4, 7, 8, 28</strong><br>
-<strong>is operator, 16, 31</strong><br>
+<strong>is operator, 16, 30</strong><br>
 <strong>iterable, 4, 18, 19</strong><br>
 <strong>iterator, 3-4, 11, 17</strong><br>
 <strong>itertools module, 3, 8</strong>  </p>
@@ -78,12 +78,12 @@ <h3 id="l">L</h3>
 <p><strong>lambda, 11</strong><br>
 <strong>lists, 1-2, 4, 11, 18-19, 21</strong><br>
 <strong>locale module, 16</strong><br>
-<strong>logging, 32</strong>  </p>
+<strong>logging, 31</strong>  </p>
 <h3 id="m">M</h3>
 <p><strong>main function, 1, 49</strong><br>
-<strong>match statement, 31</strong><br>
+<strong>match statement, 30</strong><br>
 <strong>matplotlib library, 34, 44, 46</strong><br>
-<strong>map function, 11, 31</strong><br>
+<strong>map function, 11, 30</strong><br>
 <strong>math module, 7</strong><br>
 <strong>memoryviews, 29</strong><br>
 <strong>module, 12</strong>  </p>
@@ -94,7 +94,7 @@ <h3 id="n">N</h3>
 <strong>numpy library, 37-38</strong>  </p>
 <h3 id="o">O</h3>
 <p><strong>open function, 17, 22-23, 25, 26, 28</strong><br>
-<strong>operator module, 31</strong><br>
+<strong>operator module, 30</strong><br>
 <strong>os commands, 23-25, 34</strong>  </p>
 <h3 id="p">P</h3>
 <p><strong>pandas library, 44-48</strong><br>
@@ -109,12 +109,12 @@ <h3 id="p">P</h3>
 <strong>property decorator, 15</strong><br>
 <strong>pygame library, 42-43</strong>  </p>
 <h3 id="q">Q</h3>
-<p><strong>queues, 29, 30, 33</strong>  </p>
+<p><strong>queues, 29, 32, 33</strong>  </p>
 <h3 id="r">R</h3>
 <p><strong>random module, 8</strong><br>
 <strong>ranges, 3, 4</strong><br>
 <strong>recursion, 13, 21</strong><br>
-<strong>reduce function, 11, 31</strong><br>
+<strong>reduce function, 11</strong><br>
 <strong>regular expressions, 5-6</strong><br>
 <strong>requests library, 35, 36</strong>  </p>
 <h3 id="s">S</h3>
@@ -136,11 +136,11 @@ <h3 id="s">S</h3>
 <h3 id="t">T</h3>
 <p><strong>table, 26, 27, 34, 37-38, 45-46</strong><br>
 <strong>template, 6, 36</strong><br>
-<strong>threading module, 30, 36</strong><br>
+<strong>threading module, 32, 36</strong><br>
 <strong>time module, 34, 36</strong><br>
 <strong>tuples, 3, 4, 11, 18-19</strong><br>
 <strong>type, 4</strong><br>
-<strong>type annotations, 15, 32</strong>  </p>
+<strong>type annotations, 15, 31</strong>  </p>
 <h3 id="w">W</h3>
 <p><strong>wave module, 40-41</strong><br>
 <strong>web, 36</strong>  </p> 
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index e31507ed8..329238d38 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -20,15 +20,14 @@
     '<strong>Objects returned by the <a href="#itertools">itertools</a> module, such as count, repeat and cycle.</strong>': '<strong>Objects returned by the itertools module, such as count, repeat and cycle (p. 3).</strong>',
     '<strong>Generators returned by the <a href="#generator">generator functions</a> and <a href="#comprehensions">generator expressions</a>.</strong>': '<strong>Generators returned by the generator functions (p. 4) and generator expressions (p. 11).</strong>',
     '<strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong>': '<strong>File objects returned by the open() function (p. 22), etc.</strong>',
-    '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">logging</a>.</strong>': '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see logging (p. 32).</strong>',
+    '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">logging</a>.</strong>': '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see logging (p. 31).</strong>',
     '<strong>Functions report OS related errors by raising either OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong>': '<strong>Functions report OS related errors by raising OSError or one of its subclasses (p. 23).</strong>',
     '<strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong>': '<strong>To print the spreadsheet to the console use Tabulate library (p. 34).</strong>',
     '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#dataframeplotencodedecode">Pandas</a> library.</strong>': '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use Pandas library (p. 46).</strong>',
     '<strong>Bools will be stored and returned as ints and dates as <a href="#encode">ISO formatted strings</a>.</strong>': '<strong>Bools will be stored and returned as ints and dates as ISO formatted strings (p. 9).</strong>',
     '<strong>ProcessPoolExecutor provides true parallelism but: everything sent to/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>': '<strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be pickable, 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>',
-    '<strong>Asyncio module also provides its own <a href="#queue">Queue</a>, <a href="#semaphoreeventbarrier">Event</a>, <a href="#lock">Lock</a> and <a href="#semaphoreeventbarrier">Semaphore</a> classes.</strong>': '<strong>Asyncio module also provides its own Queue, Event, Lock and Semaphore classes (p. 30).</strong>',
     '<strong>Install a WSGI 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> for better security.</strong>': '<strong>Install a WSGI server like Waitress and a HTTP server such as Nginx for better security.</strong>',
-    '<strong>Data analysis library. For examples see <a href="#displays-a-line-chart-of-total-coronavirus-deaths-per-million-grouped-by-continent">Plotly</a>.</strong>': '<strong>Data analysis library. For examples see Plotly (p. 47).</strong>',
+    '<strong>Data analysis library. For examples see <a href="#plotly">Plotly</a>.</strong>': '<strong>Data analysis library. For examples see Plotly (p. 47).</strong>',
 }
 
 
diff --git a/web/script_2.js b/web/script_2.js
index be1c1c7bf..673fc18ed 100644
--- a/web/script_2.js
+++ b/web/script_2.js
@@ -5,7 +5,7 @@ const TOC =
   '    <strong><span class="hljs-string">\'3. Syntax\'</span></strong>:      [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>],\n' +
   '    <strong><span class="hljs-string">\'4. System\'</span></strong>:      [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">Command_Line_Arguments</a>, <a href="#open">Open</a>, <a href="#paths">Path</a>, <a href="#oscommands">OS_Commands</a>],\n' +
   '    <strong><span class="hljs-string">\'5. Data\'</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>],\n' +
-  '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],\n' +
+  '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],\n' +
   '    <strong><span class="hljs-string">\'7. Libraries\'</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>],\n' +
   '    <strong><span class="hljs-string">\'8. Multimedia\'</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>]\n' +
   '}\n';
@@ -27,9 +27,9 @@ const TOC_MOBILE =
   '    <strong><span class="hljs-string">\'5. Data\'</span></strong>:        [<a href="#json">JSON</a>, <a href="#pickle">Pickle</a>, <a href="#csv">CSV</a>, <a href="#sqlite">SQLite</a>,\n' +
   '                       <a href="#bytes">Bytes</a>, <a href="#struct">Struct</a>, <a href="#array">Array</a>,\n' +
   '                       <a href="#memoryview">Memory_View</a>, <a href="#deque">Deque</a>],\n' +
-  '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>,\n' +
-  '                       <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, \n' +
-  '                       <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],\n' +
+  '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>,\n' +
+  '                       <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>,\n' +
+  '                       <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],\n' +
   '    <strong><span class="hljs-string">\'7. Libraries\'</span></strong>:   [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>,\n' +
   '                       <a href="#consoleapp">Console_App</a>, <a href="#guiapp">GUI_App</a>,\n' +
   '                       <a href="#scraping">Scraping</a>, <a href="#webapp">Web</a>, <a href="#profiling">Profiling</a>],\n' +

From ca862f4441f9cc23363da4a7c5d452189d87b1fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 27 Nov 2024 19:57:56 +0100
Subject: [PATCH 017/186] Fixed script_2.js

---
 web/script_2.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/web/script_2.js b/web/script_2.js
index 673fc18ed..8cb4f55ab 100644
--- a/web/script_2.js
+++ b/web/script_2.js
@@ -27,7 +27,7 @@ const TOC_MOBILE =
   '    <strong><span class="hljs-string">\'5. Data\'</span></strong>:        [<a href="#json">JSON</a>, <a href="#pickle">Pickle</a>, <a href="#csv">CSV</a>, <a href="#sqlite">SQLite</a>,\n' +
   '                       <a href="#bytes">Bytes</a>, <a href="#struct">Struct</a>, <a href="#array">Array</a>,\n' +
   '                       <a href="#memoryview">Memory_View</a>, <a href="#deque">Deque</a>],\n' +
-  '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>,\n' +
+  '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>,\n' +
   '                       <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>,\n' +
   '                       <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],\n' +
   '    <strong><span class="hljs-string">\'7. Libraries\'</span></strong>:   [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>,\n' +

From e5a7c71bf10f42b893cc6897eb03c4fbdb83978c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 27 Nov 2024 20:00:08 +0100
Subject: [PATCH 018/186] Updated mobile TOC

---
 web/script_2.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/web/script_2.js b/web/script_2.js
index 8cb4f55ab..12ff725a2 100644
--- a/web/script_2.js
+++ b/web/script_2.js
@@ -27,7 +27,7 @@ const TOC_MOBILE =
   '    <strong><span class="hljs-string">\'5. Data\'</span></strong>:        [<a href="#json">JSON</a>, <a href="#pickle">Pickle</a>, <a href="#csv">CSV</a>, <a href="#sqlite">SQLite</a>,\n' +
   '                       <a href="#bytes">Bytes</a>, <a href="#struct">Struct</a>, <a href="#array">Array</a>,\n' +
   '                       <a href="#memoryview">Memory_View</a>, <a href="#deque">Deque</a>],\n' +
-  '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>,\n' +
+  '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Statement</a>,\n' +
   '                       <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>,\n' +
   '                       <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],\n' +
   '    <strong><span class="hljs-string">\'7. Libraries\'</span></strong>:   [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>,\n' +

From e78d26fef1b7dde2bb7c682af3ae9edd4a25cdf2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 28 Nov 2024 00:19:44 +0100
Subject: [PATCH 019/186] Index

---
 README.md  | 2 +-
 index.html | 6 +++---
 parse.js   | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 81a9f2d06..24c40b1aa 100644
--- a/README.md
+++ b/README.md
@@ -3585,4 +3585,4 @@ Index
 * **Only available in the [PDF](https://transactions.sendowl.com/products/78175486/4422834F/view).**
 * **Ctrl+F / ⌘F is usually sufficient.**
 * **Searching `'#<title>'` on the [webpage](https://gto76.github.io/python-cheatsheet/) will limit the search to the titles.**
-* **Click on the `'🔗'` symbol to get a link to specific section.**
+* **Click on the title's `'🔗'` symbol to get a link to specific section.**
diff --git a/index.html b/index.html
index 75852dcb6..3516f5316 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 27, 2024</aside>
+    <aside>November 28, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2918,12 +2918,12 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <div><h2 id="index"><a href="#index" name="index">#</a>Index</h2><ul><li><strong>Only available in the <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">PDF</a>.</strong></li>
 <li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>
 <li><strong>Searching <code class="python hljs"><span class="hljs-string">'#&lt;title&gt;'</span></code> will limit the search to the titles.</strong></li>
-<li><strong>Click on the <code class="python hljs"><span class="hljs-string">'#'</span></code> symbol to get a link to specific section.</strong></li>
+<li><strong>Click on the title's <code class="python hljs"><span class="hljs-string">'#'</span></code> symbol to get a link to specific section.</strong></li>
 </ul></div>
  
 
   <footer>
-    <aside>November 27, 2024</aside>
+    <aside>November 28, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 3f8261722..dc4a9acc8 100755
--- a/parse.js
+++ b/parse.js
@@ -337,7 +337,7 @@ const INDEX =
   '<li><strong>Only available in the <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">PDF</a>.</strong></li>\n' +
   '<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>\n' +
   '<li><strong>Searching <code class="python hljs"><span class="hljs-string">\'#&lt;title&gt;\'</span></code> will limit the search to the titles.</strong></li>\n' +
-  '<li><strong>Click on the <code class="python hljs"><span class="hljs-string">\'#\'</span></code> symbol to get a link to specific section.</strong></li>\n';
+  '<li><strong>Click on the title\'s <code class="python hljs"><span class="hljs-string">\'#\'</span></code> symbol to get a link to specific section.</strong></li>\n';
 
 
 const DIAGRAM_1_A =

From 730877a7b3ce5ac73dc1eb53142d9a1d57544f4b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 28 Nov 2024 14:47:20 +0100
Subject: [PATCH 020/186] SQLite, Pandas

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 24c40b1aa..551573254 100644
--- a/README.md
+++ b/README.md
@@ -1918,7 +1918,7 @@ with <conn>:                                   # Exits the block with commit() o
 <conn>.execute('<query>', <dict/namedtuple>)   # Replaces ':<key>'s with values.
 <conn>.executemany('<query>', <coll_of_coll>)  # Runs execute() multiple times.
 ```
-* **Passed values can be of type str, int, float, bytes, None, or bool (stored as 0 or 1).**
+* **Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).**
 
 ### Example
 **Values are not actually saved in this example because `'conn.commit()'` is omitted!**
@@ -3182,7 +3182,7 @@ Name: a, dtype: int64
 ```
 
 ```python
-<S>  = <S> > <el/S>                            # Returns a Series of bools.
+<S>  = <S> > <el/S>                            # Returns S of bools. Pairs items by keys.
 <S>  = <S> + <el/S>                            # Items with non-matching keys get value NaN.
 ```
 
diff --git a/index.html b/index.html
index 3516f5316..a1d6d8cfd 100644
--- a/index.html
+++ b/index.html
@@ -1587,7 +1587,7 @@
 </code></pre></div>
 
 <ul>
-<li><strong>Passed values can be of type str, int, float, bytes, None, or bool (stored as 0 or 1).</strong></li>
+<li><strong>Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).</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">'conn.commit()'</span></code> is omitted!</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>conn = sqlite3.connect(<span class="hljs-string">'test.db'</span>)
 <span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height)'</span>)
@@ -2592,7 +2592,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;S&gt;  = &lt;S&gt;[coll_of_keys/coll_of_i]             <span class="hljs-comment"># Or: &lt;S&gt;[key/i : key/i]</span>
 &lt;S&gt;  = &lt;S&gt;[bools]                              <span class="hljs-comment"># Or: &lt;S&gt;.loc/iloc[bools]</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt; &gt; &lt;el/S&gt;                            <span class="hljs-comment"># Returns a Series of bools.</span>
+<pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt; &gt; &lt;el/S&gt;                            <span class="hljs-comment"># Returns S of bools. Pairs items by keys.</span>
 &lt;S&gt;  = &lt;S&gt; + &lt;el/S&gt;                            <span class="hljs-comment"># Items with non-matching keys get value NaN.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;S&gt; = pd.concat(&lt;coll_of_S&gt;)                   <span class="hljs-comment"># Concats multiple series into one long Series.</span>

From 724b2edf0b26a7e6be0adc0f40b917e28932b383 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 28 Nov 2024 14:54:28 +0100
Subject: [PATCH 021/186] Pandas

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 551573254..28f50eb3d 100644
--- a/README.md
+++ b/README.md
@@ -3268,7 +3268,7 @@ b  3  4
 ```
 
 ```python
-<DF>   = <DF>.head/tail/sample(<int>)          # Returns first, last, or random n elements.
+<DF>   = <DF>.head/tail/sample(<int>)          # Returns first, last, or random n rows.
 <DF>   = <DF>.describe()                       # Describes columns. Also shape, info(), corr().
 <DF>   = <DF>.query('<query>')                 # Filters rows with e.g. 'col_1 == val_1 and …'.
 ```
diff --git a/index.html b/index.html
index a1d6d8cfd..e332aa241 100644
--- a/index.html
+++ b/index.html
@@ -2658,7 +2658,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;DF&gt;   = &lt;DF&gt;.sort_index(ascending=<span class="hljs-keyword">True</span>)       <span class="hljs-comment"># Sorts rows by row keys. Use `axis=1` for cols.</span>
 &lt;DF&gt;   = &lt;DF&gt;.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">&lt;DF&gt;   = &lt;DF&gt;.head/tail/sample(&lt;int&gt;)          <span class="hljs-comment"># Returns first, last, or random n elements.</span>
+<pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt;.head/tail/sample(&lt;int&gt;)          <span class="hljs-comment"># Returns first, last, or random n rows.</span>
 &lt;DF&gt;   = &lt;DF&gt;.describe()                       <span class="hljs-comment"># Describes columns. Also shape, info(), corr().</span>
 &lt;DF&gt;   = &lt;DF&gt;.query(<span class="hljs-string">'&lt;query&gt;'</span>)                 <span class="hljs-comment"># Filters rows with e.g. 'col_1 == val_1 and …'.</span>
 </code></pre>

From 381dc91c9c9fcbcb84d49034dacdc47500f81b9b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 28 Nov 2024 15:38:01 +0100
Subject: [PATCH 022/186] Introspection

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 28f50eb3d..804ed1921 100644
--- a/README.md
+++ b/README.md
@@ -2235,7 +2235,7 @@ Introspection
 ```
 
 ```python
-<list> = dir(<obj>)                 # Returns names of all object's attributes (incl. methods).
+<list> = dir(<obj>)                 # Returns names of object's attributes (including methods).
 <dict> = vars(<obj>)                # Returns dict of writable attributes. Also <obj>.__dict__.
 <bool> = hasattr(<obj>, '<name>')   # Checks if object possesses attribute with passed name.
 value  = getattr(<obj>, '<name>')   # Returns object's attribute or raises AttributeError.
diff --git a/index.html b/index.html
index e332aa241..c2f9bfa5d 100644
--- a/index.html
+++ b/index.html
@@ -1831,7 +1831,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;dict&gt; = globals()                  <span class="hljs-comment"># Dict of global names and their objects, e.g. __builtin__.</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs">&lt;list&gt; = dir(&lt;obj&gt;)                 <span class="hljs-comment"># Returns names of all object's attributes (incl. methods).</span>
+<pre><code class="python language-python hljs">&lt;list&gt; = dir(&lt;obj&gt;)                 <span class="hljs-comment"># Returns names of object's attributes (including methods).</span>
 &lt;dict&gt; = vars(&lt;obj&gt;)                <span class="hljs-comment"># Returns dict of writable attributes. Also &lt;obj&gt;.__dict__.</span>
 &lt;bool&gt; = hasattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>)   <span class="hljs-comment"># Checks if object possesses attribute with passed name.</span>
 value  = getattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>)   <span class="hljs-comment"># Returns object's attribute or raises AttributeError.</span>

From 12fe5a0de6dc0ef23ec21c60e6a63cfc1f10c9ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 28 Nov 2024 17:01:48 +0100
Subject: [PATCH 023/186] Pandas

---
 README.md  | 8 ++++----
 index.html | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 804ed1921..55517d811 100644
--- a/README.md
+++ b/README.md
@@ -3164,8 +3164,8 @@ Name: a, dtype: int64
 ```
 
 ```python
-<S>  = pd.Series(<list>)                       # Assigns RangeIndex starting at 0.
-<S>  = pd.Series(<dict>)                       # Takes dictionary's keys for index.
+<S>  = pd.Series(<list>)                       # Creates index from list's indices.
+<S>  = pd.Series(<dict>)                       # Creates index from dictionary's keys.
 <S>  = pd.Series(<dict/Series>, index=<list>)  # Only keeps items with keys specified in index.
 ```
 
@@ -3193,7 +3193,7 @@ Name: a, dtype: int64
 ```
 
 ```python
-<S>.plot.line/area/bar/pie/hist()              # Generates a Matplotlib plot.
+<S>.plot.line/area/bar/pie/hist()              # Generates a plot. Accepts `title=<str>`.
 plt.show()                                     # Displays the plot. Also plt.savefig(<path>).
 ```
 * **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`!**
@@ -3269,7 +3269,7 @@ b  3  4
 
 ```python
 <DF>   = <DF>.head/tail/sample(<int>)          # Returns first, last, or random n rows.
-<DF>   = <DF>.describe()                       # Describes columns. Also shape, info(), corr().
+<DF>   = <DF>.describe()                       # Describes columns. Also info(), corr(), shape.
 <DF>   = <DF>.query('<query>')                 # Filters rows with e.g. 'col_1 == val_1 and …'.
 ```
 
diff --git a/index.html b/index.html
index c2f9bfa5d..53ccff7d7 100644
--- a/index.html
+++ b/index.html
@@ -2580,8 +2580,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 
-<pre><code class="python language-python hljs">&lt;S&gt;  = pd.Series(&lt;list&gt;)                       <span class="hljs-comment"># Assigns RangeIndex starting at 0.</span>
-&lt;S&gt;  = pd.Series(&lt;dict&gt;)                       <span class="hljs-comment"># Takes dictionary's keys for index.</span>
+<pre><code class="python language-python hljs">&lt;S&gt;  = pd.Series(&lt;list&gt;)                       <span class="hljs-comment"># Creates index from list's indices.</span>
+&lt;S&gt;  = pd.Series(&lt;dict&gt;)                       <span class="hljs-comment"># Creates index from dictionary's keys.</span>
 &lt;S&gt;  = pd.Series(&lt;dict/Series&gt;, index=&lt;list&gt;)  <span class="hljs-comment"># Only keeps items with keys specified in index.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.loc[key]                            <span class="hljs-comment"># Or: &lt;S&gt;.iloc[i]</span>
@@ -2599,7 +2599,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;S&gt; = &lt;S&gt;.combine_first(&lt;S&gt;)                   <span class="hljs-comment"># Adds items that are not yet present.</span>
 &lt;S&gt;.update(&lt;S&gt;)                                <span class="hljs-comment"># Updates items that are already present.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a Matplotlib plot.</span>
+<pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. Accepts `title=&lt;str&gt;`.</span>
 plt.show()                                     <span class="hljs-comment"># Displays the plot. Also plt.savefig(&lt;path&gt;).</span>
 </code></pre>
 <ul>
@@ -2659,7 +2659,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;DF&gt;   = &lt;DF&gt;.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">&lt;DF&gt;   = &lt;DF&gt;.head/tail/sample(&lt;int&gt;)          <span class="hljs-comment"># Returns first, last, or random n rows.</span>
-&lt;DF&gt;   = &lt;DF&gt;.describe()                       <span class="hljs-comment"># Describes columns. Also shape, info(), corr().</span>
+&lt;DF&gt;   = &lt;DF&gt;.describe()                       <span class="hljs-comment"># Describes columns. Also info(), corr(), shape.</span>
 &lt;DF&gt;   = &lt;DF&gt;.query(<span class="hljs-string">'&lt;query&gt;'</span>)                 <span class="hljs-comment"># Filters rows with e.g. 'col_1 == val_1 and …'.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;DF&gt;.plot.line/area/bar/scatter(x=col_key, …)  <span class="hljs-comment"># `y=col_key/s`. Also hist/box(by=col_key).</span>

From a2b9ed50c6e390ac0c202c00fb9f08b89174b3d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 28 Nov 2024 17:09:03 +0100
Subject: [PATCH 024/186] Regex

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 55517d811..6fb8f028b 100644
--- a/README.md
+++ b/README.md
@@ -391,7 +391,7 @@ import re
 '\w' == '[a-zA-Z0-9_]'                            # Also [ª²³…]. Matches an alphanumeric or _.
 '\s' == '[ \t\n\r\f\v]'                           # Also [\x1c-\x1f…]. Matches a whitespace.
 ```
-* **By default, decimal characters and alphanumerics from all alphabets are matched unless `'flags=re.ASCII'` is used. It restricts special sequence matches to the first 128 Unicode characters and also prevents `'\s'` from accepting `'\x1c'`, `'\x1d'`, `'\x1e'` and `'\x1f'` (the so-called information separators that divide text into files, tables, rows and fields).**
+* **By default, decimal characters and alphanumerics from all alphabets are matched unless `'flags=re.ASCII'` is used. It restricts special sequence matches to the first 128 Unicode characters and also prevents `'\s'` from accepting `'\x1c'`, `'\x1d'`, `'\x1e'` and `'\x1f'` (non-printable characters that divide text into files, tables, rows and fields, respectively).**
 * **Use a capital letter for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).**
 
 
diff --git a/index.html b/index.html
index 53ccff7d7..4b5fd7066 100644
--- a/index.html
+++ b/index.html
@@ -360,7 +360,7 @@
 </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> (the so-called information separators that divide text into files, tables, rows and fields).</strong></li>
+<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 for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).</strong></li>
 </ul>
 <div><h2 id="format"><a href="#format" name="format">#</a>Format</h2><pre><code class="python hljs">&lt;str&gt; = <span class="hljs-string">f'<span class="hljs-subst">{&lt;el_1&gt;}</span>, <span class="hljs-subst">{&lt;el_2&gt;}</span>'</span>            <span class="hljs-comment"># Curly brackets can also contain expressions.</span>

From 519ac14ecb28477e0b16769a03d9939d92725efd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 28 Nov 2024 23:46:43 +0100
Subject: [PATCH 025/186] Decorator

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 6fb8f028b..084082ce8 100644
--- a/README.md
+++ b/README.md
@@ -932,7 +932,7 @@ from functools import cache
 def fib(n):
     return n if n < 2 else fib(n-2) + fib(n-1)
 ```
-* **Potential problem with cache is that it can grow indefinitely. To clear stored return values run `'fib.cache_clear()'`, or use `'@lru_cache(maxsize=<int>)'` decorator instead.**
+* **Potential problem with cache is that it can grow indefinitely. To clear stored values run `'fib.cache_clear()'`, or use `'@lru_cache(maxsize=<int>)'` decorator instead.**
 * **CPython interpreter limits recursion depth to 3000 by default. To increase it run `'sys.setrecursionlimit(<int>)'`.**
 
 ### Parametrized Decorator
diff --git a/index.html b/index.html
index 4b5fd7066..263d07d81 100644
--- a/index.html
+++ b/index.html
@@ -778,7 +778,7 @@
 
 
 <ul>
-<li><strong>Potential problem with cache is that it can grow indefinitely. To clear stored return values run <code class="python hljs"><span class="hljs-string">'fib.cache_clear()'</span></code>, or use <code class="python hljs"><span class="hljs-string">'@lru_cache(maxsize=&lt;int&gt;)'</span></code> decorator instead.</strong></li>
+<li><strong>Potential problem with cache is that it can grow indefinitely. To clear stored values run <code class="python hljs"><span class="hljs-string">'fib.cache_clear()'</span></code>, or use <code class="python hljs"><span class="hljs-string">'@lru_cache(maxsize=&lt;int&gt;)'</span></code> decorator instead.</strong></li>
 <li><strong>CPython interpreter limits recursion depth to 3000 by default. To increase it run <code class="python hljs"><span class="hljs-string">'sys.setrecursionlimit(&lt;int&gt;)'</span></code>.</strong></li>
 </ul>
 <div><h3 id="parametrizeddecorator">Parametrized Decorator</h3><p><strong>A decorator that accepts arguments and returns a normal decorator that accepts a function.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps

From 0ff16b3ccdceedbd3bc4c7863b038647cf6c5ea1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 29 Nov 2024 13:37:32 +0100
Subject: [PATCH 026/186] Pandas

---
 README.md  | 1 +
 index.html | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 084082ce8..390241278 100644
--- a/README.md
+++ b/README.md
@@ -3375,6 +3375,7 @@ c  6  7
 ```python
 <GB> = <DF>.groupby(col_key/s)                 # Splits DF into groups based on passed column.
 <DF> = <GB>.apply(<func>)                      # Maps each group. Func can return DF, S or el.
+<DF> = <GB>.filter(<func>)                     # Drops a group if function returns False.
 <DF> = <GB>.get_group(<el>)                    # Selects a group by grouping column's value.
 <S>  = <GB>.size()                             # S of group sizes. Same keys as get_group().
 <GB> = <GB>[col_key]                           # Single column GB. All operations return S.
diff --git a/index.html b/index.html
index 263d07d81..bf3ec8ca6 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 28, 2024</aside>
+    <aside>November 29, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2747,6 +2747,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </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">&lt;GB&gt; = &lt;DF&gt;.groupby(col_key/s)                 <span class="hljs-comment"># Splits DF into groups based on passed column.</span>
 &lt;DF&gt; = &lt;GB&gt;.apply(&lt;func&gt;)                      <span class="hljs-comment"># Maps each group. Func can return DF, S or el.</span>
+&lt;DF&gt; = &lt;GB&gt;.filter(&lt;func&gt;)                     <span class="hljs-comment"># Drops a group if function returns False.</span>
 &lt;DF&gt; = &lt;GB&gt;.get_group(&lt;el&gt;)                    <span class="hljs-comment"># Selects a group by grouping column's value.</span>
 &lt;S&gt;  = &lt;GB&gt;.size()                             <span class="hljs-comment"># S of group sizes. Same keys as get_group().</span>
 &lt;GB&gt; = &lt;GB&gt;[col_key]                           <span class="hljs-comment"># Single column GB. All operations return S.</span>
@@ -2923,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>November 28, 2024</aside>
+    <aside>November 29, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 767c4ed87abda73f8f70222a2ac6b39a9b71a6e2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 29 Nov 2024 16:15:07 +0100
Subject: [PATCH 027/186] Operator

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 390241278..dd5ea9d2f 100644
--- a/README.md
+++ b/README.md
@@ -2103,7 +2103,7 @@ from collections import deque
 
 Operator
 --------
-**Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.**
+**Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence—from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.**
 ```python
 import operator as op
 ```
diff --git a/index.html b/index.html
index bf3ec8ca6..0af9b79c7 100644
--- a/index.html
+++ b/index.html
@@ -1724,7 +1724,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;deque&gt;.rotate(n=<span class="hljs-number">1</span>)                            <span class="hljs-comment"># Last element becomes first.</span>
 &lt;el&gt; = &lt;deque&gt;.popleft()                       <span class="hljs-comment"># Raises IndexError if deque is empty.</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 ordered and grouped by operator precedence from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> operator <span class="hljs-keyword">as</span> op
+<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 ordered and grouped by operator precedence—from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.</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>
 
 

From ce7e1049605ba4888afe9f9e0c3507ca37848704 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 29 Nov 2024 18:12:44 +0100
Subject: [PATCH 028/186] Index

---
 README.md           | 2 +-
 index.html          | 2 +-
 parse.js            | 2 +-
 pdf/remove_links.py | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index dd5ea9d2f..3f6f13bb7 100644
--- a/README.md
+++ b/README.md
@@ -3586,4 +3586,4 @@ Index
 * **Only available in the [PDF](https://transactions.sendowl.com/products/78175486/4422834F/view).**
 * **Ctrl+F / ⌘F is usually sufficient.**
 * **Searching `'#<title>'` on the [webpage](https://gto76.github.io/python-cheatsheet/) will limit the search to the titles.**
-* **Click on the title's `'🔗'` symbol to get a link to specific section.**
+* **Click on the title's `'🔗'` to get a link to its section.**
diff --git a/index.html b/index.html
index 0af9b79c7..cc20b6047 100644
--- a/index.html
+++ b/index.html
@@ -2919,7 +2919,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <div><h2 id="index"><a href="#index" name="index">#</a>Index</h2><ul><li><strong>Only available in the <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">PDF</a>.</strong></li>
 <li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>
 <li><strong>Searching <code class="python hljs"><span class="hljs-string">'#&lt;title&gt;'</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> symbol to get a link to specific section.</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>
  
 
diff --git a/parse.js b/parse.js
index dc4a9acc8..16488b508 100755
--- a/parse.js
+++ b/parse.js
@@ -337,7 +337,7 @@ const INDEX =
   '<li><strong>Only available in the <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">PDF</a>.</strong></li>\n' +
   '<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>\n' +
   '<li><strong>Searching <code class="python hljs"><span class="hljs-string">\'#&lt;title&gt;\'</span></code> will limit the search to the titles.</strong></li>\n' +
-  '<li><strong>Click on the title\'s <code class="python hljs"><span class="hljs-string">\'#\'</span></code> symbol to get a link to specific section.</strong></li>\n';
+  '<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>\n';
 
 
 const DIAGRAM_1_A =
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index 329238d38..65fec859b 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -8,7 +8,7 @@
 
 MATCHES = {
     '<strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong>': '<strong>For details about sort(), sorted(), min() and max() see sortable (p. 16).</strong>',
-    '<strong>Module <a href="#operator">operator</a> has function itemgetter() that can replace listed <a href="#lambda">lambdas</a>.</strong>': '<strong>Module \'operator\' has function itemgetter() that can replace listed lambdas (p. 11, 31).</strong>',
+    '<strong>Module <a href="#operator">operator</a> has function itemgetter() that can replace listed <a href="#lambda">lambdas</a>.</strong>': '<strong>Module \'operator\' (p. 31) has function itemgetter() that can replace listed lambdas (p. 11).</strong>',
     '<strong>This text uses the term \'collection\' instead of \'iterable\'. For rationale see <a href="#collection">collection</a>.</strong>': '<strong>This text uses the term \'collection\' instead of \'iterable\'. For rationale see collection (p. 18).</strong>',
     '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its <a href="#class">repr()</a> method.</strong>': '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its repr() method.</strong>',
     '<strong>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>': '<strong>It can be any callable, but is usually implemented as a function that returns a closure.</strong>',

From 7daf56e3fdfccc9b1aff43a004bed0e3356e0a77 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 29 Nov 2024 22:23:25 +0100
Subject: [PATCH 029/186] Updated index

---
 pdf/index_for_pdf.html       | 26 +++++++++++++-------------
 pdf/index_for_pdf_print.html | 16 ++++++++--------
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html
index 44050adcc..86a2722bb 100644
--- a/pdf/index_for_pdf.html
+++ b/pdf/index_for_pdf.html
@@ -57,7 +57,7 @@ <h3 id="g">G</h3>
 <p><strong>games, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a>, <a href="#pygame">42</a>-<a href="#basicmariobrothersexample">43</a></strong><br>
 <strong>generators, <a href="#generator">4</a>, <a href="#comprehensions">11</a>, <a href="#iterator-1">17</a></strong><br>
 <strong>global keyword, <a href="#nonlocal">12</a></strong><br>
-<strong>gui, <a href="#guiapp">35</a></strong>  </p>
+<strong>gui app, <a href="#guiapp">35</a></strong>  </p>
 <h3 id="h">H</h3>
 <p><strong>hashable, <a href="#dataclass">15</a>, <a href="#hashable">16</a></strong><br>
 <strong>hexadecimal representation, <a href="#ints">7</a>, <a href="#binhex">8</a>, <a href="#encode-1">28</a></strong>  </p>
@@ -67,7 +67,7 @@ <h3 id="i">I</h3>
 <strong>inline, <a href="#otheruses">11</a>, <a href="#dataclass">15</a>, <a href="#inline-1">20</a></strong><br>
 <strong>input function, <a href="#input">22</a></strong><br>
 <strong>introspection,  <a href="#exceptionobject">21</a>, <a href="#introspection">31</a></strong><br>
-<strong>ints, <a href="#abstractbaseclasses">4</a>, <a href="#ints">7</a>, <a href="#random">8</a>, <a href="#encode-1">28</a></strong><br>
+<strong>ints, <a href="#abstractbaseclasses">4</a>, <a href="#ints">7</a>-<a href="#random">8</a>, <a href="#encode-1">28</a></strong><br>
 <strong>is operator, <a href="#comparable">16</a>, <a href="#operator">30</a></strong><br>
 <strong>iterable, <a href="#abstractbaseclasses">4</a>, <a href="#iterable">18</a>, <a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a></strong><br>
 <strong>iterator, <a href="#enumerate">3</a>-<a href="#generator">4</a>, <a href="#comprehensions">11</a>, <a href="#iterator-1">17</a></strong><br>
@@ -76,24 +76,24 @@ <h3 id="j">J</h3>
 <p><strong>json, <a href="#json">25</a>, <a href="#restrequest">36</a>, <a href="#dataframeencodedecode">46</a></strong>  </p>
 <h3 id="l">L</h3>
 <p><strong>lambda, <a href="#lambda">11</a></strong><br>
-<strong>lists, <a href="#list">1</a>-<a href="#list">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
+<strong>lists, <a href="#list">1</a>-<a href="#list">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
 <strong>locale module, <a href="#sortable">16</a></strong><br>
 <strong>logging, <a href="#logging">31</a></strong>  </p>
 <h3 id="m">M</h3>
 <p><strong>main function, <a href="#main">1</a>, <a href="#basicscripttemplate">49</a></strong><br>
 <strong>match statement, <a href="#matchstatement">30</a></strong><br>
-<strong>matplotlib library, <a href="#plot">34</a>, <a href="#series">44</a>, <a href="#dataframeencodedecode">46</a></strong><br>
+<strong>matplotlib library, <a href="#plot">34</a>, <a href="#pandas">44</a>, <a href="#dataframe">45</a></strong><br>
 <strong>map function, <a href="#mapfilterreduce">11</a>, <a href="#operator">30</a></strong><br>
 <strong>math module, <a href="#numbers">7</a></strong><br>
 <strong>memoryviews, <a href="#memoryview">29</a></strong><br>
 <strong>module, <a href="#imports">12</a></strong>  </p>
 <h3 id="n">N</h3>
-<p><strong>namedtuples, <a href="#namedtuple">3</a></strong><br>
+<p><strong>namedtuples, <a href="#namedtuple">3</a>, <a href="#example">6</a></strong><br>
 <strong>nonlocal keyword, <a href="#nonlocal">12</a></strong><br>
 <strong>numbers, <a href="#abstractbaseclasses">4</a>, <a href="#numbers-1">6</a>-<a href="#random">8</a></strong><br>
-<strong>numpy library, <a href="#numpy">37</a>-<a href="#indexing">38</a></strong>  </p>
+<strong>numpy library, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#image">39</a>, <a href="#series">44</a></strong>  </p>
 <h3 id="o">O</h3>
-<p><strong>open function, <a href="#contextmanager">17</a>, <a href="#open">22</a>-<a href="#modes">23</a>, <a href="#readobjectfromjsonfile">25</a>, <a href="#readrowsfromcsvfile">26</a>, <a href="#readbytesfromfile">28</a></strong><br>
+<p><strong>open function, <a href="#contextmanager">17</a>, <a href="#open">22</a>-<a href="#modes">23</a>, <a href="#readcollectionfromjsonfile">25</a>, <a href="#readrowsfromcsvfile">26</a>, <a href="#readbytesfromfile">28</a></strong><br>
 <strong>operator module, <a href="#operator">30</a></strong><br>
 <strong>os commands, <a href="#paths">23</a>-<a href="#shellcommands">25</a>, <a href="#runsabasicfileexplorerintheconsole">34</a></strong>  </p>
 <h3 id="p">P</h3>
@@ -102,16 +102,16 @@ <h3 id="p">P</h3>
 <strong>paths, <a href="#paths">23</a>-<a href="#oscommands">24</a>, <a href="#runsabasicfileexplorerintheconsole">34</a></strong><br>
 <strong>pickle module, <a href="#pickle">25</a></strong><br>
 <strong>pillow library, <a href="#image">39</a>-<a href="#animation">40</a></strong><br>
-<strong>plotting, <a href="#plot">34</a>, <a href="#series">44</a>, <a href="#dataframeencodedecode">46</a>, <a href="#plotly">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
+<strong>plotting, <a href="#plot">34</a>, <a href="#pandas">44</a>, <a href="#dataframe">45</a>, <a href="#plotly">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
 <strong>print function, <a href="#class">14</a>, <a href="#print">22</a></strong><br>
 <strong>profiling, <a href="#profiling">36</a>-<a href="#profilingbyline">37</a></strong><br>
 <strong>progress bar, <a href="#progressbar">34</a></strong><br>
-<strong>property decorator, <a href="#property">15</a></strong><br>
+<strong>property decorator, <a href="#property">15</a>, <a href="#hashable">16</a></strong><br>
 <strong>pygame library, <a href="#pygame">42</a>-<a href="#basicmariobrothersexample">43</a></strong>  </p>
 <h3 id="q">Q</h3>
 <p><strong>queues, <a href="#deque">29</a>, <a href="#queue">32</a>, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a></strong>  </p>
 <h3 id="r">R</h3>
-<p><strong>random module, <a href="#random">8</a></strong><br>
+<p><strong>random module, <a href="#random">8</a>, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a>, <a href="#addsnoisetothewavfile">41</a></strong><br>
 <strong>ranges, <a href="#range">3</a>, <a href="#abstractbaseclasses">4</a></strong><br>
 <strong>recursion, <a href="#cache">13</a>, <a href="#builtinexceptions">21</a></strong><br>
 <strong>reduce function, <a href="#mapfilterreduce">11</a></strong><br>
@@ -138,10 +138,10 @@ <h3 id="t">T</h3>
 <strong>template, <a href="#format">6</a>, <a href="#dynamicrequest">36</a></strong><br>
 <strong>threading module, <a href="#threading">32</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong><br>
 <strong>time module, <a href="#progressbar">34</a>, <a href="#profiling">36</a></strong><br>
-<strong>tuples, <a href="#tuple">3</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a></strong><br>
-<strong>type, <a href="#type">4</a></strong><br>
+<strong>tuples, <a href="#tuple">3</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a></strong><br>
+<strong>type, <a href="#type">4</a>, <a href="#ducktypes">16</a>, <a href="#matchstatement">30</a></strong><br>
 <strong>type annotations, <a href="#typeannotations">15</a>, <a href="#introspection">31</a></strong>  </p>
 <h3 id="w">W</h3>
 <p><strong>wave module, <a href="#audio">40</a>-<a href="#writefloatsamplestowavfile">41</a></strong><br>
-<strong>web, <a href="#webapp">36</a></strong>  </p> 
+<strong>web app, <a href="#webapp">36</a></strong>  </p>
 </div>
\ No newline at end of file
diff --git a/pdf/index_for_pdf_print.html b/pdf/index_for_pdf_print.html
index 126dbf0ec..41ecf8940 100644
--- a/pdf/index_for_pdf_print.html
+++ b/pdf/index_for_pdf_print.html
@@ -67,7 +67,7 @@ <h3 id="i">I</h3>
 <strong>inline, 11, 15, 20</strong><br>
 <strong>input function, 22</strong><br>
 <strong>introspection, 21, 31</strong><br>
-<strong>ints, 4, 7, 8, 28</strong><br>
+<strong>ints, 4, 7-8, 28</strong><br>
 <strong>is operator, 16, 30</strong><br>
 <strong>iterable, 4, 18, 19</strong><br>
 <strong>iterator, 3-4, 11, 17</strong><br>
@@ -82,16 +82,16 @@ <h3 id="l">L</h3>
 <h3 id="m">M</h3>
 <p><strong>main function, 1, 49</strong><br>
 <strong>match statement, 30</strong><br>
-<strong>matplotlib library, 34, 44, 46</strong><br>
+<strong>matplotlib library, 34, 44, 45</strong><br>
 <strong>map function, 11, 30</strong><br>
 <strong>math module, 7</strong><br>
 <strong>memoryviews, 29</strong><br>
 <strong>module, 12</strong>  </p>
 <h3 id="n">N</h3>
-<p><strong>namedtuples, 3</strong><br>
+<p><strong>namedtuples, 3, 6</strong><br>
 <strong>nonlocal keyword, 12</strong><br>
 <strong>numbers, 4, 6-8</strong><br>
-<strong>numpy library, 37-38</strong>  </p>
+<strong>numpy library, 37-38, 39, 44</strong>  </p>
 <h3 id="o">O</h3>
 <p><strong>open function, 17, 22-23, 25, 26, 28</strong><br>
 <strong>operator module, 30</strong><br>
@@ -102,16 +102,16 @@ <h3 id="p">P</h3>
 <strong>paths, 23-24, 34</strong><br>
 <strong>pickle module, 25</strong><br>
 <strong>pillow library, 39-40</strong><br>
-<strong>plotting, 34, 44, 46, 47-48</strong><br>
+<strong>plotting, 34, 44, 45, 47-48</strong><br>
 <strong>print function, 14, 22</strong><br>
 <strong>profiling, 36-37</strong><br>
 <strong>progress bar, 34</strong><br>
-<strong>property decorator, 15</strong><br>
+<strong>property decorator, 15, 16</strong><br>
 <strong>pygame library, 42-43</strong>  </p>
 <h3 id="q">Q</h3>
 <p><strong>queues, 29, 32, 33</strong>  </p>
 <h3 id="r">R</h3>
-<p><strong>random module, 8</strong><br>
+<p><strong>random module, 8, 33, 41</strong><br>
 <strong>ranges, 3, 4</strong><br>
 <strong>recursion, 13, 21</strong><br>
 <strong>reduce function, 11</strong><br>
@@ -139,7 +139,7 @@ <h3 id="t">T</h3>
 <strong>threading module, 32, 36</strong><br>
 <strong>time module, 34, 36</strong><br>
 <strong>tuples, 3, 4, 11, 18-19</strong><br>
-<strong>type, 4</strong><br>
+<strong>type, 4, 16, 30</strong><br>
 <strong>type annotations, 15, 31</strong>  </p>
 <h3 id="w">W</h3>
 <p><strong>wave module, 40-41</strong><br>

From c4199675d3c6904c8d72e1ea737d186ebcc0589c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 1 Dec 2024 17:48:52 +0100
Subject: [PATCH 030/186] Threading, NumPy, Pygame

---
 README.md  |  6 +++---
 index.html | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 3f6f13bb7..5df754696 100644
--- a/README.md
+++ b/README.md
@@ -2285,7 +2285,7 @@ with <lock>:                                   # Enters the block by calling acq
 ```python
 <Semaphore> = Semaphore(value=1)               # Lock that can be acquired by 'value' threads.
 <Event>     = Event()                          # Method wait() blocks until set() is called.
-<Barrier>   = Barrier(n_times)                 # Wait() blocks until it's called n_times.
+<Barrier>   = Barrier(n_times)                 # Wait() blocks until it's called n times.
 ```
 
 ### Queue
@@ -2710,7 +2710,7 @@ import numpy as np
 <1/2d_arr> = <2d>[<2d/1d_bools>]                        # 1d_bools must have size of a column.
 ```
 * **`':'` returns a slice of all dimension's indices. Omitted dimensions default to `':'`.**
-* **Indices should not be tuples because Python converts `'obj[i, j]'`  to `'obj[(i, j)]'`!**
+* **Sixth line fails if tuple is used because Python converts `'obj[i, j]'` to `'obj[(i, j)]'`!**
 * **Indexing with a slice and 1d array works the same as when using two slices (lines 4, 6, 7).**
 * **`'ix_([1, 2], [3, 4])'` returns `'[[1], [2]]'` and `'[[3, 4]]'`. Due to broadcasting rules, this is the same as using `'[[1, 1], [2, 2]]'` and `'[[3, 4], [3, 4]]'`.**
 * **Any value that is broadcastable to the indexed shape can be assigned to the selection.**
@@ -3011,7 +3011,7 @@ while not pg.event.get(pg.QUIT):
 ### Rectangle
 **Object for storing rectangular coordinates.**
 ```python
-<Rect> = pg.Rect(x, y, width, height)           # Floats get truncated into ints.
+<Rect> = pg.Rect(x, y, width, height)           # Returns a rectangle. Floats get truncated.
 <int>  = <Rect>.x/y/centerx/centery/…           # Top, right, bottom, left. Allows assignments.
 <tup.> = <Rect>.topleft/center/…                # Topright, bottomright, bottomleft. Same.
 <Rect> = <Rect>.move((delta_x, delta_y))        # Use move_ip() to move in-place.
diff --git a/index.html b/index.html
index cc20b6047..94dda5677 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>November 29, 2024</aside>
+    <aside>December 1, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1868,7 +1868,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <div><h3 id="semaphoreeventbarrier">Semaphore, Event, Barrier</h3><pre><code class="python language-python hljs">&lt;Semaphore&gt; = Semaphore(value=<span class="hljs-number">1</span>)               <span class="hljs-comment"># Lock that can be acquired by 'value' threads.</span>
 &lt;Event&gt;     = Event()                          <span class="hljs-comment"># Method wait() blocks until set() is called.</span>
-&lt;Barrier&gt;   = Barrier(n_times)                 <span class="hljs-comment"># Wait() blocks until it's called n_times.</span>
+&lt;Barrier&gt;   = Barrier(n_times)                 <span class="hljs-comment"># Wait() blocks until it's called n times.</span>
 </code></pre></div>
 
 <div><h3 id="queue">Queue</h3><pre><code class="python language-python hljs">&lt;Queue&gt; = queue.Queue(maxsize=<span class="hljs-number">0</span>)               <span class="hljs-comment"># A thread-safe first-in-first-out queue.</span>
@@ -2211,7 +2211,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <ul>
 <li><strong><code class="python hljs"><span class="hljs-string">':'</span></code> returns a slice of all dimension's indices. Omitted dimensions default to <code class="python hljs"><span class="hljs-string">':'</span></code>.</strong></li>
-<li><strong>Indices should not be tuples because 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>!</strong></li>
+<li><strong>Sixth line fails if tuple is used because 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>!</strong></li>
 <li><strong>Indexing with a slice and 1d array works the same as when using two slices (lines 4, 6, 7).</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 using <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>
@@ -2451,7 +2451,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     pg.display.flip()
 </code></pre></div>
 
-<div><h3 id="rectangle">Rectangle</h3><p><strong>Object for storing rectangular coordinates.</strong></p><pre><code class="python language-python hljs">&lt;Rect&gt; = pg.Rect(x, y, width, height)           <span class="hljs-comment"># Floats get truncated into ints.</span>
+<div><h3 id="rectangle">Rectangle</h3><p><strong>Object for storing rectangular coordinates.</strong></p><pre><code class="python language-python hljs">&lt;Rect&gt; = pg.Rect(x, y, width, height)           <span class="hljs-comment"># Returns a rectangle. Floats get truncated.</span>
 &lt;int&gt;  = &lt;Rect&gt;.x/y/centerx/centery/…           <span class="hljs-comment"># Top, right, bottom, left. Allows assignments.</span>
 &lt;tup.&gt; = &lt;Rect&gt;.topleft/center/…                <span class="hljs-comment"># Topright, bottomright, bottomleft. Same.</span>
 &lt;Rect&gt; = &lt;Rect&gt;.move((delta_x, delta_y))        <span class="hljs-comment"># Use move_ip() to move in-place.</span>
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>November 29, 2024</aside>
+    <aside>December 1, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From d3c1a2db36f921b5fada16459516d84a574482f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 1 Dec 2024 18:10:42 +0100
Subject: [PATCH 031/186] Fixed Pandas dataframe

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 5df754696..fdcbdc97e 100644
--- a/README.md
+++ b/README.md
@@ -3317,7 +3317,7 @@ c  6  7
 ```python
 <S>  = <DF>.sum/max/mean/idxmax/all()          # Or: <DF>.apply/agg(lambda <S>: <el>)
 <DF> = <DF>.rank/diff/cumsum/ffill/interpo…()  # Or: <DF>.apply/agg/transform(lambda <S>: <S>)
-<DF> = <DF>.isna/fillna/isin([<el/coll>])      # Or: <S>.agg/transform/map(lambda <el>: <el>)
+<DF> = <DF>.isna/fillna/isin([<el/coll>])      # Or: <DF>.applymap(lambda <el>: <el>)
 ```
 
 ```text
diff --git a/index.html b/index.html
index 94dda5677..e450bed74 100644
--- a/index.html
+++ b/index.html
@@ -2698,7 +2698,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <div><h4 id="dataframeaggregatetransformmap">DataFrame — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;S&gt;  = &lt;DF&gt;.sum/max/mean/idxmax/all()          <span class="hljs-comment"># Or: &lt;DF&gt;.apply/agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;DF&gt; = &lt;DF&gt;.rank/diff/cumsum/ffill/interpo…()  <span class="hljs-comment"># Or: &lt;DF&gt;.apply/agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
-&lt;DF&gt; = &lt;DF&gt;.isna/fillna/isin([&lt;el/coll&gt;])      <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform/map(lambda &lt;el&gt;: &lt;el&gt;)</span>
+&lt;DF&gt; = &lt;DF&gt;.isna/fillna/isin([&lt;el/coll&gt;])      <span class="hljs-comment"># Or: &lt;DF&gt;.applymap(lambda &lt;el&gt;: &lt;el&gt;)</span>
 </code></pre></div>
 
 <pre><code class="python hljs">┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓

From a821b2b55b18c74b7a5feda4f210ecbcac45d9ed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 3 Dec 2024 05:48:10 +0100
Subject: [PATCH 032/186] Pandas

---
 README.md  | 84 +++++++++++++++++++++++++--------------------------
 index.html | 88 ++++++++++++++++++++++++++---------------------------
 parse.js   | 89 ++++++++++++++++++++++++++++--------------------------
 3 files changed, 133 insertions(+), 128 deletions(-)

diff --git a/README.md b/README.md
index fdcbdc97e..82ed9102a 100644
--- a/README.md
+++ b/README.md
@@ -3231,7 +3231,7 @@ plt.show()                                     # Displays the plot. Also plt.sav
 **Table with labeled rows and columns.**
 
 ```python
->>> l = pd.DataFrame([[1, 2], [3, 4]], index=['a', 'b'], columns=['x', 'y']); l
+>>> df = pd.DataFrame([[1, 2], [3, 4]], index=['a', 'b'], columns=['x', 'y']); df
    x  y
 a  1  2
 b  3  4
@@ -3251,7 +3251,7 @@ b  3  4
 
 ```python
 <S/DF> = <DF>[col_key/s]                       # Or: <DF>.<col_key>
-<DF>   = <DF>[row_bools]                       # Keeps rows as specified by bools.
+<DF>   = <DF>[<S_of_bools>]                    # Filters rows. For example `df[df.x > 1]`.
 <DF>   = <DF>[<DF_of_bools>]                   # Assigns NaN to items that are False in bools.
 ```
 
@@ -3270,7 +3270,7 @@ b  3  4
 ```python
 <DF>   = <DF>.head/tail/sample(<int>)          # Returns first, last, or random n rows.
 <DF>   = <DF>.describe()                       # Describes columns. Also info(), corr(), shape.
-<DF>   = <DF>.query('<query>')                 # Filters rows with e.g. 'col_1 == val_1 and …'.
+<DF>   = <DF>.query('<query>')                 # Filters rows. For example `df.query('x > 1')`.
 ```
 
 ```python
@@ -3280,37 +3280,37 @@ plt.show()                                     # Displays the plot. Also plt.sav
 
 #### DataFrame — Merge, Join, Concat:
 ```python
->>> r = pd.DataFrame([[4, 5], [6, 7]], index=['b', 'c'], columns=['y', 'z']); r
+>>> df_2 = pd.DataFrame([[4, 5], [6, 7]], index=['b', 'c'], columns=['y', 'z']); df_2
    y  z
 b  4  5
 c  6  7
 ```
 
 ```text
-+------------------------+---------------+------------+------------+--------------------------+
-|                        |    'outer'    |   'inner'  |   'left'   |       Description        |
-+------------------------+---------------+------------+------------+--------------------------+
-| l.merge(r, on='y',     |    x   y   z  | x   y   z  | x   y   z  | Merges on column if 'on' |
-|            how=…)      | 0  1   2   .  | 3   4   5  | 1   2   .  | or 'left/right_on' are   |
-|                        | 1  3   4   5  |            | 3   4   5  | set, else on shared cols.|
-|                        | 2  .   6   7  |            |            | Uses 'inner' by default. |
-+------------------------+---------------+------------+------------+--------------------------+
-| l.join(r, lsuffix='l', |    x yl yr  z |            | x yl yr  z | Merges on row keys.      |
-|           rsuffix='r', | a  1  2  .  . | x yl yr  z | 1  2  .  . | Uses 'left' by default.  |
-|           how=…)       | b  3  4  4  5 | 3  4  4  5 | 3  4  4  5 | If r is a Series, it is  |
-|                        | c  .  .  6  7 |            |            | treated as a column.     |
-+------------------------+---------------+------------+------------+--------------------------+
-| pd.concat([l, r],      |    x   y   z  |     y      |            | Adds rows at the bottom. |
-|           axis=0,      | a  1   2   .  |     2      |            | Uses 'outer' by default. |
-|           join=…)      | b  3   4   .  |     4      |            | A Series is treated as a |
-|                        | b  .   4   5  |     4      |            | column. To add a row use |
-|                        | c  .   6   7  |     6      |            | pd.concat([l, DF([s])]). |
-+------------------------+---------------+------------+------------+--------------------------+
-| pd.concat([l, r],      |    x  y  y  z |            |            | Adds columns at the      |
-|           axis=1,      | a  1  2  .  . | x  y  y  z |            | right end. Uses 'outer'  |
-|           join=…)      | b  3  4  4  5 | 3  4  4  5 |            | by default. A Series is  |
-|                        | c  .  .  6  7 |            |            | treated as a column.     |
-+------------------------+---------------+------------+------------+--------------------------+
++-----------------------+---------------+------------+------------+---------------------------+
+|                       |    'outer'    |   'inner'  |   'left'   |       Description         |
++-----------------------+---------------+------------+------------+---------------------------+
+| df.merge(df_2,        |    x   y   z  | x   y   z  | x   y   z  | Merges on column if 'on'  |
+|          on='y',      | 0  1   2   .  | 3   4   5  | 1   2   .  | or 'left/right_on' are    |
+|          how=…)       | 1  3   4   5  |            | 3   4   5  | set, else on shared cols. |
+|                       | 2  .   6   7  |            |            | Uses 'inner' by default.  |
++-----------------------+---------------+------------+------------+---------------------------+
+| df.join(df_2,         |    x yl yr  z |            | x yl yr  z | Merges on row keys.       |
+|         lsuffix='l',  | a  1  2  .  . | x yl yr  z | 1  2  .  . | Uses 'left' by default.   |
+|         rsuffix='r',  | b  3  4  4  5 | 3  4  4  5 | 3  4  4  5 | If r is a Series, it is   |
+|         how=…)        | c  .  .  6  7 |            |            | treated as a column.      |
++-----------------------+---------------+------------+------------+---------------------------+
+| pd.concat([df, df_2], |    x   y   z  |     y      |            | Adds rows at the bottom.  |
+|           axis=0,     | a  1   2   .  |     2      |            | Uses 'outer' by default.  |
+|           join=…)     | b  3   4   .  |     4      |            | A Series is treated as a  |
+|                       | b  .   4   5  |     4      |            | column. To add a row use  |
+|                       | c  .   6   7  |     6      |            | pd.concat([df, DF([s])]). |
++-----------------------+---------------+------------+------------+---------------------------+
+| pd.concat([df, df_2], |    x  y  y  z |            |            | Adds columns at the       |
+|           axis=1,     | a  1  2  .  . | x  y  y  z |            | right end. Uses 'outer'   |
+|           join=…)     | b  3  4  4  5 | 3  4  4  5 |            | by default. A Series is   |
+|                       | c  .  .  6  7 |            |            | treated as a column.      |
++-----------------------+---------------+------------+------------+---------------------------+
 ```
 
 #### DataFrame — Aggregate, Transform, Map:
@@ -3321,23 +3321,23 @@ c  6  7
 ```
 
 ```text
-+----------------+---------------+---------------+---------------+
-|                |     'sum'     |    ['sum']    | {'x': 'sum'}  |
-+----------------+---------------+---------------+---------------+
-| l.apply(…)     |      x  4     |        x  y   |     x  4      |
-| l.agg(…)       |      y  6     |   sum  4  6   |               |
-+----------------+---------------+---------------+---------------+
++-----------------+---------------+---------------+---------------+
+|                 |     'sum'     |    ['sum']    | {'x': 'sum'}  |
++-----------------+---------------+---------------+---------------+
+| df.apply(…)     |      x  4     |        x  y   |     x  4      |
+| df.agg(…)       |      y  6     |   sum  4  6   |               |
++-----------------+---------------+---------------+---------------+
 ```
 
 ```text
-+----------------+---------------+---------------+---------------+
-|                |     'rank'    |    ['rank']   | {'x': 'rank'} |
-+----------------+---------------+---------------+---------------+
-| l.apply(…)     |               |       x    y  |               |
-| l.agg(…)       |       x    y  |    rank rank  |         x     |
-| l.transform(…) |  a  1.0  1.0  |  a  1.0  1.0  |    a  1.0     |
-|                |  b  2.0  2.0  |  b  2.0  2.0  |    b  2.0     |
-+----------------+---------------+---------------+---------------+
++-----------------+---------------+---------------+---------------+
+|                 |     'rank'    |    ['rank']   | {'x': 'rank'} |
++-----------------+---------------+---------------+---------------+
+| df.apply(…)     |               |       x    y  |               |
+| df.agg(…)       |       x    y  |    rank rank  |         x     |
+| df.transform(…) |  a  1.0  1.0  |  a  1.0  1.0  |    a  1.0     |
+|                 |  b  2.0  2.0  |  b  2.0  2.0  |    b  2.0     |
++-----------------+---------------+---------------+---------------+
 ```
 * **All methods operate on columns by default. Pass `'axis=1'` to process the rows instead.**
 * **Fifth result's columns are indexed with a multi-index. This means we need a tuple of column keys to specify a column: `'<DF>.loc[row_key, (col_key_1, col_key_2)]'`.**
diff --git a/index.html b/index.html
index e450bed74..48ccfc4e2 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 1, 2024</aside>
+    <aside>December 3, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2631,7 +2631,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>Methods ffill(), interpolate(), fillna() and dropna() accept <code class="python hljs"><span class="hljs-string">'inplace=True'</span></code>.</strong></li>
 <li><strong>Last result has a multi-index. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;[key_1, key_2]'</span></code> to get its values.</strong></li>
 </ul>
-<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">&gt;&gt;&gt; </span>l = 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>]); l
+<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">&gt;&gt;&gt; </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>
@@ -2647,7 +2647,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;DF&gt;   = &lt;DF&gt;.loc[row_bools, col_bools]        <span class="hljs-comment"># Or: &lt;DF&gt;.iloc[row_bools, col_bools]</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;S/DF&gt; = &lt;DF&gt;[col_key/s]                       <span class="hljs-comment"># Or: &lt;DF&gt;.&lt;col_key&gt;</span>
-&lt;DF&gt;   = &lt;DF&gt;[row_bools]                       <span class="hljs-comment"># Keeps rows as specified by bools.</span>
+&lt;DF&gt;   = &lt;DF&gt;[&lt;S_of_bools&gt;]                    <span class="hljs-comment"># Filters rows. For example `df[df.x &gt; 1]`.</span>
 &lt;DF&gt;   = &lt;DF&gt;[&lt;DF_of_bools&gt;]                   <span class="hljs-comment"># Assigns NaN to items that are False in bools.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt; &gt; &lt;el/S/DF&gt;                      <span class="hljs-comment"># Returns DF of bools. S is treated as a row.</span>
@@ -2660,62 +2660,62 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt;.head/tail/sample(&lt;int&gt;)          <span class="hljs-comment"># Returns first, last, or random n rows.</span>
 &lt;DF&gt;   = &lt;DF&gt;.describe()                       <span class="hljs-comment"># Describes columns. Also info(), corr(), shape.</span>
-&lt;DF&gt;   = &lt;DF&gt;.query(<span class="hljs-string">'&lt;query&gt;'</span>)                 <span class="hljs-comment"># Filters rows with e.g. 'col_1 == val_1 and …'.</span>
+&lt;DF&gt;   = &lt;DF&gt;.query(<span class="hljs-string">'&lt;query&gt;'</span>)                 <span class="hljs-comment"># Filters rows. For example `df.query('x &gt; 1')`.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;DF&gt;.plot.line/area/bar/scatter(x=col_key, …)  <span class="hljs-comment"># `y=col_key/s`. Also hist/box(by=col_key).</span>
 plt.show()                                     <span class="hljs-comment"># Displays the plot. Also plt.savefig(&lt;path&gt;).</span>
 </code></pre>
-<div><h4 id="dataframemergejoinconcat">DataFrame — Merge, Join, Concat:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>r = 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>]); r
+<div><h4 id="dataframemergejoinconcat">DataFrame — Merge, Join, Concat:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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        ┃
-┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨
-┃ l.merge(r, on=<span class="hljs-string">'y'</span>,     │    x   y   z  │ x   y   z  │ x   y   z  │ Merges on column if <span class="hljs-string">'on'</span> ┃
-┃            how=…)      │ <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 <span class="hljs-string">'left/right_on'</span> are   ┃
-┃                        │ <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. ┃
-┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨
-┃ l.join(r, lsuffix=<span class="hljs-string">'l'</span>, │    x yl yr  z │            │ x yl yr  z │ Merges on row keys.      ┃
-┃           rsuffix=<span class="hljs-string">'r'</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.  ┃
-┃           how=…)       │ 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 r is a Series, it is  ┃
-┃                        │ c  .  .  <span class="hljs-number">6</span>  <span class="hljs-number">7</span> │            │            │ treated as a column.     ┃
-┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨
-┃ pd.concat([l, r],      │    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([l, DF([s])]). ┃
-┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨
-┃ pd.concat([l, r],      │    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.     ┃
-┗━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━┛
+<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/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 r is a Series, it is   ┃
+┃         how=…)        │ c  .  .  <span class="hljs-number">6</span>  <span class="hljs-number">7</span> │            │            │ 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">&lt;S&gt;  = &lt;DF&gt;.sum/max/mean/idxmax/all()          <span class="hljs-comment"># Or: &lt;DF&gt;.apply/agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;DF&gt; = &lt;DF&gt;.rank/diff/cumsum/ffill/interpo…()  <span class="hljs-comment"># Or: &lt;DF&gt;.apply/agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
 &lt;DF&gt; = &lt;DF&gt;.isna/fillna/isin([&lt;el/coll&gt;])      <span class="hljs-comment"># Or: &lt;DF&gt;.applymap(lambda &lt;el&gt;: &lt;el&gt;)</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>}  ┃
-┠────────────────┼───────────────┼───────────────┼───────────────┨
-┃ l.apply(…)     │      x  <span class="hljs-number">4</span>     │        x  y   │     x  <span class="hljs-number">4</span>      ┃
-┃ l.agg(…)       │      y  <span class="hljs-number">6</span>     │   sum  <span class="hljs-number">4</span>  <span class="hljs-number">6</span>   │               ┃
-┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛
+<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>} ┃
-┠────────────────┼───────────────┼───────────────┼───────────────┨
-┃ l.apply(…)     │               │       x    y  │               ┃
-┃ l.agg(…)       │       x    y  │    rank rank  │         x     ┃
-┃ l.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>     ┃
-┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛
+┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓
+┃                 │     <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>
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 1, 2024</aside>
+    <aside>December 3, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 16488b508..34b28868d 100755
--- a/parse.js
+++ b/parse.js
@@ -599,56 +599,57 @@ const DIAGRAM_14_A =
   "|              |    'rank'   |   ['rank']  | {'r': 'rank'} |";
 
 const DIAGRAM_15_A =
-  '+------------------------+---------------+------------+------------+--------------------------+';
+  '+-----------------------+---------------+------------+------------+---------------------------+';
 
 const DIAGRAM_15_B =
-  "┏━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n" +
-  "┃                        │    'outer'    │   'inner'  │   'left'   │       Description        ┃\n" +
-  "┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨\n" +
-  "┃ l.merge(r, on='y',     │    x   y   z  │ x   y   z  │ x   y   z  │ Merges on column if 'on' ┃\n" +
-  "┃            how=…)      │ 0  1   2   .  │ 3   4   5  │ 1   2   .  │ or 'left/right_on' are   ┃\n" +
-  "┃                        │ 1  3   4   5  │            │ 3   4   5  │ set, else on shared cols.┃\n" +
-  "┃                        │ 2  .   6   7  │            │            │ Uses 'inner' by default. ┃\n" +
-  "┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨\n" +
-  "┃ l.join(r, lsuffix='l', │    x yl yr  z │            │ x yl yr  z │ Merges on row keys.      ┃\n" +
-  "┃           rsuffix='r', │ a  1  2  .  . │ x yl yr  z │ 1  2  .  . │ Uses 'left' by default.  ┃\n" +
-  "┃           how=…)       │ b  3  4  4  5 │ 3  4  4  5 │ 3  4  4  5 │ If r is a Series, it is  ┃\n" +
-  "┃                        │ c  .  .  6  7 │            │            │ treated as a column.     ┃\n" +
-  "┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨\n" +
-  "┃ pd.concat([l, r],      │    x   y   z  │     y      │            │ Adds rows at the bottom. ┃\n" +
-  "┃           axis=0,      │ a  1   2   .  │     2      │            │ Uses 'outer' by default. ┃\n" +
-  "┃           join=…)      │ b  3   4   .  │     4      │            │ A Series is treated as a ┃\n" +
-  "┃                        │ b  .   4   5  │     4      │            │ column. To add a row use ┃\n" +
-  "┃                        │ c  .   6   7  │     6      │            │ pd.concat([l, DF([s])]). ┃\n" +
-  "┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨\n" +
-  "┃ pd.concat([l, r],      │    x  y  y  z │            │            │ Adds columns at the      ┃\n" +
-  "┃           axis=1,      │ a  1  2  .  . │ x  y  y  z │            │ right end. Uses 'outer'  ┃\n" +
-  "┃           join=…)      │ b  3  4  4  5 │ 3  4  4  5 │            │ by default. A Series is  ┃\n" +
-  "┃                        │ c  .  .  6  7 │            │            │ treated as a column.     ┃\n" +
-  "┗━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n";
+  "┏━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n" +
+  "┃                       │    'outer'    │   'inner'  │   'left'   │       Description         ┃\n" +
+  "┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨\n" +
+  "┃ df.merge(df_2,        │    x   y   z  │ x   y   z  │ x   y   z  │ Merges on column if 'on'  ┃\n" +
+  "┃          on='y',      │ 0  1   2   .  │ 3   4   5  │ 1   2   .  │ or 'left/right_on' are    ┃\n" +
+  "┃          how=…)       │ 1  3   4   5  │            │ 3   4   5  │ set, else on shared cols. ┃\n" +
+  "┃                       │ 2  .   6   7  │            │            │ Uses 'inner' by default.  ┃\n" +
+  "┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨\n" +
+  "┃ df.join(df_2,         │    x yl yr  z │            │ x yl yr  z │ Merges on row keys.       ┃\n" +
+  "┃         lsuffix='l',  │ a  1  2  .  . │ x yl yr  z │ 1  2  .  . │ Uses 'left' by default.   ┃\n" +
+  "┃         rsuffix='r',  │ b  3  4  4  5 │ 3  4  4  5 │ 3  4  4  5 │ If r is a Series, it is   ┃\n" +
+  "┃         how=…)        │ c  .  .  6  7 │            │            │ treated as a column.      ┃\n" +
+  "┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨\n" +
+  "┃ pd.concat([df, df_2], │    x   y   z  │     y      │            │ Adds rows at the bottom.  ┃\n" +
+  "┃           axis=0,     │ a  1   2   .  │     2      │            │ Uses 'outer' by default.  ┃\n" +
+  "┃           join=…)     │ b  3   4   .  │     4      │            │ A Series is treated as a  ┃\n" +
+  "┃                       │ b  .   4   5  │     4      │            │ column. To add a row use  ┃\n" +
+  "┃                       │ c  .   6   7  │     6      │            │ pd.concat([df, DF([s])]). ┃\n" +
+  "┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨\n" +
+  "┃ pd.concat([df, df_2], │    x  y  y  z │            │            │ Adds columns at the       ┃\n" +
+  "┃           axis=1,     │ a  1  2  .  . │ x  y  y  z │            │ right end. Uses 'outer'   ┃\n" +
+  "┃           join=…)     │ b  3  4  4  5 │ 3  4  4  5 │            │ by default. A Series is   ┃\n" +
+  "┃                       │ c  .  .  6  7 │            │            │ treated as a column.      ┃\n" +
+  "┗━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n";
+
 
 const DIAGRAM_16_A =
-  '| l.apply(…)     |      x  4     |        x  y   |     x  4      |';
+  '| df.apply(…)     |      x  4     |        x  y   |     x  4      |';
 
 const DIAGRAM_16_B =
-  "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" +
-  "┃                │     'sum'     │    ['sum']    │ {'x': 'sum'}  ┃\n" +
-  "┠────────────────┼───────────────┼───────────────┼───────────────┨\n" +
-  "┃ l.apply(…)     │      x  4     │        x  y   │     x  4      ┃\n" +
-  "┃ l.agg(…)       │      y  6     │   sum  4  6   │               ┃\n" +
-  "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n" +
+  "┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" +
+  "┃                 │     'sum'     │    ['sum']    │ {'x': 'sum'}  ┃\n" +
+  "┠─────────────────┼───────────────┼───────────────┼───────────────┨\n" +
+  "┃ df.apply(…)     │      x  4     │        x  y   │     x  4      ┃\n" +
+  "┃ df.agg(…)       │      y  6     │   sum  4  6   │               ┃\n" +
+  "┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n" +
   "\n" +
-  "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" +
-  "┃                │     'rank'    │    ['rank']   │ {'x': 'rank'} ┃\n" +
-  "┠────────────────┼───────────────┼───────────────┼───────────────┨\n" +
-  "┃ l.apply(…)     │               │       x    y  │               ┃\n" +
-  "┃ l.agg(…)       │       x    y  │    rank rank  │         x     ┃\n" +
-  "┃ l.transform(…) │  a  1.0  1.0  │  a  1.0  1.0  │    a  1.0     ┃\n" +
-  "┃                │  b  2.0  2.0  │  b  2.0  2.0  │    b  2.0     ┃\n" +
-  "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n";
+  "┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" +
+  "┃                 │     'rank'    │    ['rank']   │ {'x': 'rank'} ┃\n" +
+  "┠─────────────────┼───────────────┼───────────────┼───────────────┨\n" +
+  "┃ df.apply(…)     │               │       x    y  │               ┃\n" +
+  "┃ df.agg(…)       │       x    y  │    rank rank  │         x     ┃\n" +
+  "┃ df.transform(…) │  a  1.0  1.0  │  a  1.0  1.0  │    a  1.0     ┃\n" +
+  "┃                 │  b  2.0  2.0  │  b  2.0  2.0  │    b  2.0     ┃\n" +
+  "┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n";
 
 const DIAGRAM_17_A =
-  "|                |     'rank'    |    ['rank']   | {'x': 'rank'} |";
+  "|                 |     'rank'    |    ['rank']   | {'x': 'rank'} |";
 
 const DIAGRAM_18_A =
   '| gb.agg(…)       |      x   y  |             |      x    y |               |';
@@ -897,7 +898,7 @@ function insertPageBreakBefore(an_id) {
 }
 
 function fixPandasDiagram() {
-  const diagram_15 = '┏━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━┓';
+  const diagram_15 = '┏━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━┓';
   $(`code:contains(${diagram_15})`).find(".hljs-keyword:contains(and)").after("and");
   $(`code:contains(${diagram_15})`).find(".hljs-keyword:contains(as)").after("as");
   $(`code:contains(${diagram_15})`).find(".hljs-keyword:contains(is)").after("is");
@@ -905,6 +906,10 @@ function fixPandasDiagram() {
   $(`code:contains(${diagram_15})`).find(".hljs-keyword:contains(or)").after("or");
   $(`code:contains(${diagram_15})`).find(".hljs-keyword:contains(else)").after("else");
   $(`code:contains(${diagram_15})`).find(".hljs-keyword").remove();
+  $(`code:contains(${diagram_15})`).find(".hljs-string:contains(\'left/right_on\')").after("\'left/right_on\'");
+  $(`code:contains(${diagram_15})`).find(".hljs-string:contains(\'left/right_on\')").remove();
+  $(`code:contains(${diagram_15})`).find(".hljs-string:contains('on')").after("'on'");
+  $(`code:contains(${diagram_15})`).find(".hljs-string:contains('on')").remove();
 }
 
 function removePlotImages() {

From dc90042c5e256413173d3a381bb7e52748fdec29 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 3 Dec 2024 06:11:13 +0100
Subject: [PATCH 033/186] Pandas

---
 README.md  | 4 ++--
 index.html | 4 ++--
 parse.js   | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 82ed9102a..4899da1f5 100644
--- a/README.md
+++ b/README.md
@@ -3297,8 +3297,8 @@ c  6  7
 +-----------------------+---------------+------------+------------+---------------------------+
 | df.join(df_2,         |    x yl yr  z |            | x yl yr  z | Merges on row keys.       |
 |         lsuffix='l',  | a  1  2  .  . | x yl yr  z | 1  2  .  . | Uses 'left' by default.   |
-|         rsuffix='r',  | b  3  4  4  5 | 3  4  4  5 | 3  4  4  5 | If r is a Series, it is   |
-|         how=…)        | c  .  .  6  7 |            |            | treated as a column.      |
+|         rsuffix='r',  | b  3  4  4  5 | 3  4  4  5 | 3  4  4  5 | If Series is passed, it   |
+|         how=…)        | c  .  .  6  7 |            |            | is treated as a column.   |
 +-----------------------+---------------+------------+------------+---------------------------+
 | pd.concat([df, df_2], |    x   y   z  |     y      |            | Adds rows at the bottom.  |
 |           axis=0,     | a  1   2   .  |     2      |            | Uses 'outer' by default.  |
diff --git a/index.html b/index.html
index 48ccfc4e2..7ba2306e7 100644
--- a/index.html
+++ b/index.html
@@ -2681,8 +2681,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 ┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨
 ┃ 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 r is a Series, it is   ┃
-┃         how=…)        │ c  .  .  <span class="hljs-number">6</span>  <span class="hljs-number">7</span> │            │            │ treated as a column.      ┃
+┃         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.  ┃
diff --git a/parse.js b/parse.js
index 34b28868d..232585772 100755
--- a/parse.js
+++ b/parse.js
@@ -612,8 +612,8 @@ const DIAGRAM_15_B =
   "┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨\n" +
   "┃ df.join(df_2,         │    x yl yr  z │            │ x yl yr  z │ Merges on row keys.       ┃\n" +
   "┃         lsuffix='l',  │ a  1  2  .  . │ x yl yr  z │ 1  2  .  . │ Uses 'left' by default.   ┃\n" +
-  "┃         rsuffix='r',  │ b  3  4  4  5 │ 3  4  4  5 │ 3  4  4  5 │ If r is a Series, it is   ┃\n" +
-  "┃         how=…)        │ c  .  .  6  7 │            │            │ treated as a column.      ┃\n" +
+  "┃         rsuffix='r',  │ b  3  4  4  5 │ 3  4  4  5 │ 3  4  4  5 │ If Series is passed, it   ┃\n" +
+  "┃         how=…)        │ c  .  .  6  7 │            │            │ is treated as a column.   ┃\n" +
   "┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨\n" +
   "┃ pd.concat([df, df_2], │    x   y   z  │     y      │            │ Adds rows at the bottom.  ┃\n" +
   "┃           axis=0,     │ a  1   2   .  │     2      │            │ Uses 'outer' by default.  ┃\n" +

From 1a02f13142119e0f44809e13c0a9f4d6a1908203 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 4 Dec 2024 05:58:37 +0100
Subject: [PATCH 034/186] Pandas

---
 README.md  |  6 +++---
 index.html | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 4899da1f5..b5ef95eb6 100644
--- a/README.md
+++ b/README.md
@@ -3166,7 +3166,6 @@ Name: a, dtype: int64
 ```python
 <S>  = pd.Series(<list>)                       # Creates index from list's indices.
 <S>  = pd.Series(<dict>)                       # Creates index from dictionary's keys.
-<S>  = pd.Series(<dict/Series>, index=<list>)  # Only keeps items with keys specified in index.
 ```
 
 ```python
@@ -3193,11 +3192,11 @@ Name: a, dtype: int64
 ```
 
 ```python
-<S>.plot.line/area/bar/pie/hist()              # Generates a plot. Accepts `title=<str>`.
-plt.show()                                     # Displays the plot. Also plt.savefig(<path>).
+<S>.plot.line/area/bar/pie/hist()              # Generates a plot. `plt.show()` displays it.
 ```
 * **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`!**
 * **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
+* **Series will silently overflow if we run `'pd.Series([100], dtype="int8") + 100'`.**
 
 #### Series — Aggregate, Transform, Map:
 ```python
@@ -3225,6 +3224,7 @@ plt.show()                                     # Displays the plot. Also plt.sav
 +--------------+-------------+-------------+---------------+
 ```
 * **Methods ffill(), interpolate(), fillna() and dropna() accept `'inplace=True'`.**
+* **Agg/transform() pass Series to functions that raise Type/Value/AttrError on single item.**
 * **Last result has a multi-index. Use `'<S>[key_1, key_2]'` to get its values.**
 
 ### DataFrame
diff --git a/index.html b/index.html
index 7ba2306e7..e6f46f496 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 3, 2024</aside>
+    <aside>December 4, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2582,7 +2582,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <pre><code class="python language-python hljs">&lt;S&gt;  = pd.Series(&lt;list&gt;)                       <span class="hljs-comment"># Creates index from list's indices.</span>
 &lt;S&gt;  = pd.Series(&lt;dict&gt;)                       <span class="hljs-comment"># Creates index from dictionary's keys.</span>
-&lt;S&gt;  = pd.Series(&lt;dict/Series&gt;, index=&lt;list&gt;)  <span class="hljs-comment"># Only keeps items with keys specified in index.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.loc[key]                            <span class="hljs-comment"># Or: &lt;S&gt;.iloc[i]</span>
 &lt;S&gt;  = &lt;S&gt;.loc[coll_of_keys]                   <span class="hljs-comment"># Or: &lt;S&gt;.iloc[coll_of_i]</span>
@@ -2599,12 +2598,12 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;S&gt; = &lt;S&gt;.combine_first(&lt;S&gt;)                   <span class="hljs-comment"># Adds items that are not yet present.</span>
 &lt;S&gt;.update(&lt;S&gt;)                                <span class="hljs-comment"># Updates items that are already present.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. Accepts `title=&lt;str&gt;`.</span>
-plt.show()                                     <span class="hljs-comment"># Displays the plot. Also plt.savefig(&lt;path&gt;).</span>
+<pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. `plt.show()` displays it.</span>
 </code></pre>
 <ul>
 <li><strong>Indexing objects can't be tuples 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>!</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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
+<li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>.</strong></li>
 </ul>
 <div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.sum/max/mean/idxmax/all()           <span class="hljs-comment"># Or: &lt;S&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;S&gt;  = &lt;S&gt;.rank/diff/cumsum/ffill/interpol…()  <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
@@ -2629,6 +2628,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <ul>
 <li><strong>Methods ffill(), interpolate(), fillna() and dropna() accept <code class="python hljs"><span class="hljs-string">'inplace=True'</span></code>.</strong></li>
+<li><strong>Agg/transform() pass Series to functions that raise Type/Value/AttrError on single item.</strong></li>
 <li><strong>Last result has a multi-index. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;[key_1, key_2]'</span></code> to get its values.</strong></li>
 </ul>
 <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">&gt;&gt;&gt; </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
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 3, 2024</aside>
+    <aside>December 4, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From e2ab4c9997dc0695c0924b1193d8665108ba8f20 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 4 Dec 2024 21:56:17 +0100
Subject: [PATCH 035/186] Memoryview, Plotly

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index b5ef95eb6..de711683e 100644
--- a/README.md
+++ b/README.md
@@ -2078,7 +2078,7 @@ Memory View
 ```
 
 ```python
-<list>  = list(<mview>)                        # Returns a list of ints, floats or bytes.
+<list>  = list(<mview>)                        # Returns a list of ints, floats, or bytes.
 <str>   = str(<mview>, 'utf-8')                # Treats memoryview as a bytes object.
 <str>   = <mview>.hex()                        # Returns hex pairs. Accepts `sep=<str>`.
 ```
@@ -3482,7 +3482,7 @@ def scrape_data():
 
 def wrangle_data(covid, bitcoin, gold, dow):
     df = pd.concat([bitcoin, gold, dow], axis=1)  # Creates table by joining columns on dates.
-    df = df.sort_index().interpolate()            # Sorts table by date and interpolates NaN-s.
+    df = df.sort_index().interpolate()            # Sorts rows by date and interpolates NaN-s.
     df = df.loc['2020-02-23':]                    # Discards rows before '2020-02-23'.
     df = (df / df.iloc[0]) * 100                  # Calculates percentages relative to day 1.
     df = df.join(covid)                           # Adds column with covid cases.
diff --git a/index.html b/index.html
index e6f46f496..316f8095e 100644
--- a/index.html
+++ b/index.html
@@ -1710,7 +1710,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;mview&gt;)         <span class="hljs-comment"># Treats memoryview as a sequence of numbers.</span>
 &lt;file&gt;.write(&lt;mview&gt;)                          <span class="hljs-comment"># Writes `bytes(&lt;mview&gt;)` to the binary file.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;list&gt;  = list(&lt;mview&gt;)                        <span class="hljs-comment"># Returns a list of ints, floats or bytes.</span>
+<pre><code class="python language-python hljs">&lt;list&gt;  = list(&lt;mview&gt;)                        <span class="hljs-comment"># Returns a list of ints, floats, or bytes.</span>
 &lt;str&gt;   = str(&lt;mview&gt;, <span class="hljs-string">'utf-8'</span>)                <span class="hljs-comment"># Treats memoryview as a bytes object.</span>
 &lt;str&gt;   = &lt;mview&gt;.hex()                        <span class="hljs-comment"># Returns hex pairs. Accepts `sep=&lt;str&gt;`.</span>
 </code></pre>
@@ -2829,7 +2829,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <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 table by joining columns on dates.</span>
-    df = df.sort_index().interpolate()            <span class="hljs-comment"># Sorts table by date and interpolates NaN-s.</span>
+    df = df.sort_index().interpolate()            <span class="hljs-comment"># Sorts rows by date and interpolates NaN-s.</span>
     df = df.loc[<span class="hljs-string">'2020-02-23'</span>:]                    <span class="hljs-comment"># Discards rows before '2020-02-23'.</span>
     df = (df / df.iloc[<span class="hljs-number">0</span>]) * <span class="hljs-number">100</span>                  <span class="hljs-comment"># Calculates percentages relative to day 1.</span>
     df = df.join(covid)                           <span class="hljs-comment"># Adds column with covid cases.</span>

From 64580a209ddc566a5469581e3cd8a02a90b54678 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 4 Dec 2024 22:08:08 +0100
Subject: [PATCH 036/186] Pandas

---
 README.md  | 2 +-
 index.html | 2 +-
 parse.js   | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index de711683e..a92923322 100644
--- a/README.md
+++ b/README.md
@@ -3291,7 +3291,7 @@ c  6  7
 |                       |    'outer'    |   'inner'  |   'left'   |       Description         |
 +-----------------------+---------------+------------+------------+---------------------------+
 | df.merge(df_2,        |    x   y   z  | x   y   z  | x   y   z  | Merges on column if 'on'  |
-|          on='y',      | 0  1   2   .  | 3   4   5  | 1   2   .  | or 'left/right_on' are    |
+|          on='y',      | 0  1   2   .  | 3   4   5  | 1   2   .  | or 'left_on/right_on' are |
 |          how=…)       | 1  3   4   5  |            | 3   4   5  | set, else on shared cols. |
 |                       | 2  .   6   7  |            |            | Uses 'inner' by default.  |
 +-----------------------+---------------+------------+------------+---------------------------+
diff --git a/index.html b/index.html
index 316f8095e..8e806278a 100644
--- a/index.html
+++ b/index.html
@@ -2675,7 +2675,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 ┃                       │    <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/right_on' are    ┃
+┃          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.  ┃
 ┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨
diff --git a/parse.js b/parse.js
index 232585772..0107a32bd 100755
--- a/parse.js
+++ b/parse.js
@@ -606,7 +606,7 @@ const DIAGRAM_15_B =
   "┃                       │    'outer'    │   'inner'  │   'left'   │       Description         ┃\n" +
   "┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨\n" +
   "┃ df.merge(df_2,        │    x   y   z  │ x   y   z  │ x   y   z  │ Merges on column if 'on'  ┃\n" +
-  "┃          on='y',      │ 0  1   2   .  │ 3   4   5  │ 1   2   .  │ or 'left/right_on' are    ┃\n" +
+  "┃          on='y',      │ 0  1   2   .  │ 3   4   5  │ 1   2   .  │ or 'left_on/right_on' are ┃\n" +
   "┃          how=…)       │ 1  3   4   5  │            │ 3   4   5  │ set, else on shared cols. ┃\n" +
   "┃                       │ 2  .   6   7  │            │            │ Uses 'inner' by default.  ┃\n" +
   "┠───────────────────────┼───────────────┼────────────┼────────────┼───────────────────────────┨\n" +
@@ -906,8 +906,8 @@ function fixPandasDiagram() {
   $(`code:contains(${diagram_15})`).find(".hljs-keyword:contains(or)").after("or");
   $(`code:contains(${diagram_15})`).find(".hljs-keyword:contains(else)").after("else");
   $(`code:contains(${diagram_15})`).find(".hljs-keyword").remove();
-  $(`code:contains(${diagram_15})`).find(".hljs-string:contains(\'left/right_on\')").after("\'left/right_on\'");
-  $(`code:contains(${diagram_15})`).find(".hljs-string:contains(\'left/right_on\')").remove();
+  $(`code:contains(${diagram_15})`).find(".hljs-string:contains(\'left_on/right_on\')").after("\'left_on/right_on\'");
+  $(`code:contains(${diagram_15})`).find(".hljs-string:contains(\'left_on/right_on\')").remove();
   $(`code:contains(${diagram_15})`).find(".hljs-string:contains('on')").after("'on'");
   $(`code:contains(${diagram_15})`).find(".hljs-string:contains('on')").remove();
 }

From 0782c2cdf928ef026d38e8c84a4890e8b5948a75 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 4 Dec 2024 23:14:55 +0100
Subject: [PATCH 037/186] Operator

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index a92923322..2fef6254f 100644
--- a/README.md
+++ b/README.md
@@ -2103,7 +2103,7 @@ from collections import deque
 
 Operator
 --------
-**Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence—from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.**
+**Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence, from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are ordered by precedence also within a group.**
 ```python
 import operator as op
 ```
diff --git a/index.html b/index.html
index 8e806278a..bf65fa607 100644
--- a/index.html
+++ b/index.html
@@ -1724,7 +1724,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;deque&gt;.rotate(n=<span class="hljs-number">1</span>)                            <span class="hljs-comment"># Last element becomes first.</span>
 &lt;el&gt; = &lt;deque&gt;.popleft()                       <span class="hljs-comment"># Raises IndexError if deque is empty.</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 ordered and grouped by operator precedence—from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> operator <span class="hljs-keyword">as</span> op
+<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 ordered and grouped by operator precedence, from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are ordered by precedence also within a group.</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>
 
 

From 449b7cf2ddc094c375ddfd0392c928f1759e5570 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 5 Dec 2024 07:23:03 +0100
Subject: [PATCH 038/186] SQLite

---
 README.md  | 2 +-
 index.html | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 2fef6254f..dfe53c387 100644
--- a/README.md
+++ b/README.md
@@ -1938,7 +1938,7 @@ with <conn>:                                   # Exits the block with commit() o
 from sqlalchemy import create_engine, text
 <engine> = create_engine('<url>')              # Url: 'dialect://user:password@host/dbname'.
 <conn>   = <engine>.connect()                  # Creates a connection. Also <conn>.close().
-<cursor> = <conn>.execute(text('<query>'), …)  # Replaces ':<key>'s with keyword arguments.
+<cursor> = <conn>.execute(text('<query>'), …)  # `<dict>`. Replaces ':<key>'s with values.
 with <conn>.begin(): ...                       # Exits the block with commit or rollback.
 ```
 
diff --git a/index.html b/index.html
index bf65fa607..d18dab7ec 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 4, 2024</aside>
+    <aside>December 5, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1602,7 +1602,7 @@
 <span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> create_engine, text
 &lt;engine&gt; = create_engine(<span class="hljs-string">'&lt;url&gt;'</span>)              <span class="hljs-comment"># Url: 'dialect://user:password@host/dbname'.</span>
 &lt;conn&gt;   = &lt;engine&gt;.connect()                  <span class="hljs-comment"># Creates a connection. Also &lt;conn&gt;.close().</span>
-&lt;cursor&gt; = &lt;conn&gt;.execute(text(<span class="hljs-string">'&lt;query&gt;'</span>), …)  <span class="hljs-comment"># Replaces ':&lt;key&gt;'s with keyword arguments.</span>
+&lt;cursor&gt; = &lt;conn&gt;.execute(text(<span class="hljs-string">'&lt;query&gt;'</span>), …)  <span class="hljs-comment"># `&lt;dict&gt;`. Replaces ':&lt;key&gt;'s with values.</span>
 <span class="hljs-keyword">with</span> &lt;conn&gt;.begin(): ...                       <span class="hljs-comment"># Exits the block with commit or rollback.</span>
 </code></pre></div>
 
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 4, 2024</aside>
+    <aside>December 5, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 6d85e2b3c1f3a4123453d876e9399c0b121d18ca Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 6 Dec 2024 20:51:50 +0100
Subject: [PATCH 039/186] Pandas

---
 README.md  |  6 +++---
 index.html | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index dfe53c387..e83499fbc 100644
--- a/README.md
+++ b/README.md
@@ -3164,8 +3164,8 @@ Name: a, dtype: int64
 ```
 
 ```python
-<S>  = pd.Series(<list>)                       # Creates index from list's indices.
-<S>  = pd.Series(<dict>)                       # Creates index from dictionary's keys.
+<S>  = pd.Series(<list>)                       # Uses list's indices for 'index'.
+<S>  = pd.Series(<dict>)                       # Uses dictionary's keys for 'index'.
 ```
 
 ```python
@@ -3365,7 +3365,7 @@ c  6  7
 <DF>.to_pickle/excel(<path>)                   # Run `$ pip3 install "pandas[excel]" odfpy`.
 <DF>.to_sql('<table_name>', <connection>)      # Also `if_exists='fail/replace/append'`.
 ```
-* **Read\_csv() only parses dates of columns that were specified by 'parse\_dates' argument. It automatically tries to detect the format, but it can be helped with 'date\_format' or 'datefirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.**
+* **Read\_csv() only parses dates of columns that were specified by 'parse\_dates' argument. It automatically tries to detect the format, but it can be helped with 'date\_format' or 'datefirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.**
 * **If there's a single invalid date then it returns the whole column as a series of strings, unlike `'<S> = pd.to_datetime(<S>, errors="coerce")'`, which uses pd.NaT.**
 * **To get specific attributes from a series of Timestamps use `'<S>.dt.year/date/…'`.**
 
diff --git a/index.html b/index.html
index d18dab7ec..68761a2d3 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 5, 2024</aside>
+    <aside>December 6, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2580,8 +2580,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 
-<pre><code class="python language-python hljs">&lt;S&gt;  = pd.Series(&lt;list&gt;)                       <span class="hljs-comment"># Creates index from list's indices.</span>
-&lt;S&gt;  = pd.Series(&lt;dict&gt;)                       <span class="hljs-comment"># Creates index from dictionary's keys.</span>
+<pre><code class="python language-python hljs">&lt;S&gt;  = pd.Series(&lt;list&gt;)                       <span class="hljs-comment"># Uses list's indices for 'index'.</span>
+&lt;S&gt;  = pd.Series(&lt;dict&gt;)                       <span class="hljs-comment"># Uses dictionary's keys for 'index'.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.loc[key]                            <span class="hljs-comment"># Or: &lt;S&gt;.iloc[i]</span>
 &lt;S&gt;  = &lt;S&gt;.loc[coll_of_keys]                   <span class="hljs-comment"># Or: &lt;S&gt;.iloc[coll_of_i]</span>
@@ -2741,7 +2741,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;DF&gt;.to_sql(<span class="hljs-string">'&lt;table_name&gt;'</span>, &lt;connection&gt;)      <span class="hljs-comment"># Also `if_exists='fail/replace/append'`.</span>
 </code></pre>
 <ul>
-<li><strong>Read_csv() only parses dates of columns that were specified by 'parse_dates' argument. It automatically tries to detect the format, but it can be helped with 'date_format' or 'datefirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.</strong></li>
+<li><strong>Read_csv() only parses dates of columns that were specified by 'parse_dates' argument. It&nbsp;automatically tries to detect the format, but it can be helped with 'date_format' or 'datefirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.</strong></li>
 <li><strong>If there's a single invalid date then it returns the whole column as a series of strings, unlike <code class="python hljs"><span class="hljs-string">'&lt;S&gt; = pd.to_datetime(&lt;S&gt;, errors="coerce")'</span></code>, which uses pd.NaT.</strong></li>
 <li><strong>To get specific attributes from a series of Timestamps use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.dt.year/date/…'</span></code>.</strong></li>
 </ul>
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 5, 2024</aside>
+    <aside>December 6, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From c2ed921b2a94dc422c83e0e05677f918fd657c33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 7 Dec 2024 17:18:57 +0100
Subject: [PATCH 040/186] Pandas

---
 README.md  | 2 +-
 index.html | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index e83499fbc..35113d9e0 100644
--- a/README.md
+++ b/README.md
@@ -3224,7 +3224,7 @@ Name: a, dtype: int64
 +--------------+-------------+-------------+---------------+
 ```
 * **Methods ffill(), interpolate(), fillna() and dropna() accept `'inplace=True'`.**
-* **Agg/transform() pass Series to functions that raise Type/Value/AttrError on single item.**
+* **Agg() and transform() pass a Series to a function if it raises Type/Val/AttrError on a scalar.**
 * **Last result has a multi-index. Use `'<S>[key_1, key_2]'` to get its values.**
 
 ### DataFrame
diff --git a/index.html b/index.html
index 68761a2d3..933e8d942 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 6, 2024</aside>
+    <aside>December 7, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2628,7 +2628,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <ul>
 <li><strong>Methods ffill(), interpolate(), fillna() and dropna() accept <code class="python hljs"><span class="hljs-string">'inplace=True'</span></code>.</strong></li>
-<li><strong>Agg/transform() pass Series to functions that raise Type/Value/AttrError on single item.</strong></li>
+<li><strong>Agg() and transform() pass a Series to a function if it raises Type/Val/AttrError on a scalar.</strong></li>
 <li><strong>Last result has a multi-index. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;[key_1, key_2]'</span></code> to get its values.</strong></li>
 </ul>
 <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">&gt;&gt;&gt; </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
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 6, 2024</aside>
+    <aside>December 7, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From b85b68997736838f24dc1ff17d7d2efe0d0d4a31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 7 Dec 2024 18:24:34 +0100
Subject: [PATCH 041/186] Pygame

---
 README.md  | 4 ++--
 index.html | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 35113d9e0..ee97bd5b0 100644
--- a/README.md
+++ b/README.md
@@ -3008,10 +3008,10 @@ while not pg.event.get(pg.QUIT):
     pg.display.flip()
 ```
 
-### Rectangle
+### Rect
 **Object for storing rectangular coordinates.**
 ```python
-<Rect> = pg.Rect(x, y, width, height)           # Returns a rectangle. Floats get truncated.
+<Rect> = pg.Rect(x, y, width, height)           # Creates Rect object. Truncates passed floats.
 <int>  = <Rect>.x/y/centerx/centery/…           # Top, right, bottom, left. Allows assignments.
 <tup.> = <Rect>.topleft/center/…                # Topright, bottomright, bottomleft. Same.
 <Rect> = <Rect>.move((delta_x, delta_y))        # Use move_ip() to move in-place.
diff --git a/index.html b/index.html
index 933e8d942..12fba5274 100644
--- a/index.html
+++ b/index.html
@@ -2451,7 +2451,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     pg.display.flip()
 </code></pre></div>
 
-<div><h3 id="rectangle">Rectangle</h3><p><strong>Object for storing rectangular coordinates.</strong></p><pre><code class="python language-python hljs">&lt;Rect&gt; = pg.Rect(x, y, width, height)           <span class="hljs-comment"># Returns a rectangle. Floats get truncated.</span>
+<div><h3 id="rect">Rect</h3><p><strong>Object for storing rectangular coordinates.</strong></p><pre><code class="python language-python hljs">&lt;Rect&gt; = pg.Rect(x, y, width, height)           <span class="hljs-comment"># Creates Rect object. Truncates passed floats.</span>
 &lt;int&gt;  = &lt;Rect&gt;.x/y/centerx/centery/…           <span class="hljs-comment"># Top, right, bottom, left. Allows assignments.</span>
 &lt;tup.&gt; = &lt;Rect&gt;.topleft/center/…                <span class="hljs-comment"># Topright, bottomright, bottomleft. Same.</span>
 &lt;Rect&gt; = &lt;Rect&gt;.move((delta_x, delta_y))        <span class="hljs-comment"># Use move_ip() to move in-place.</span>

From fbcf68b441a014838dd65b81f001c22fda5c4803 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 7 Dec 2024 18:34:42 +0100
Subject: [PATCH 042/186] Cython

---
 README.md  | 4 ++--
 index.html | 4 ++--
 parse.js   | 6 +++---
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index ee97bd5b0..f7b6b48c5 100644
--- a/README.md
+++ b/README.md
@@ -3525,8 +3525,8 @@ import <cython_script>
 * **Script needs to be saved with a `'pyx'` extension.**
 
 ```python
-cdef <ctype> <var_name> = <obj>
-cdef <ctype>[n_elements] <var_name> = [<el_1>, <el_2>, ...]
+cdef <ctype> <var_name> [= <obj>]
+cdef <ctype>[n_elements] <var_name> [= <collection>]
 cdef <ctype/void> <func_name>(<ctype> <arg_name>): ...
 ```
 
diff --git a/index.html b/index.html
index 12fba5274..e19d5f0e5 100644
--- a/index.html
+++ b/index.html
@@ -2867,8 +2867,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <div><h4 id="definitions">Definitions:</h4><ul>
 <li><strong>All <code class="python hljs"><span class="hljs-string">'cdef'</span></code> definitions are optional, but they contribute to the speed-up.</strong></li>
 <li><strong>Script needs to be saved with a <code class="python hljs"><span class="hljs-string">'pyx'</span></code> extension.</strong></li>
-</ul><pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> &lt;ctype&gt; &lt;var_name&gt; = &lt;obj&gt;
-<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; = [&lt;el_1&gt;, &lt;el_2&gt;, ...]
+</ul><pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> &lt;ctype&gt; &lt;var_name&gt; [= &lt;obj&gt;]
+<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;collection&gt;]
 <span class="hljs-keyword">cdef</span> &lt;ctype/void&gt; &lt;func_name&gt;(&lt;ctype&gt; &lt;arg_name&gt;): ...
 </code></pre></div>
 
diff --git a/parse.js b/parse.js
index 0107a32bd..f3bd88903 100755
--- a/parse.js
+++ b/parse.js
@@ -320,8 +320,8 @@ const GROUPBY =
 
 
 const CYTHON_1 =
-  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; &lt;var_name&gt; = &lt;obj&gt;\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; = [&lt;el_1&gt;, &lt;el_2&gt;, ...]\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; &lt;var_name&gt; [= &lt;obj&gt;]\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;collection&gt;]\n' +
   '<span class="hljs-keyword">cdef</span> &lt;ctype/void&gt; &lt;func_name&gt;(&lt;ctype&gt; &lt;arg_name&gt;): ...\n';
 
 const CYTHON_2 =
@@ -851,7 +851,7 @@ function fixHighlights() {
   $(`code:contains(samples_f = (sin(i *)`).html(AUDIO_2);
   $(`code:contains(collections, dataclasses, enum, io, itertools)`).html(MARIO);
   $(`code:contains(>>> gb = df.groupby)`).html(GROUPBY);
-  $(`code:contains(cdef <ctype> <var_name> = <obj>)`).html(CYTHON_1);
+  $(`code:contains(cdef <ctype> <var_name> [= <obj>])`).html(CYTHON_1);
   $(`code:contains(cdef class <class_name>:)`).html(CYTHON_2);
   $(`code:contains(cdef enum <enum_name>: <member_name>, <member_name>, ...)`).html(CYTHON_3);
   $(`ul:contains(Only available in)`).html(INDEX);

From 907f39fcbc3826beed63054e6979235b8e07c634 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 9 Dec 2024 21:58:36 +0100
Subject: [PATCH 043/186] Cython

---
 README.md  | 10 +++++-----
 index.html | 14 +++++++-------
 parse.js   | 12 ++++++------
 3 files changed, 18 insertions(+), 18 deletions(-)

diff --git a/README.md b/README.md
index f7b6b48c5..db4e9d88f 100644
--- a/README.md
+++ b/README.md
@@ -3525,15 +3525,15 @@ import <cython_script>
 * **Script needs to be saved with a `'pyx'` extension.**
 
 ```python
-cdef <ctype> <var_name> [= <obj>]
-cdef <ctype>[n_elements] <var_name> [= <collection>]
-cdef <ctype/void> <func_name>(<ctype> <arg_name>): ...
+cdef <ctype/type> <var_name> [= <obj>]
+cdef <ctype>[n_elements] <var_name> [= <coll_of_nums>]
+cdef <ctype/type/void> <func_name>(<ctype/type> <arg_name>): ...
 ```
 
 ```python
 cdef class <class_name>:
-    cdef public <ctype> <attr_name>
-    def __init__(self, <ctype> <arg_name>):
+    cdef public <ctype/type> <attr_name>
+    def __init__(self, <ctype/type> <arg_name>):
         self.<attr_name> = <arg_name>
 ```
 
diff --git a/index.html b/index.html
index e19d5f0e5..b22faa747 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 7, 2024</aside>
+    <aside>December 9, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2867,15 +2867,15 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <div><h4 id="definitions">Definitions:</h4><ul>
 <li><strong>All <code class="python hljs"><span class="hljs-string">'cdef'</span></code> definitions are optional, but they contribute to the speed-up.</strong></li>
 <li><strong>Script needs to be saved with a <code class="python hljs"><span class="hljs-string">'pyx'</span></code> extension.</strong></li>
-</ul><pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> &lt;ctype&gt; &lt;var_name&gt; [= &lt;obj&gt;]
-<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;collection&gt;]
-<span class="hljs-keyword">cdef</span> &lt;ctype/void&gt; &lt;func_name&gt;(&lt;ctype&gt; &lt;arg_name&gt;): ...
+</ul><pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; &lt;var_name&gt; [= &lt;obj&gt;]
+<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;coll_of_nums&gt;]
+<span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; &lt;arg_name&gt;): ...
 </code></pre></div>
 
 
 <pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>
-    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype&gt; &lt;attr_name&gt;
-    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype&gt; &lt;arg_name&gt;)</span>:</span>
+    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype/type&gt; &lt;attr_name&gt;
+    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; &lt;arg_name&gt;)</span>:</span>
         self.&lt;attr_name&gt; = &lt;arg_name&gt;
 </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="bash language-bash hljs">$ python3 -m venv NAME      <span class="hljs-comment"># Creates virtual environment in current directory.</span>
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 7, 2024</aside>
+    <aside>December 9, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index f3bd88903..fa5f10011 100755
--- a/parse.js
+++ b/parse.js
@@ -320,14 +320,14 @@ const GROUPBY =
 
 
 const CYTHON_1 =
-  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; &lt;var_name&gt; [= &lt;obj&gt;]\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;collection&gt;]\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype/void&gt; &lt;func_name&gt;(&lt;ctype&gt; &lt;arg_name&gt;): ...\n';
+  '<span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; &lt;var_name&gt; [= &lt;obj&gt;]\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;coll_of_nums&gt;]\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; &lt;arg_name&gt;): ...\n';
 
 const CYTHON_2 =
   '<span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>\n' +
-  '    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype&gt; &lt;attr_name&gt;\n' +
-  '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype&gt; &lt;arg_name&gt;)</span>:</span>\n' +
+  '    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype/type&gt; &lt;attr_name&gt;\n' +
+  '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; &lt;arg_name&gt;)</span>:</span>\n' +
   '        self.&lt;attr_name&gt; = &lt;arg_name&gt;\n';
 
 const CYTHON_3 =
@@ -851,7 +851,7 @@ function fixHighlights() {
   $(`code:contains(samples_f = (sin(i *)`).html(AUDIO_2);
   $(`code:contains(collections, dataclasses, enum, io, itertools)`).html(MARIO);
   $(`code:contains(>>> gb = df.groupby)`).html(GROUPBY);
-  $(`code:contains(cdef <ctype> <var_name> [= <obj>])`).html(CYTHON_1);
+  $(`code:contains(cdef <ctype/type> <var_name> [= <obj>])`).html(CYTHON_1);
   $(`code:contains(cdef class <class_name>:)`).html(CYTHON_2);
   $(`code:contains(cdef enum <enum_name>: <member_name>, <member_name>, ...)`).html(CYTHON_3);
   $(`ul:contains(Only available in)`).html(INDEX);

From 3183af6b42c06a1f7b13797ec2382934219ba9c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 10 Dec 2024 02:12:10 +0100
Subject: [PATCH 044/186] Cython

---
 README.md  | 10 +++++-----
 index.html | 14 +++++++-------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
index db4e9d88f..21caa408e 100644
--- a/README.md
+++ b/README.md
@@ -3511,18 +3511,18 @@ if __name__ == '__main__':
 Appendix
 --------
 ### Cython
-**Library that compiles Python code into C.**
+**Library that compiles Python-like code into C.**
 
 ```python
 # $ pip3 install cython
-import pyximport; pyximport.install()
-import <cython_script>
-<cython_script>.main()
+import pyximport; pyximport.install()  # Module that runs imported Cython scripts.
+import <cython_script>                 # Script needs a '.pyx' extension.
+<cython_script>.main()                 # Main() isn't automatically executed.
 ```
 
 #### Definitions:
 * **All `'cdef'` definitions are optional, but they contribute to the speed-up.**
-* **Script needs to be saved with a `'pyx'` extension.**
+* **Also supports C pointers via `'*'` and `'&'`, structs, unions, and enums.**
 
 ```python
 cdef <ctype/type> <var_name> [= <obj>]
diff --git a/index.html b/index.html
index b22faa747..64862d916 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 9, 2024</aside>
+    <aside>December 10, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2856,17 +2856,17 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<div><h2 id="appendix"><a href="#appendix" name="appendix">#</a>Appendix</h2><div><h3 id="cython">Cython</h3><p><strong>Library that compiles Python 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-keyword">import</span> &lt;cython_script&gt;
-&lt;cython_script&gt;.main()
+<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 imported Cython scripts.</span>
+<span class="hljs-keyword">import</span> &lt;cython_script&gt;                 <span class="hljs-comment"># Script needs a '.pyx' extension.</span>
+&lt;cython_script&gt;.main()                 <span class="hljs-comment"># Main() isn't automatically executed.</span>
 </code></pre></div></div>
 
 
 
 <div><h4 id="definitions">Definitions:</h4><ul>
 <li><strong>All <code class="python hljs"><span class="hljs-string">'cdef'</span></code> definitions are optional, but they contribute to the speed-up.</strong></li>
-<li><strong>Script needs to be saved with a <code class="python hljs"><span class="hljs-string">'pyx'</span></code> extension.</strong></li>
+<li><strong>Also supports C pointers via <code class="python hljs"><span class="hljs-string">'*'</span></code> and <code class="python hljs"><span class="hljs-string">'&amp;'</span></code>, structs, unions, and enums.</strong></li>
 </ul><pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; &lt;var_name&gt; [= &lt;obj&gt;]
 <span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;coll_of_nums&gt;]
 <span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; &lt;arg_name&gt;): ...
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 9, 2024</aside>
+    <aside>December 10, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From b00c3d99a65701e93152ce1f7fe67b48c22d8077 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 10 Dec 2024 12:01:47 +0100
Subject: [PATCH 045/186] Input, Cython

---
 README.md  | 8 ++++----
 index.html | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 21caa408e..654f3be5d 100644
--- a/README.md
+++ b/README.md
@@ -1531,11 +1531,11 @@ pprint(<collection>, width=80, depth=None, compact=False, sort_dicts=True)
 Input
 -----
 ```python
-<str> = input(prompt=None)
+<str> = input([<obj>])
 ```
 * **Reads a line from the user input or pipe if present (trailing newline gets stripped).**
-* **Prompt string is printed to the standard output before input is read.**
-* **Raises EOFError when user hits EOF (ctrl-d/ctrl-z⏎) or input stream gets exhausted.**
+* **If argument is passed, it gets printed to the standard output before input is read.**
+* **EOFError is raised if user hits EOF (ctrl-d/ctrl-z⏎) or input stream gets exhausted.**
 
 
 Command Line Arguments
@@ -3516,7 +3516,7 @@ Appendix
 ```python
 # $ pip3 install cython
 import pyximport; pyximport.install()  # Module that runs imported Cython scripts.
-import <cython_script>                 # Script needs a '.pyx' extension.
+import <cython_script>                 # Script's filename needs a '.pyx' extension.
 <cython_script>.main()                 # Main() isn't automatically executed.
 ```
 
diff --git a/index.html b/index.html
index 64862d916..48a2873c0 100644
--- a/index.html
+++ b/index.html
@@ -1294,13 +1294,13 @@
 <li><strong>Each item is printed on its own line if collection exceeds 'width' characters.</strong></li>
 <li><strong>Nested collections that are 'depth' levels deep get printed as '…'.</strong></li>
 </ul>
-<div><h2 id="input"><a href="#input" name="input">#</a>Input</h2><pre><code class="python language-python hljs">&lt;str&gt; = input(prompt=<span class="hljs-keyword">None</span>)
+<div><h2 id="input"><a href="#input" name="input">#</a>Input</h2><pre><code class="python language-python hljs">&lt;str&gt; = input([&lt;obj&gt;])
 </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>Prompt string is printed to the standard output before input is read.</strong></li>
-<li><strong>Raises EOFError when user hits EOF (ctrl-d/ctrl-z⏎) or input stream gets exhausted.</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 input stream gets exhausted.</strong></li>
 </ul>
 <div><h2 id="commandlinearguments"><a href="#commandlinearguments" name="commandlinearguments">#</a>Command Line 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>]
@@ -2858,7 +2858,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <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 imported Cython scripts.</span>
-<span class="hljs-keyword">import</span> &lt;cython_script&gt;                 <span class="hljs-comment"># Script needs a '.pyx' extension.</span>
+<span class="hljs-keyword">import</span> &lt;cython_script&gt;                 <span class="hljs-comment"># Script's filename needs a '.pyx' extension.</span>
 &lt;cython_script&gt;.main()                 <span class="hljs-comment"># Main() isn't automatically executed.</span>
 </code></pre></div></div>
 

From db1bcb964dc9ccc4645b47a002447980ec2a81a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 11 Dec 2024 00:22:57 +0100
Subject: [PATCH 046/186] Match statement

---
 index.html | 6 +++---
 parse.js   | 7 +++++++
 2 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/index.html b/index.html
index 48a2873c0..b375f4abf 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 10, 2024</aside>
+    <aside>December 11, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1778,7 +1778,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <span class="hljs-meta">... </span>        parts=[<span class="hljs-string">'/'</span>, <span class="hljs-string">'home'</span>, user, *_]
 <span class="hljs-meta">... </span>    ) <span class="hljs-keyword">as</span> p <span class="hljs-keyword">if</span> p.name.lower().startswith(<span class="hljs-string">'readme'</span>) <span class="hljs-keyword">and</span> p.is_file():
 <span class="hljs-meta">... </span>        print(<span class="hljs-string">f'<span class="hljs-subst">{p.name}</span> is a readme file that belongs to user <span class="hljs-subst">{user}</span>.'</span>)
-<span class="hljs-string">'README.md is a readme file that belongs to user gto.'</span>
+README.md is a readme file that belongs to user gto.
 </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
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 10, 2024</aside>
+    <aside>December 11, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index fa5f10011..e592db829 100755
--- a/parse.js
+++ b/parse.js
@@ -733,6 +733,7 @@ function modifyPage() {
   unindentBanner();
   updateDiagrams();
   highlightCode();
+  fixMatchHighlights();
   fixPandasDiagram();
   removePlotImages();
   fixABCSequenceDiv();
@@ -897,6 +898,12 @@ function insertPageBreakBefore(an_id) {
   $('<div class="pagebreak"></div>').insertBefore($(an_id).parent())
 }
 
+function fixMatchHighlights() {
+  const line = $(`span:contains(README.md is a readme file that belongs to user gto.)`);
+  line.after('README.md is a readme file that belongs to user gto.');
+  line.remove();
+}
+
 function fixPandasDiagram() {
   const diagram_15 = '┏━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━┓';
   $(`code:contains(${diagram_15})`).find(".hljs-keyword:contains(and)").after("and");

From 35bec326dfcc41d874fb2334bd1da377be92b57d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 11 Dec 2024 07:55:49 +0100
Subject: [PATCH 047/186] Pygame

---
 README.md  |  3 ++-
 index.html | 11 ++++++-----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 654f3be5d..cd4607042 100644
--- a/README.md
+++ b/README.md
@@ -2991,6 +2991,7 @@ simpleaudio.play_buffer(samples_i, 1, 2, F).wait_done()
 
 Pygame
 ------
+#### Opes a window and draws a square that can be moved with arrow keys:
 ```python
 # $ pip3 install pygame
 import pygame as pg
@@ -3006,6 +3007,7 @@ while not pg.event.get(pg.QUIT):
     screen.fill(pg.Color('black'))
     pg.draw.rect(screen, pg.Color('white'), rect)
     pg.display.flip()
+pg.quit()
 ```
 
 ### Rect
@@ -3054,7 +3056,6 @@ arc(<Surf>, color, <Rect>, from_rad, to_rad)    # Also ellipse(<Surf>, color, <R
 rect(<Surf>, color, <Rect>, width=0)            # Also polygon(<Surf>, color, points, width=0).
 ```
 
-### Font
 ```python
 <Font> = pg.font.Font(<path/file>, size)        # Loads TTF file. Pass None for default font.
 <Surf> = <Font>.render(text, antialias, color)  # Background color can be specified at the end.
diff --git a/index.html b/index.html
index b375f4abf..40f7a2760 100644
--- a/index.html
+++ b/index.html
@@ -2435,7 +2435,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div></div>
 
 
-<div><h2 id="pygame"><a href="#pygame" name="pygame">#</a>Pygame</h2><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pygame</span>
+<div><h2 id="pygame"><a href="#pygame" name="pygame">#</a>Pygame</h2><div><h4 id="opesawindowanddrawsasquarethatcanbemovedwitharrowkeys">Opes 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()
@@ -2449,7 +2449,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     screen.fill(pg.Color(<span class="hljs-string">'black'</span>))
     pg.draw.rect(screen, pg.Color(<span class="hljs-string">'white'</span>), rect)
     pg.display.flip()
-</code></pre></div>
+pg.quit()
+</code></pre></div></div>
+
 
 <div><h3 id="rect">Rect</h3><p><strong>Object for storing rectangular coordinates.</strong></p><pre><code class="python language-python hljs">&lt;Rect&gt; = pg.Rect(x, y, width, height)           <span class="hljs-comment"># Creates Rect object. Truncates passed floats.</span>
 &lt;int&gt;  = &lt;Rect&gt;.x/y/centerx/centery/…           <span class="hljs-comment"># Top, right, bottom, left. Allows assignments.</span>
@@ -2485,10 +2487,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 arc(&lt;Surf&gt;, color, &lt;Rect&gt;, from_rad, to_rad)    <span class="hljs-comment"># Also ellipse(&lt;Surf&gt;, color, &lt;Rect&gt;, width=0).</span>
 rect(&lt;Surf&gt;, color, &lt;Rect&gt;, width=<span class="hljs-number">0</span>)            <span class="hljs-comment"># Also polygon(&lt;Surf&gt;, color, points, width=0).</span>
 </code></pre>
-<div><h3 id="font">Font</h3><pre><code class="python language-python hljs">&lt;Font&gt; = pg.font.Font(&lt;path/file&gt;, size)        <span class="hljs-comment"># Loads TTF file. Pass None for default font.</span>
+<pre><code class="python language-python hljs">&lt;Font&gt; = pg.font.Font(&lt;path/file&gt;, size)        <span class="hljs-comment"># Loads TTF file. Pass None for default font.</span>
 &lt;Surf&gt; = &lt;Font&gt;.render(text, antialias, color)  <span class="hljs-comment"># Background color can be specified at the end.</span>
-</code></pre></div>
-
+</code></pre>
 <div><h3 id="sound">Sound</h3><pre><code class="python language-python hljs">&lt;Sound&gt; = pg.mixer.Sound(&lt;path/file/bytes&gt;)     <span class="hljs-comment"># WAV file or bytes/array of signed shorts.</span>
 &lt;Sound&gt;.play/stop()                             <span class="hljs-comment"># Also set_volume(&lt;float&gt;), fadeout(msec).</span>
 </code></pre></div>

From 6ec61eafcaed1e63a177c9a7836578b1b6daf149 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 13 Dec 2024 11:45:49 +0100
Subject: [PATCH 048/186] NumPy

---
 README.md  | 11 +++++------
 index.html | 19 ++++++++-----------
 2 files changed, 13 insertions(+), 17 deletions(-)

diff --git a/README.md b/README.md
index cd4607042..1637037eb 100644
--- a/README.md
+++ b/README.md
@@ -2710,7 +2710,7 @@ import numpy as np
 <1/2d_arr> = <2d>[<2d/1d_bools>]                        # 1d_bools must have size of a column.
 ```
 * **`':'` returns a slice of all dimension's indices. Omitted dimensions default to `':'`.**
-* **Sixth line fails if tuple is used because Python converts `'obj[i, j]'` to `'obj[(i, j)]'`!**
+* **Python converts `'obj[i, j]'` to `'obj[(i, j)]'`. This makes `'<2d>[row_i, col_i]'` and `'<2d>[row_indices]'` indistinguishable to NumPy if tuple of indices is passed!**
 * **Indexing with a slice and 1d array works the same as when using two slices (lines 4, 6, 7).**
 * **`'ix_([1, 2], [3, 4])'` returns `'[[1], [2]]'` and `'[[3, 4]]'`. Due to broadcasting rules, this is the same as using `'[[1, 1], [2, 2]]'` and `'[[3, 4], [3, 4]]'`.**
 * **Any value that is broadcastable to the indexed shape can be assigned to the selection.**
@@ -2734,7 +2734,9 @@ right = [[0.1], [0.6], [0.8]]                           # Shape: (3, 1)
 left  = [[0.1,  0.6,  0.8],                             # Shape: (3, 3) <- !
          [0.1,  0.6,  0.8],
          [0.1,  0.6,  0.8]]
+```
 
+```python
 right = [[0.1,  0.1,  0.1],                             # Shape: (3, 3) <- !
          [0.6,  0.6,  0.6],
          [0.8,  0.8,  0.8]]
@@ -2748,14 +2750,11 @@ right = [[0.1,  0.1,  0.1],                             # Shape: (3, 3) <- !
 [ 0.1,  0.6,  0.8 ]
 >>> wrapped_points = points.reshape(3, 1)
 [[0.1], [0.6], [0.8]]
->>> distances = points - wrapped_points
+>>> deltas = points - wrapped_points
 [[ 0. ,  0.5,  0.7],
  [-0.5,  0. ,  0.2],
  [-0.7, -0.2,  0. ]]
->>> distances = np.abs(distances)
-[[ 0. ,  0.5,  0.7],
- [ 0.5,  0. ,  0.2],
- [ 0.7,  0.2,  0. ]]
+>>> distances = np.abs(deltas)
 >>> distances[range(3), range(3)] = np.inf
 [[ inf,  0.5,  0.7],
  [ 0.5,  inf,  0.2],
diff --git a/index.html b/index.html
index 40f7a2760..da850a308 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 11, 2024</aside>
+    <aside>December 13, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2211,7 +2211,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <ul>
 <li><strong><code class="python hljs"><span class="hljs-string">':'</span></code> returns a slice of all dimension's indices. Omitted dimensions default to <code class="python hljs"><span class="hljs-string">':'</span></code>.</strong></li>
-<li><strong>Sixth line fails if tuple is used because 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>!</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">'&lt;2d&gt;[row_i, col_i]'</span></code> and <code class="python hljs"><span class="hljs-string">'&lt;2d&gt;[row_indices]'</span></code> indistinguishable to NumPy if tuple of indices is passed!</strong></li>
 <li><strong>Indexing with a slice and 1d array works the same as when using two slices (lines 4, 6, 7).</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 using <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>
@@ -2228,24 +2228,21 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <div><h4 id="2ifanydimensionsdifferinsizeexpandtheonesthathavesize1byduplicatingtheirelements">2. If any dimensions differ in size, expand the ones that have size 1 by duplicating their elements:</h4><pre><code class="python language-python hljs">left  = [[<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"># Shape: (3, 3) &lt;- !</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>]]
+</code></pre></div>
 
-right = [[<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"># Shape: (3, 3) &lt;- !</span>
+<pre><code class="python language-python hljs">right = [[<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"># Shape: (3, 3) &lt;- !</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>
-
+</code></pre>
 <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>] =&gt; [<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">&gt;&gt;&gt; </span>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">&gt;&gt;&gt; </span>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">&gt;&gt;&gt; </span>distances = points - wrapped_points
+<span class="hljs-meta">&gt;&gt;&gt; </span>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">&gt;&gt;&gt; </span>distances = np.abs(distances)
-[[ <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">&gt;&gt;&gt; </span>distances = np.abs(deltas)
 <span class="hljs-meta">&gt;&gt;&gt; </span>distances[range(<span class="hljs-number">3</span>), range(<span class="hljs-number">3</span>)] = np.inf
 [[ 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>],
@@ -2925,7 +2922,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 11, 2024</aside>
+    <aside>December 13, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 952214829fc41a680f00cd5dc20bf92a05d10219 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 14 Dec 2024 04:36:23 +0100
Subject: [PATCH 049/186] Pandas

---
 README.md  | 4 ++--
 index.html | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 1637037eb..0c2ed3f34 100644
--- a/README.md
+++ b/README.md
@@ -3344,8 +3344,8 @@ c  6  7
 
 #### DataFrame — Multi-Index:
 ```python
-<DF>   = <DF>.xs(row_key, level=<int>)         # Rows with key on passed level of multi-index.
-<DF>   = <DF>.xs(row_keys, level=<ints>)       # Rows that have first key on first level, etc.
+<DF>   = <DF>.xs(key, level=<int>)             # Rows with key on passed level of multi-index.
+<DF>   = <DF>.xs(keys, level=<ints>, axis=1)   # Cols that have first key on first level, etc.
 <DF>   = <DF>.set_index(col_keys)              # Combines multiple columns into a multi-index.
 <S/DF> = <DF>.stack/unstack(level=-1)          # Combines col keys with row keys or vice versa.
 <DF>   = <DF>.pivot_table(index=col_key/s)     # `columns=key/s, values=key/s, aggfunc='mean'`.
diff --git a/index.html b/index.html
index da850a308..a2f010a3c 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 13, 2024</aside>
+    <aside>December 14, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2720,8 +2720,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>All methods operate on columns by default. Pass <code class="python hljs"><span class="hljs-string">'axis=1'</span></code> to process the rows instead.</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">'&lt;DF&gt;.loc[row_key, (col_key_1, col_key_2)]'</span></code>.</strong></li>
 </ul>
-<div><h4 id="dataframemultiindex">DataFrame — Multi-Index:</h4><pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt;.xs(row_key, level=&lt;int&gt;)         <span class="hljs-comment"># Rows with key on passed level of multi-index.</span>
-&lt;DF&gt;   = &lt;DF&gt;.xs(row_keys, level=&lt;ints&gt;)       <span class="hljs-comment"># Rows that have first key on first level, etc.</span>
+<div><h4 id="dataframemultiindex">DataFrame — Multi-Index:</h4><pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt;.xs(key, level=&lt;int&gt;)             <span class="hljs-comment"># Rows with key on passed level of multi-index.</span>
+&lt;DF&gt;   = &lt;DF&gt;.xs(keys, level=&lt;ints&gt;, axis=<span class="hljs-number">1</span>)   <span class="hljs-comment"># Cols that have first key on first level, etc.</span>
 &lt;DF&gt;   = &lt;DF&gt;.set_index(col_keys)              <span class="hljs-comment"># Combines multiple columns into a multi-index.</span>
 &lt;S/DF&gt; = &lt;DF&gt;.stack/unstack(level=<span class="hljs-number">-1</span>)          <span class="hljs-comment"># Combines col keys with row keys or vice versa.</span>
 &lt;DF&gt;   = &lt;DF&gt;.pivot_table(index=col_key/s)     <span class="hljs-comment"># `columns=key/s, values=key/s, aggfunc='mean'`.</span>
@@ -2922,7 +2922,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 13, 2024</aside>
+    <aside>December 14, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 94cc0649fa1451d8169d8ad6c1e484b58d24dc98 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 14 Dec 2024 11:17:31 +0100
Subject: [PATCH 050/186] List

---
 README.md           | 6 +++---
 index.html          | 6 +++---
 pdf/remove_links.py | 6 +++---
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/README.md b/README.md
index 0c2ed3f34..cfa09566e 100644
--- a/README.md
+++ b/README.md
@@ -60,9 +60,9 @@ sorted_by_second = sorted(<collection>, key=lambda el: el[1])
 sorted_by_both   = sorted(<collection>, key=lambda el: (el[1], el[0]))
 flatter_list     = list(itertools.chain.from_iterable(<list>))
 ```
-* **For details about sort(), sorted(), min() and max() see [sortable](#sortable).**
+* **For details about sort(), sorted(), min() and max() see [Sortable](#sortable).**
 * **Module [operator](#operator) has function itemgetter() that can replace listed [lambdas](#lambda).**
-* **This text uses the term 'collection' instead of 'iterable'. For rationale see [collection](#collection).**
+* **This text uses the term collection instead of iterable. For rationale see [Collection](#collection).**
 
 ```python
 <int> = len(<list>)             # Returns number of items. Also works on dict, set and string.
@@ -1420,7 +1420,7 @@ except (<exception>, [...]) as <name>: ...
 * **Also catches subclasses of the exception.**
 * **Use `'traceback.print_exc()'` to print the full error message to stderr.**
 * **Use `'print(<name>)'` to print just the cause of the exception (its arguments).**
-* **Use `'logging.exception(<str>)'` to log the passed message, followed by the full error message of the caught exception. For details see [logging](#logging).**
+* **Use `'logging.exception(<str>)'` to log the passed message, followed by the full error message of the caught exception. For details see [Logging](#logging).**
 * **Use `'sys.exc_info()'` to get exception type, object, and traceback of caught exception.**
 
 ### Raising Exceptions
diff --git a/index.html b/index.html
index a2f010a3c..9e97a0a69 100644
--- a/index.html
+++ b/index.html
@@ -123,9 +123,9 @@
 flatter_list     = list(itertools.chain.from_iterable(&lt;list&gt;))
 </code></pre>
 <ul>
-<li><strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong></li>
+<li><strong>For details about sort(), sorted(), min() and max() 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 'iterable'. For rationale see <a href="#collection">collection</a>.</strong></li>
+<li><strong>This text uses the term collection instead of iterable. For rationale see <a href="#collection">Collection</a>.</strong></li>
 </ul>
 <pre><code class="python language-python hljs">&lt;int&gt; = len(&lt;list&gt;)             <span class="hljs-comment"># Returns number of items. Also works on dict, set and string.</span>
 &lt;int&gt; = &lt;list&gt;.count(&lt;el&gt;)      <span class="hljs-comment"># Returns number of occurrences. Also `if &lt;el&gt; in &lt;coll&gt;: ...`.</span>
@@ -1207,7 +1207,7 @@
 <li><strong>Also catches subclasses of the exception.</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 stderr.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'print(&lt;name&gt;)'</span></code> to print just the cause of the exception (its arguments).</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'logging.exception(&lt;str&gt;)'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">logging</a>.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'logging.exception(&lt;str&gt;)'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">Logging</a>.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'sys.exc_info()'</span></code> to get exception type, object, and traceback of caught exception.</strong></li>
 </ul>
 <div><h3 id="raisingexceptions">Raising Exceptions</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">raise</span> &lt;exception&gt;
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index 65fec859b..df3153140 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -7,9 +7,9 @@
 
 
 MATCHES = {
-    '<strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong>': '<strong>For details about sort(), sorted(), min() and max() see sortable (p. 16).</strong>',
+    '<strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">Sortable</a>.</strong>': '<strong>For details about sort(), sorted(), min() and max() see Sortable (p. 16).</strong>',
     '<strong>Module <a href="#operator">operator</a> has function itemgetter() that can replace listed <a href="#lambda">lambdas</a>.</strong>': '<strong>Module \'operator\' (p. 31) has function itemgetter() that can replace listed lambdas (p. 11).</strong>',
-    '<strong>This text uses the term \'collection\' instead of \'iterable\'. For rationale see <a href="#collection">collection</a>.</strong>': '<strong>This text uses the term \'collection\' instead of \'iterable\'. For rationale see collection (p. 18).</strong>',
+    '<strong>This text uses the term collection instead of iterable. For rationale see <a href="#collection">Collection</a>.</strong>': '<strong>This text uses the term collection instead of iterable. For rationale see Collection (p. 18).</strong>',
     '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its <a href="#class">repr()</a> method.</strong>': '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its repr() method.</strong>',
     '<strong>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>': '<strong>It can be any callable, but is usually implemented as a function that returns a closure.</strong>',
     '<strong>Hints are used by type checkers like <a href="https://pypi.org/project/mypy/">mypy</a>, data validation libraries such as <a href="https://pypi.org/project/pydantic/">Pydantic</a> and lately also by <a href="https://pypi.org/project/Cython/">Cython</a> compiler. However, they are not enforced by CPython interpreter.</strong>': '<strong>Hints are used by type checkers like mypy, data validation libraries such as Pydantic and lately also by Cython compiler. However, they are not enforced by CPython interpreter.</strong>',
@@ -20,7 +20,7 @@
     '<strong>Objects returned by the <a href="#itertools">itertools</a> module, such as count, repeat and cycle.</strong>': '<strong>Objects returned by the itertools module, such as count, repeat and cycle (p. 3).</strong>',
     '<strong>Generators returned by the <a href="#generator">generator functions</a> and <a href="#comprehensions">generator expressions</a>.</strong>': '<strong>Generators returned by the generator functions (p. 4) and generator expressions (p. 11).</strong>',
     '<strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong>': '<strong>File objects returned by the open() function (p. 22), etc.</strong>',
-    '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">logging</a>.</strong>': '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see logging (p. 31).</strong>',
+    '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">Logging</a>.</strong>': '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see Logging (p. 31).</strong>',
     '<strong>Functions report OS related errors by raising either OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong>': '<strong>Functions report OS related errors by raising OSError or one of its subclasses (p. 23).</strong>',
     '<strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong>': '<strong>To print the spreadsheet to the console use Tabulate library (p. 34).</strong>',
     '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#dataframeplotencodedecode">Pandas</a> library.</strong>': '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use Pandas library (p. 46).</strong>',

From a603cb5864f71a4a84fa5178d4758bc3b1785bdb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 16 Dec 2024 03:52:32 +0100
Subject: [PATCH 051/186] Closure, NumPy

---
 README.md  | 57 +++++++++++++++++++++++++--------------------------
 index.html | 60 ++++++++++++++++++++++++++++--------------------------
 2 files changed, 59 insertions(+), 58 deletions(-)

diff --git a/README.md b/README.md
index cfa09566e..85927841a 100644
--- a/README.md
+++ b/README.md
@@ -840,7 +840,7 @@ import <package>.<module>  # Imports a built-in or '<package>/<module>.py'.
 
 Closure
 -------
-**We have/get a closure in Python when a nested function references a value of its enclosing function and then the enclosing function returns the nested function.**
+**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.**
 
 ```python
 def get_multiplier(a):
@@ -2717,50 +2717,49 @@ import numpy as np
 
 ### Broadcasting
 **A set of rules by which NumPy functions operate on arrays of different shapes.**
-
 ```python
-left  = [ 0.1 ,  0.6 ,  0.8 ]                           # Shape: (3,)
-right = [[0.1], [0.6], [0.8]]                           # Shape: (3, 1)
+left  = np.array([ 0.1,  0.6,  0.8 ])                   # `left.shape  == (3,)`
+right = np.array([[0.1],[0.6],[0.8]])                   # `right.shape == (3, 1)`
 ```
 
 #### 1. If array shapes differ in length, left-pad the shorter shape with ones:
 ```python
-left  = [[0.1 ,  0.6 ,  0.8]]                           # Shape: (1, 3) <- !
-right = [[0.1], [0.6], [0.8]]                           # Shape: (3, 1)
+left  = np.array([[0.1,  0.6,  0.8]])                   # `left.shape  == (1, 3)`
+right = np.array([[0.1],[0.6],[0.8]])                   # `right.shape == (3, 1)`
 ```
 
 #### 2. If any dimensions differ in size, expand the ones that have size 1 by duplicating their elements:
 ```python
-left  = [[0.1,  0.6,  0.8],                             # Shape: (3, 3) <- !
-         [0.1,  0.6,  0.8],
-         [0.1,  0.6,  0.8]]
-```
+left  = np.array([[0.1,  0.6,  0.8],                    # `left.shape  == (3, 3)`
+                  [0.1,  0.6,  0.8],
+                  [0.1,  0.6,  0.8]])
 
-```python
-right = [[0.1,  0.1,  0.1],                             # Shape: (3, 3) <- !
-         [0.6,  0.6,  0.6],
-         [0.8,  0.8,  0.8]]
+right = np.array([[0.1,  0.1,  0.1],                    # `right.shape == (3, 3)`
+                  [0.6,  0.6,  0.6],
+                  [0.8,  0.8,  0.8]])
 ```
 
 ### Example
 #### For each point returns index of its nearest point (`[0.1, 0.6, 0.8] => [1, 2, 1]`):
 
 ```python
->>> points = np.array([0.1, 0.6, 0.8])
-[ 0.1,  0.6,  0.8 ]
->>> wrapped_points = points.reshape(3, 1)
-[[0.1], [0.6], [0.8]]
->>> deltas = points - wrapped_points
-[[ 0. ,  0.5,  0.7],
- [-0.5,  0. ,  0.2],
- [-0.7, -0.2,  0. ]]
->>> distances = np.abs(deltas)
->>> distances[range(3), range(3)] = np.inf
-[[ inf,  0.5,  0.7],
- [ 0.5,  inf,  0.2],
- [ 0.7,  0.2,  inf]]
->>> distances.argmin(1)
-[1, 2, 1]
+>>> print(points := np.array([0.1, 0.6, 0.8]))
+[0.1  0.6  0.8]
+>>> print(wrapped_points := points.reshape(3, 1))
+[[0.1]
+ [0.6]
+ [0.8]]
+>>> print(deltas := points - wrapped_points)
+[[ 0.   0.5  0.7]
+ [-0.5  0.   0.2]
+ [-0.7 -0.2  0. ]]
+>>> deltas[range(3), range(3)] = np.inf
+>>> print(distances := np.abs(deltas))
+[[inf  0.5  0.7]
+ [0.5  inf  0.2]
+ [0.7  0.2  inf]]
+>>> print(distances.argmin(axis=1))
+[1 2 1]
 ```
 
 
diff --git a/index.html b/index.html
index 9e97a0a69..00d14fb3c 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 14, 2024</aside>
+    <aside>December 16, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -701,7 +701,7 @@
 <li><strong>Directory of the file that is passed to python command serves as a root of local imports.</strong></li>
 <li><strong>For relative imports use <code class="python hljs"><span class="hljs-string">'from .[…][&lt;pkg/module&gt;[.…]] import &lt;obj&gt;'</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 the nested function.</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>
+<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.</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
@@ -2216,39 +2216,41 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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 using <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>A set of rules by which NumPy functions operate on arrays of different shapes.</strong></p><pre><code class="python language-python hljs">left  = [ <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"># Shape: (3,)</span>
-right = [[<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"># Shape: (3, 1)</span>
+<div><h3 id="broadcasting">Broadcasting</h3><p><strong>A set of rules by which NumPy functions operate on arrays of different shapes.</strong></p><pre><code class="python language-python hljs">left  = 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"># `left.shape  == (3,)`</span>
+right = 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"># `right.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">left  = [[<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"># Shape: (1, 3) &lt;- !</span>
-right = [[<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"># Shape: (3, 1)</span>
+<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">left  = 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"># `left.shape  == (1, 3)`</span>
+right = 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"># `right.shape == (3, 1)`</span>
 </code></pre></div>
 
-<div><h4 id="2ifanydimensionsdifferinsizeexpandtheonesthathavesize1byduplicatingtheirelements">2. If any dimensions differ in size, expand the ones that have size 1 by duplicating their elements:</h4><pre><code class="python language-python hljs">left  = [[<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"># Shape: (3, 3) &lt;- !</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>]]
+<div><h4 id="2ifanydimensionsdifferinsizeexpandtheonesthathavesize1byduplicatingtheirelements">2. If any dimensions differ in size, expand the ones that have size 1 by duplicating their elements:</h4><pre><code class="python language-python hljs">left  = 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"># `left.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>]])
+
+right = 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"># `right.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>
 
-<pre><code class="python language-python hljs">right = [[<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"># Shape: (3, 3) &lt;- !</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><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>] =&gt; [<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">&gt;&gt;&gt; </span>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">&gt;&gt;&gt; </span>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">&gt;&gt;&gt; </span>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">&gt;&gt;&gt; </span>distances = np.abs(deltas)
-<span class="hljs-meta">&gt;&gt;&gt; </span>distances[range(<span class="hljs-number">3</span>), range(<span class="hljs-number">3</span>)] = np.inf
-[[ 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">&gt;&gt;&gt; </span>distances.argmin(<span class="hljs-number">1</span>)
-[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">1</span>]
+<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>] =&gt; [<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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span>deltas[range(<span class="hljs-number">3</span>), range(<span class="hljs-number">3</span>)] = np.inf
+<span class="hljs-meta">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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>
 
 
@@ -2922,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 14, 2024</aside>
+    <aside>December 16, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 07477fcc2ae0925ca5cae516f5cb85e2a5d00673 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 16 Dec 2024 06:13:44 +0100
Subject: [PATCH 052/186] NumPy

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 85927841a..74a688ec9 100644
--- a/README.md
+++ b/README.md
@@ -2711,7 +2711,7 @@ import numpy as np
 ```
 * **`':'` returns a slice of all dimension's indices. Omitted dimensions default to `':'`.**
 * **Python converts `'obj[i, j]'` to `'obj[(i, j)]'`. This makes `'<2d>[row_i, col_i]'` and `'<2d>[row_indices]'` indistinguishable to NumPy if tuple of indices is passed!**
-* **Indexing with a slice and 1d array works the same as when using two slices (lines 4, 6, 7).**
+* **Indexing with a slice and 1d object works the same as when using two slices (lines 4, 6, 7).**
 * **`'ix_([1, 2], [3, 4])'` returns `'[[1], [2]]'` and `'[[3, 4]]'`. Due to broadcasting rules, this is the same as using `'[[1, 1], [2, 2]]'` and `'[[3, 4], [3, 4]]'`.**
 * **Any value that is broadcastable to the indexed shape can be assigned to the selection.**
 
diff --git a/index.html b/index.html
index 00d14fb3c..91a4da512 100644
--- a/index.html
+++ b/index.html
@@ -2212,7 +2212,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <ul>
 <li><strong><code class="python hljs"><span class="hljs-string">':'</span></code> returns a slice of all dimension's indices. Omitted dimensions default to <code class="python hljs"><span class="hljs-string">':'</span></code>.</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">'&lt;2d&gt;[row_i, col_i]'</span></code> and <code class="python hljs"><span class="hljs-string">'&lt;2d&gt;[row_indices]'</span></code> indistinguishable to NumPy if tuple of indices is passed!</strong></li>
-<li><strong>Indexing with a slice and 1d array works the same as when using two slices (lines 4, 6, 7).</strong></li>
+<li><strong>Indexing with a slice and 1d object works the same as when using two slices (lines 4, 6, 7).</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 using <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>

From 13293997540daaa1fcdeb0409432ddfe2e4b5455 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 18 Dec 2024 06:35:22 +0100
Subject: [PATCH 053/186] Iterable duck types, Deque, Introspection

---
 README.md  |  8 ++++----
 index.html | 12 ++++++------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index 74a688ec9..26fd401c3 100644
--- a/README.md
+++ b/README.md
@@ -1294,8 +1294,8 @@ class MySequence:
 ```
 
 #### Discrepancies between glossary definitions and abstract base classes:
-* **Python's glossary defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.**
-* **Passing ABC Iterable to isinstance() or issubclass() checks whether object/class has method iter(), while ABC Collection checks for iter(), contains() and len().**
+* **Python's glossary defines iterable as any object with special methods iter() and/or getitem() and sequence as any object with getitem() and len(). It doesn't define collection.**
+* **Passing ABC Iterable to isinstance() or issubclass() only checks whether object/class has special method iter(), while ABC Collection checks for iter(), contains() and len().**
 
 ### ABC Sequence
 * **It's a richer interface than the basic sequence.**
@@ -2086,7 +2086,7 @@ Memory View
 
 Deque
 -----
-**List with efficient appends and pops from either side. Pronounced "deck".**
+**List with efficient appends and pops from either side.**
 
 ```python
 from collections import deque
@@ -2229,7 +2229,7 @@ CRITICAL:my_module:Running out of disk space.
 Introspection
 -------------
 ```python
-<list> = dir()                      # List of local names (variables, funcs, classes, modules).
+<list> = dir()                      # Local names of variables, functions, classes and modules.
 <dict> = vars()                     # Dict of local names and their objects. Also locals().
 <dict> = globals()                  # Dict of global names and their objects, e.g. __builtin__.
 ```
diff --git a/index.html b/index.html
index 91a4da512..24faa76a7 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 16, 2024</aside>
+    <aside>December 18, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1099,8 +1099,8 @@
 
 
 <div><h4 id="discrepanciesbetweenglossarydefinitionsandabstractbaseclasses">Discrepancies between glossary definitions and abstract base classes:</h4><ul>
-<li><strong>Python's glossary defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.</strong></li>
-<li><strong>Passing ABC Iterable to isinstance() or issubclass() checks whether object/class has method iter(), while ABC Collection checks for iter(), contains() and len().</strong></li>
+<li><strong>Python's glossary defines iterable as any object with special methods iter() and/or getitem() and sequence as any object with getitem() and len(). It doesn't define collection.</strong></li>
+<li><strong>Passing ABC Iterable to 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>
 
 
@@ -1714,7 +1714,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;str&gt;   = str(&lt;mview&gt;, <span class="hljs-string">'utf-8'</span>)                <span class="hljs-comment"># Treats memoryview as a bytes object.</span>
 &lt;str&gt;   = &lt;mview&gt;.hex()                        <span class="hljs-comment"># Returns hex pairs. Accepts `sep=&lt;str&gt;`.</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. Pronounced "deck".</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> deque
+<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>
 
 
@@ -1826,7 +1826,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 2023-02-07 23:21:01,430 CRITICAL:my_module:Running out of disk space.
 </code></pre></div>
 
-<div><h2 id="introspection"><a href="#introspection" name="introspection">#</a>Introspection</h2><pre><code class="python language-python hljs">&lt;list&gt; = dir()                      <span class="hljs-comment"># List of local names (variables, funcs, classes, modules).</span>
+<div><h2 id="introspection"><a href="#introspection" name="introspection">#</a>Introspection</h2><pre><code class="python language-python hljs">&lt;list&gt; = dir()                      <span class="hljs-comment"># Local names of variables, functions, classes and modules.</span>
 &lt;dict&gt; = vars()                     <span class="hljs-comment"># Dict of local names and their objects. Also locals().</span>
 &lt;dict&gt; = globals()                  <span class="hljs-comment"># Dict of global names and their objects, e.g. __builtin__.</span>
 </code></pre></div>
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 16, 2024</aside>
+    <aside>December 18, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 380ec207e85c04fc02b05814f8e78e51b1efe77b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 19 Dec 2024 02:58:26 +0100
Subject: [PATCH 054/186] Open, Operator

---
 README.md  | 4 ++--
 index.html | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 26fd401c3..83d97555d 100644
--- a/README.md
+++ b/README.md
@@ -1566,7 +1566,7 @@ args  = p.parse_args()                                            # Exits on par
 
 Open
 ----
-**Opens the file and returns a corresponding file object.**
+**Opens a file and returns the corresponding file object.**
 
 ```python
 <file> = open(<path>, mode='r', encoding=None, newline=None)
@@ -2103,7 +2103,7 @@ from collections import deque
 
 Operator
 --------
-**Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence, from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are ordered by precedence also within a group.**
+**Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence, from least to most binding. Logical and arithmetic operators in lines 1, 3 and 5 are also ordered by precedence within their own group.**
 ```python
 import operator as op
 ```
diff --git a/index.html b/index.html
index 24faa76a7..ef1b7e3ef 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 18, 2024</aside>
+    <aside>December 19, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1323,7 +1323,7 @@
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'default=&lt;obj&gt;'</span></code> to set option's or optional argument's default value.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'type=FileType(&lt;mode&gt;)'</span></code> for files. Accepts 'encoding', but 'newline' is None.</strong></li>
 </ul>
-<div><h2 id="open"><a href="#open" name="open">#</a>Open</h2><p><strong>Opens the file and returns a corresponding file object.</strong></p><pre><code class="python language-python hljs">&lt;file&gt; = open(&lt;path&gt;, mode=<span class="hljs-string">'r'</span>, encoding=<span class="hljs-keyword">None</span>, newline=<span class="hljs-keyword">None</span>)
+<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">&lt;file&gt; = open(&lt;path&gt;, mode=<span class="hljs-string">'r'</span>, encoding=<span class="hljs-keyword">None</span>, newline=<span class="hljs-keyword">None</span>)
 </code></pre></div>
 
 
@@ -1724,7 +1724,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;deque&gt;.rotate(n=<span class="hljs-number">1</span>)                            <span class="hljs-comment"># Last element becomes first.</span>
 &lt;el&gt; = &lt;deque&gt;.popleft()                       <span class="hljs-comment"># Raises IndexError if deque is empty.</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 ordered and grouped by operator precedence, from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are ordered by precedence also within a group.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> operator <span class="hljs-keyword">as</span> op
+<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 ordered and grouped by operator precedence, from least to most binding. Logical and arithmetic operators in lines 1, 3 and 5 are also ordered by precedence within their own group.</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>
 
 
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 18, 2024</aside>
+    <aside>December 19, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 51d1127cfd707c4bfce81454ed8b50605b153deb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 20 Dec 2024 11:54:02 +0100
Subject: [PATCH 055/186] Pandas

---
 README.md  | 14 +++++++-------
 index.html | 18 +++++++++---------
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/README.md b/README.md
index 83d97555d..a967e964a 100644
--- a/README.md
+++ b/README.md
@@ -3352,15 +3352,16 @@ c  6  7
 
 #### DataFrame — Encode, Decode:
 ```python
-<DF> = pd.read_json/html('<str/path/url>')     # Run `$ pip3 install beautifulsoup4 lxml`.
-<DF> = pd.read_csv('<path/url>')               # `header/index_col/dtype/usecols/…=<obj>`.
-<DF> = pd.read_pickle/excel('<path/url>')      # Use `sheet_name=None` to get all Excel sheets.
-<DF> = pd.read_sql('<table/query>', <conn.>)   # SQLite3/SQLAlchemy connection (see #SQLite).
+<DF>   = pd.read_json/pickle(<path/url/file>)  # Also accepts io.StringIO/BytesIO(<str/bytes>).
+<DF>   = pd.read_csv(<path/url/file>)          # `header/index_col/dtype/usecols/…=<obj>`.
+<DF>   = pd.read_excel(<path/url/file>)        # `sheet_name=None` returns dict of all sheets.
+<DF>   = pd.read_sql('<table/query>', <conn>)  # SQLite3/SQLAlchemy connection (see #SQLite).
+<list> = pd.read_html(<path/url/file>)         # Run `$ pip3 install beautifulsoup4 lxml`.
 ```
 
 ```python
 <dict> = <DF>.to_dict('d/l/s/…')               # Returns columns as dicts, lists or series.
-<str>  = <DF>.to_json/html/csv/latex()         # Saves output to a file if path is passed.
+<str>  = <DF>.to_json/csv/html/latex()         # Saves output to a file if path is passed.
 <DF>.to_pickle/excel(<path>)                   # Run `$ pip3 install "pandas[excel]" odfpy`.
 <DF>.to_sql('<table_name>', <connection>)      # Also `if_exists='fail/replace/append'`.
 ```
@@ -3373,8 +3374,7 @@ c  6  7
 
 ```python
 <GB> = <DF>.groupby(col_key/s)                 # Splits DF into groups based on passed column.
-<DF> = <GB>.apply(<func>)                      # Maps each group. Func can return DF, S or el.
-<DF> = <GB>.filter(<func>)                     # Drops a group if function returns False.
+<DF> = <GB>.apply/filter(<func>)               # Filter drops a group if func returns False.
 <DF> = <GB>.get_group(<el>)                    # Selects a group by grouping column's value.
 <S>  = <GB>.size()                             # S of group sizes. Same keys as get_group().
 <GB> = <GB>[col_key]                           # Single column GB. All operations return S.
diff --git a/index.html b/index.html
index ef1b7e3ef..0e6b6a1a9 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 19, 2024</aside>
+    <aside>December 20, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2729,14 +2729,15 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;DF&gt;   = &lt;DF&gt;.pivot_table(index=col_key/s)     <span class="hljs-comment"># `columns=key/s, values=key/s, aggfunc='mean'`.</span>
 </code></pre></div>
 
-<div><h4 id="dataframeencodedecode">DataFrame — Encode, Decode:</h4><pre><code class="python language-python hljs">&lt;DF&gt; = pd.read_json/html(<span class="hljs-string">'&lt;str/path/url&gt;'</span>)     <span class="hljs-comment"># Run `$ pip3 install beautifulsoup4 lxml`.</span>
-&lt;DF&gt; = pd.read_csv(<span class="hljs-string">'&lt;path/url&gt;'</span>)               <span class="hljs-comment"># `header/index_col/dtype/usecols/…=&lt;obj&gt;`.</span>
-&lt;DF&gt; = pd.read_pickle/excel(<span class="hljs-string">'&lt;path/url&gt;'</span>)      <span class="hljs-comment"># Use `sheet_name=None` to get all Excel sheets.</span>
-&lt;DF&gt; = pd.read_sql(<span class="hljs-string">'&lt;table/query&gt;'</span>, &lt;conn.&gt;)   <span class="hljs-comment"># SQLite3/SQLAlchemy connection (see #SQLite).</span>
+<div><h4 id="dataframeencodedecode">DataFrame — Encode, Decode:</h4><pre><code class="python language-python hljs">&lt;DF&gt;   = pd.read_json/pickle(&lt;path/url/file&gt;)  <span class="hljs-comment"># Also accepts io.StringIO/BytesIO(&lt;str/bytes&gt;).</span>
+&lt;DF&gt;   = pd.read_csv(&lt;path/url/file&gt;)          <span class="hljs-comment"># `header/index_col/dtype/usecols/…=&lt;obj&gt;`.</span>
+&lt;DF&gt;   = pd.read_excel(&lt;path/url/file&gt;)        <span class="hljs-comment"># `sheet_name=None` returns dict of all sheets.</span>
+&lt;DF&gt;   = pd.read_sql(<span class="hljs-string">'&lt;table/query&gt;'</span>, &lt;conn&gt;)  <span class="hljs-comment"># SQLite3/SQLAlchemy connection (see #SQLite).</span>
+&lt;list&gt; = pd.read_html(&lt;path/url/file&gt;)         <span class="hljs-comment"># Run `$ pip3 install beautifulsoup4 lxml`.</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs">&lt;dict&gt; = &lt;DF&gt;.to_dict(<span class="hljs-string">'d/l/s/…'</span>)               <span class="hljs-comment"># Returns columns as dicts, lists or series.</span>
-&lt;str&gt;  = &lt;DF&gt;.to_json/html/csv/latex()         <span class="hljs-comment"># Saves output to a file if path is passed.</span>
+&lt;str&gt;  = &lt;DF&gt;.to_json/csv/html/latex()         <span class="hljs-comment"># Saves output to a file if path is passed.</span>
 &lt;DF&gt;.to_pickle/excel(&lt;path&gt;)                   <span class="hljs-comment"># Run `$ pip3 install "pandas[excel]" odfpy`.</span>
 &lt;DF&gt;.to_sql(<span class="hljs-string">'&lt;table_name&gt;'</span>, &lt;connection&gt;)      <span class="hljs-comment"># Also `if_exists='fail/replace/append'`.</span>
 </code></pre>
@@ -2746,8 +2747,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>To get specific attributes from a series of Timestamps use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.dt.year/date/…'</span></code>.</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">&lt;GB&gt; = &lt;DF&gt;.groupby(col_key/s)                 <span class="hljs-comment"># Splits DF into groups based on passed column.</span>
-&lt;DF&gt; = &lt;GB&gt;.apply(&lt;func&gt;)                      <span class="hljs-comment"># Maps each group. Func can return DF, S or el.</span>
-&lt;DF&gt; = &lt;GB&gt;.filter(&lt;func&gt;)                     <span class="hljs-comment"># Drops a group if function returns False.</span>
+&lt;DF&gt; = &lt;GB&gt;.apply/filter(&lt;func&gt;)               <span class="hljs-comment"># Filter drops a group if func returns False.</span>
 &lt;DF&gt; = &lt;GB&gt;.get_group(&lt;el&gt;)                    <span class="hljs-comment"># Selects a group by grouping column's value.</span>
 &lt;S&gt;  = &lt;GB&gt;.size()                             <span class="hljs-comment"># S of group sizes. Same keys as get_group().</span>
 &lt;GB&gt; = &lt;GB&gt;[col_key]                           <span class="hljs-comment"># Single column GB. All operations return S.</span>
@@ -2924,7 +2924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 19, 2024</aside>
+    <aside>December 20, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 3d17eeb4fb59350bea3f65581d5eefcddc55a2fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 24 Dec 2024 11:00:31 +0100
Subject: [PATCH 056/186] Scraping, Plotly example rewrite

---
 README.md  | 54 +++++++++++++++++++++++++++++---------------------
 index.html | 58 ++++++++++++++++++++++++++++++++----------------------
 2 files changed, 66 insertions(+), 46 deletions(-)

diff --git a/README.md b/README.md
index a967e964a..5ad71adca 100644
--- a/README.md
+++ b/README.md
@@ -2510,10 +2510,9 @@ document   = bs4.BeautifulSoup(response.text, 'html.parser')
 table      = document.find('table', class_='infobox vevent')
 python_url = table.find('th', text='Website').next_sibling.a['href']
 logo_url   = table.find('img')['src']
-logo       = requests.get(f'https:{logo_url}').content
 filename   = os.path.basename(logo_url)
 with open(filename, 'wb') as file:
-    file.write(logo)
+    file.write(requests.get(f'https:{logo_url}').content)
 print(f'{python_url}, file://{os.path.abspath(filename)}')
 ```
 
@@ -2525,6 +2524,7 @@ from selenium import webdriver
 
 <WebDrv> = webdriver.Chrome/Firefox/Safari/Edge()     # Opens a browser. Also <WebDrv>.quit().
 <WebDrv>.get('<url>')                                 # Also <WebDrv>.implicitly_wait(seconds).
+<str>  = <WebDrv>.page_source                         # Returns HTML of fully rendered page.
 <El>   = <WebDrv/El>.find_element('css selector', …)  # '<tag>#<id>.<class>[<attr>="<val>"]…'.
 <list> = <WebDrv/El>.find_elements('xpath', …)        # '//<tag>[@<attr>="<val>"]…'. See XPath.
 <str>  = <El>.get_attribute(<str>)                    # Property if exists. Also <El>.text.
@@ -3457,32 +3457,41 @@ px.line(df, x='Date', y='Total Deaths per Million', color='Continent').show()
 <div id="e23ccacc-a456-478b-b467-7282a2165921" class="plotly-graph-div" style="height:287px; width:935px;"></div>
 
 ```python
-import pandas as pd, plotly.graph_objects as go
+# $ pip3 install pandas selenium plotly lxml
+import pandas as pd, selenium.webdriver, plotly.graph_objects as go
+
 
 def main():
-    covid, bitcoin, gold, dow = scrape_data()
+    covid, (bitcoin, gold, dow) = get_covid_cases(), get_tickers()
     df = wrangle_data(covid, bitcoin, gold, dow)
     display_data(df)
 
-def scrape_data():
-    def get_covid_cases():
-        url = 'https://covid.ourworldindata.org/data/owid-covid-data.csv'
-        df = pd.read_csv(url, usecols=['location', 'date', 'total_cases'])
-        df = df[df.location == 'World']
-        return df.set_index('date').total_cases
-    def get_ticker(symbol):
-        url = (f'https://query1.finance.yahoo.com/v7/finance/download/{symbol}?'
-               'period1=1579651200&period2=9999999999&interval=1d&events=history')
-        df = pd.read_csv(url, usecols=['Date', 'Close'])
-        return df.set_index('Date').Close
-    out = get_covid_cases(), get_ticker('BTC-USD'), get_ticker('GC=F'), get_ticker('^DJI')
-    names = ['Total Cases', 'Bitcoin', 'Gold', 'Dow Jones']
-    return map(pd.Series.rename, out, names)
+def get_covid_cases():
+    url = 'https://covid.ourworldindata.org/data/owid-covid-data.csv'
+    df = pd.read_csv(url, usecols=['location', 'date', 'total_cases'], parse_dates=['date'])
+    df = df[df.location == 'World']
+    s = df.set_index('date').total_cases
+    return s.rename('Total Cases')
+
+def get_tickers():
+    with selenium.webdriver.Chrome() as driver:
+        symbols = {'Bitcoin': 'BTC-USD', 'Gold': 'GC=F', 'Dow Jones': '%5EDJI'}
+        for name, symbol in symbols.items():
+            yield get_ticker(driver, name, symbol)
+
+def get_ticker(driver, name, symbol):
+    url = f'https://finance.yahoo.com/quote/{symbol}/history/'
+    driver.get(url + '?period1=1579651200&period2=9999999999')
+    if buttons := driver.find_elements('xpath', '//button[@name="reject"]'):
+        buttons[0].click()
+    dataframes = pd.read_html(driver.page_source, parse_dates=['Date'])
+    s = dataframes[0].set_index('Date').Open
+    return s.rename(name)
 
 def wrangle_data(covid, bitcoin, gold, dow):
     df = pd.concat([bitcoin, gold, dow], axis=1)  # Creates table by joining columns on dates.
     df = df.sort_index().interpolate()            # Sorts rows by date and interpolates NaN-s.
-    df = df.loc['2020-02-23':]                    # Discards rows before '2020-02-23'.
+    df = df.loc['2020-02-23':'2021-12-20']        # Keeps rows between specified dates.
     df = (df / df.iloc[0]) * 100                  # Calculates percentages relative to day 1.
     df = df.join(covid)                           # Adds column with covid cases.
     return df.sort_values(df.index[-1], axis=1)   # Sorts columns by last day's value.
@@ -3494,11 +3503,12 @@ def display_data(df):
         trace = go.Scatter(x=df.index, y=df[col_name], name=col_name, yaxis=yaxis)
         figure.add_trace(trace)
     figure.update_layout(
+        width=944,
+        height=423,
         yaxis1=dict(title='Total Cases', rangemode='tozero'),
         yaxis2=dict(title='%', rangemode='tozero', overlaying='y', side='right'),
-        legend=dict(x=1.08),
-        width=944,
-        height=423
+        colorway=['#EF553B', '#636EFA', '#00CC96', '#FFA152'],
+        legend=dict(x=1.08)
     )
     figure.show()
 
diff --git a/index.html b/index.html
index 0e6b6a1a9..f83060fe6 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 20, 2024</aside>
+    <aside>December 24, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2052,10 +2052,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 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>, text=<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>]
-logo       = requests.get(<span class="hljs-string">f'https:<span class="hljs-subst">{logo_url}</span>'</span>).content
 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(logo)
+    file.write(requests.get(<span class="hljs-string">f'https:<span class="hljs-subst">{logo_url}</span>'</span>).content)
 print(<span class="hljs-string">f'<span class="hljs-subst">{python_url}</span>, file://<span class="hljs-subst">{os.path.abspath(filename)}</span>'</span>)
 </code></pre></div></div>
 
@@ -2065,6 +2064,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 &lt;WebDrv&gt; = webdriver.Chrome/Firefox/Safari/Edge()     <span class="hljs-comment"># Opens a browser. Also &lt;WebDrv&gt;.quit().</span>
 &lt;WebDrv&gt;.get(<span class="hljs-string">'&lt;url&gt;'</span>)                                 <span class="hljs-comment"># Also &lt;WebDrv&gt;.implicitly_wait(seconds).</span>
+&lt;str&gt;  = &lt;WebDrv&gt;.page_source                         <span class="hljs-comment"># Returns HTML of fully rendered page.</span>
 &lt;El&gt;   = &lt;WebDrv/El&gt;.find_element(<span class="hljs-string">'css selector'</span>, …)  <span class="hljs-comment"># '&lt;tag&gt;#&lt;id&gt;.&lt;class&gt;[&lt;attr&gt;="&lt;val&gt;"]…'.</span>
 &lt;list&gt; = &lt;WebDrv/El&gt;.find_elements(<span class="hljs-string">'xpath'</span>, …)        <span class="hljs-comment"># '//&lt;tag&gt;[@&lt;attr&gt;="&lt;val&gt;"]…'. See XPath.</span>
 &lt;str&gt;  = &lt;El&gt;.get_attribute(&lt;str&gt;)                    <span class="hljs-comment"># Property if exists. Also &lt;El&gt;.text.</span>
@@ -2805,32 +2805,41 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<div><h4 id="displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">Displays a multi-axis line chart of total coronavirus 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:287px; width:935px;"></div><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd, plotly.graph_objects <span class="hljs-keyword">as</span> go
+<div><h4 id="displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">Displays a multi-axis line chart of total coronavirus 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:287px; width:935px;"></div><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pandas selenium plotly lxml</span>
+<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd, selenium.webdriver, 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 = scrape_data()
+    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">scrape_data</span><span class="hljs-params">()</span>:</span>
-    <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://covid.ourworldindata.org/data/owid-covid-data.csv'</span>
-        df = pd.read_csv(url, usecols=[<span class="hljs-string">'location'</span>, <span class="hljs-string">'date'</span>, <span class="hljs-string">'total_cases'</span>])
-        df = df[df.location == <span class="hljs-string">'World'</span>]
-        <span class="hljs-keyword">return</span> df.set_index(<span class="hljs-string">'date'</span>).total_cases
-    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_ticker</span><span class="hljs-params">(symbol)</span>:</span>
-        url = (<span class="hljs-string">f'https://query1.finance.yahoo.com/v7/finance/download/<span class="hljs-subst">{symbol}</span>?'</span>
-               <span class="hljs-string">'period1=1579651200&amp;period2=9999999999&amp;interval=1d&amp;events=history'</span>)
-        df = pd.read_csv(url, usecols=[<span class="hljs-string">'Date'</span>, <span class="hljs-string">'Close'</span>])
-        <span class="hljs-keyword">return</span> df.set_index(<span class="hljs-string">'Date'</span>).Close
-    out = get_covid_cases(), get_ticker(<span class="hljs-string">'BTC-USD'</span>), get_ticker(<span class="hljs-string">'GC=F'</span>), get_ticker(<span class="hljs-string">'^DJI'</span>)
-    names = [<span class="hljs-string">'Total Cases'</span>, <span class="hljs-string">'Bitcoin'</span>, <span class="hljs-string">'Gold'</span>, <span class="hljs-string">'Dow Jones'</span>]
-    <span class="hljs-keyword">return</span> map(pd.Series.rename, out, names)
+<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://covid.ourworldindata.org/data/owid-covid-data.csv'</span>
+    df = pd.read_csv(url, usecols=[<span class="hljs-string">'location'</span>, <span class="hljs-string">'date'</span>, <span class="hljs-string">'total_cases'</span>], parse_dates=[<span class="hljs-string">'date'</span>])
+    df = df[df.location == <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:
+        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">for</span> name, symbol <span class="hljs-keyword">in</span> symbols.items():
+            <span class="hljs-keyword">yield</span> get_ticker(driver, name, symbol)
+
+<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&amp;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()
+    dataframes = pd.read_html(driver.page_source, 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 table by joining columns on dates.</span>
     df = df.sort_index().interpolate()            <span class="hljs-comment"># Sorts rows by date and interpolates NaN-s.</span>
-    df = df.loc[<span class="hljs-string">'2020-02-23'</span>:]                    <span class="hljs-comment"># Discards rows before '2020-02-23'.</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 specified dates.</span>
     df = (df / df.iloc[<span class="hljs-number">0</span>]) * <span class="hljs-number">100</span>                  <span class="hljs-comment"># Calculates percentages relative to day 1.</span>
     df = df.join(covid)                           <span class="hljs-comment"># Adds column with 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 last day's value.</span>
@@ -2842,11 +2851,12 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
         trace = go.Scatter(x=df.index, y=df[col_name], name=col_name, yaxis=yaxis)
         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>),
-        legend=dict(x=<span class="hljs-number">1.08</span>),
-        width=<span class="hljs-number">944</span>,
-        height=<span class="hljs-number">423</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()
 
@@ -2924,7 +2934,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 20, 2024</aside>
+    <aside>December 24, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 72673286e5e89f92fcc73337e270db5a198e9c54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 25 Dec 2024 14:22:04 +0100
Subject: [PATCH 057/186] Input, Pandas

---
 README.md  |  8 ++++----
 index.html | 12 ++++++------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index 5ad71adca..33970c4b1 100644
--- a/README.md
+++ b/README.md
@@ -1531,7 +1531,7 @@ pprint(<collection>, width=80, depth=None, compact=False, sort_dicts=True)
 Input
 -----
 ```python
-<str> = input([<obj>])
+<str> = input()
 ```
 * **Reads a line from the user input or pipe if present (trailing newline gets stripped).**
 * **If argument is passed, it gets printed to the standard output before input is read.**
@@ -3193,9 +3193,9 @@ Name: a, dtype: int64
 ```python
 <S>.plot.line/area/bar/pie/hist()              # Generates a plot. `plt.show()` displays it.
 ```
-* **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`!**
+* **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`.**
 * **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
-* **Series will silently overflow if we run `'pd.Series([100], dtype="int8") + 100'`.**
+* **Series will silently overflow if we run `'pd.Series([100], dtype="int8") + 100'`!**
 
 #### Series — Aggregate, Transform, Map:
 ```python
@@ -3407,7 +3407,7 @@ z
 
 ```python
 <RS/RDF/RGB> = <S/DF/GB>.rolling(win_size)     # Also: `min_periods=None, center=False`.
-<RS/RDF/RGB> = <RDF/RGB>[col_key/s]            # Or: <RDF/RGB>.col_key
+<RS/RDF/RGB> = <RDF/RGB>[col_key/s]            # Or: <RDF/RGB>.<col_key>
 <S/DF>       = <R>.mean/sum/max()              # Or: <R>.apply/agg(<agg_func/str>)
 ```
 
diff --git a/index.html b/index.html
index f83060fe6..7084bbf2f 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 24, 2024</aside>
+    <aside>December 25, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1294,7 +1294,7 @@
 <li><strong>Each item is printed on its own line if collection exceeds 'width' characters.</strong></li>
 <li><strong>Nested collections that are 'depth' levels deep get printed as '…'.</strong></li>
 </ul>
-<div><h2 id="input"><a href="#input" name="input">#</a>Input</h2><pre><code class="python language-python hljs">&lt;str&gt; = input([&lt;obj&gt;])
+<div><h2 id="input"><a href="#input" name="input">#</a>Input</h2><pre><code class="python language-python hljs">&lt;str&gt; = input()
 </code></pre></div>
 
 <ul>
@@ -2601,9 +2601,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. `plt.show()` displays it.</span>
 </code></pre>
 <ul>
-<li><strong>Indexing objects can't be tuples 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>!</strong></li>
+<li><strong>Indexing objects can't be tuples 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>.</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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
-<li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>.</strong></li>
+<li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
 </ul>
 <div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.sum/max/mean/idxmax/all()           <span class="hljs-comment"># Or: &lt;S&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;S&gt;  = &lt;S&gt;.rank/diff/cumsum/ffill/interpol…()  <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
@@ -2772,7 +2772,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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">&lt;RS/RDF/RGB&gt; = &lt;S/DF/GB&gt;.rolling(win_size)     <span class="hljs-comment"># Also: `min_periods=None, center=False`.</span>
-&lt;RS/RDF/RGB&gt; = &lt;RDF/RGB&gt;[col_key/s]            <span class="hljs-comment"># Or: &lt;RDF/RGB&gt;.col_key</span>
+&lt;RS/RDF/RGB&gt; = &lt;RDF/RGB&gt;[col_key/s]            <span class="hljs-comment"># Or: &lt;RDF/RGB&gt;.&lt;col_key&gt;</span>
 &lt;S/DF&gt;       = &lt;R&gt;.mean/sum/max()              <span class="hljs-comment"># Or: &lt;R&gt;.apply/agg(&lt;agg_func/str&gt;)</span>
 </code></pre></div>
 
@@ -2934,7 +2934,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 24, 2024</aside>
+    <aside>December 25, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 480f6db8096a4b2bd7efbf10eaa763450cf8d9a2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 25 Dec 2024 14:29:13 +0100
Subject: [PATCH 058/186] Match statement

---
 README.md | 2 +-
 parse.js  | 9 +--------
 2 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/README.md b/README.md
index 33970c4b1..b1cf2d29c 100644
--- a/README.md
+++ b/README.md
@@ -2167,7 +2167,7 @@ match <object/expression>:
 ...         parts=['/', 'home', user, *_]
 ...     ) as p if p.name.lower().startswith('readme') and p.is_file():
 ...         print(f'{p.name} is a readme file that belongs to user {user}.')
-'README.md is a readme file that belongs to user gto.'
+README.md is a readme file that belongs to user gto.
 ```
 
 
diff --git a/parse.js b/parse.js
index e592db829..7ab29869b 100755
--- a/parse.js
+++ b/parse.js
@@ -110,7 +110,7 @@ const MATCH_EXAMPLE =
   '<span class="hljs-meta">... </span>        parts=[<span class="hljs-string">\'/\'</span>, <span class="hljs-string">\'home\'</span>, user, *_]\n' +
   '<span class="hljs-meta">... </span>    ) <span class="hljs-keyword">as</span> p <span class="hljs-keyword">if</span> p.name.lower().startswith(<span class="hljs-string">\'readme\'</span>) <span class="hljs-keyword">and</span> p.is_file():\n' +
   '<span class="hljs-meta">... </span>        print(<span class="hljs-string">f\'<span class="hljs-subst">{p.name}</span> is a readme file that belongs to user <span class="hljs-subst">{user}</span>.\'</span>)\n' +
-  '<span class="hljs-string">\'README.md is a readme file that belongs to user gto.\'</span>\n';
+  'README.md is a readme file that belongs to user gto.\n';
 
 const COROUTINES =
   '<span class="hljs-keyword">import</span> asyncio, collections, curses, curses.textpad, enum, random\n' +
@@ -733,7 +733,6 @@ function modifyPage() {
   unindentBanner();
   updateDiagrams();
   highlightCode();
-  fixMatchHighlights();
   fixPandasDiagram();
   removePlotImages();
   fixABCSequenceDiv();
@@ -898,12 +897,6 @@ function insertPageBreakBefore(an_id) {
   $('<div class="pagebreak"></div>').insertBefore($(an_id).parent())
 }
 
-function fixMatchHighlights() {
-  const line = $(`span:contains(README.md is a readme file that belongs to user gto.)`);
-  line.after('README.md is a readme file that belongs to user gto.');
-  line.remove();
-}
-
 function fixPandasDiagram() {
   const diagram_15 = '┏━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━┓';
   $(`code:contains(${diagram_15})`).find(".hljs-keyword:contains(and)").after("and");

From dabd9b94328995cd0d3123e98d6812744981b135 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 25 Dec 2024 14:31:35 +0100
Subject: [PATCH 059/186] Logging

---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index b1cf2d29c..cfa9dfd14 100644
--- a/README.md
+++ b/README.md
@@ -2167,7 +2167,7 @@ match <object/expression>:
 ...         parts=['/', 'home', user, *_]
 ...     ) as p if p.name.lower().startswith('readme') and p.is_file():
 ...         print(f'{p.name} is a readme file that belongs to user {user}.')
-README.md is a readme file that belongs to user gto.
+'README.md is a readme file that belongs to user gto.'
 ```
 
 
@@ -2220,9 +2220,9 @@ log.basicConfig(
 >>> log.basicConfig()
 >>> log.root.handlers[0].setLevel('WARNING')
 >>> logger.critical('Running out of disk space.')
-CRITICAL:my_module:Running out of disk space.
+'CRITICAL:my_module:Running out of disk space.'
 >>> print(open('test.log').read())
-2023-02-07 23:21:01,430 CRITICAL:my_module:Running out of disk space.
+'2023-02-07 23:21:01,430 CRITICAL:my_module:Running out of disk space.'
 ```
 
 

From d3c933074988f19779162c1519ad977b483e0fd8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 25 Dec 2024 14:49:20 +0100
Subject: [PATCH 060/186] Match statement, Logging

---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index cfa9dfd14..b1cf2d29c 100644
--- a/README.md
+++ b/README.md
@@ -2167,7 +2167,7 @@ match <object/expression>:
 ...         parts=['/', 'home', user, *_]
 ...     ) as p if p.name.lower().startswith('readme') and p.is_file():
 ...         print(f'{p.name} is a readme file that belongs to user {user}.')
-'README.md is a readme file that belongs to user gto.'
+README.md is a readme file that belongs to user gto.
 ```
 
 
@@ -2220,9 +2220,9 @@ log.basicConfig(
 >>> log.basicConfig()
 >>> log.root.handlers[0].setLevel('WARNING')
 >>> logger.critical('Running out of disk space.')
-'CRITICAL:my_module:Running out of disk space.'
+CRITICAL:my_module:Running out of disk space.
 >>> print(open('test.log').read())
-'2023-02-07 23:21:01,430 CRITICAL:my_module:Running out of disk space.'
+2023-02-07 23:21:01,430 CRITICAL:my_module:Running out of disk space.
 ```
 
 

From 989c834d05b5a28fdd16e75003dafe6da1ae2cdb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 26 Dec 2024 21:13:31 +0100
Subject: [PATCH 061/186] Duck types, NumPy, Cython

---
 README.md  | 10 +++++-----
 index.html | 14 +++++++-------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
index b1cf2d29c..114b4550b 100644
--- a/README.md
+++ b/README.md
@@ -1164,7 +1164,7 @@ class MySortable:
 ### Iterator
 * **Any object that has methods next() and iter() is an iterator.**
 * **Next() should return next item or raise StopIteration exception.**
-* **Iter() should return 'self'.**
+* **Iter() should return 'self', i.e. unmodified object on which it was called.**
 ```python
 class Counter:
     def __init__(self):
@@ -2718,14 +2718,14 @@ import numpy as np
 ### Broadcasting
 **A set of rules by which NumPy functions operate on arrays of different shapes.**
 ```python
-left  = np.array([ 0.1,  0.6,  0.8 ])                   # `left.shape  == (3,)`
-right = np.array([[0.1],[0.6],[0.8]])                   # `right.shape == (3, 1)`
+left  = np.array([0.1,  0.6,  0.8])                     # `left.shape  == (3,)`
+right = np.array([[0.1], [0.6], [0.8]])                 # `right.shape == (3, 1)`
 ```
 
 #### 1. If array shapes differ in length, left-pad the shorter shape with ones:
 ```python
 left  = np.array([[0.1,  0.6,  0.8]])                   # `left.shape  == (1, 3)`
-right = np.array([[0.1],[0.6],[0.8]])                   # `right.shape == (3, 1)`
+right = np.array([[0.1], [0.6], [0.8]])                 # `right.shape == (3, 1)`
 ```
 
 #### 2. If any dimensions differ in size, expand the ones that have size 1 by duplicating their elements:
@@ -3525,7 +3525,7 @@ Appendix
 ```python
 # $ pip3 install cython
 import pyximport; pyximport.install()  # Module that runs imported Cython scripts.
-import <cython_script>                 # Script's filename needs a '.pyx' extension.
+import <cython_script>                 # Script must be saved with '.pyx' extension.
 <cython_script>.main()                 # Main() isn't automatically executed.
 ```
 
diff --git a/index.html b/index.html
index 7084bbf2f..e9492d15f 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 25, 2024</aside>
+    <aside>December 26, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -978,7 +978,7 @@
 <div><h3 id="iterator-1">Iterator</h3><ul>
 <li><strong>Any object that has methods next() and iter() is an iterator.</strong></li>
 <li><strong>Next() should return next item or raise StopIteration exception.</strong></li>
-<li><strong>Iter() should return 'self'.</strong></li>
+<li><strong>Iter() should return 'self', i.e. unmodified object on which it was called.</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>
@@ -2216,13 +2216,13 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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 using <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>A set of rules by which NumPy functions operate on arrays of different shapes.</strong></p><pre><code class="python language-python hljs">left  = 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"># `left.shape  == (3,)`</span>
-right = 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"># `right.shape == (3, 1)`</span>
+<div><h3 id="broadcasting">Broadcasting</h3><p><strong>A set of rules by which NumPy functions operate on arrays of different shapes.</strong></p><pre><code class="python language-python hljs">left  = 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"># `left.shape  == (3,)`</span>
+right = 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"># `right.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">left  = 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"># `left.shape  == (1, 3)`</span>
-right = 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"># `right.shape == (3, 1)`</span>
+right = 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"># `right.shape == (3, 1)`</span>
 </code></pre></div>
 
 <div><h4 id="2ifanydimensionsdifferinsizeexpandtheonesthathavesize1byduplicatingtheirelements">2. If any dimensions differ in size, expand the ones that have size 1 by duplicating their elements:</h4><pre><code class="python language-python hljs">left  = 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"># `left.shape  == (3, 3)`</span>
@@ -2868,7 +2868,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <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 imported Cython scripts.</span>
-<span class="hljs-keyword">import</span> &lt;cython_script&gt;                 <span class="hljs-comment"># Script's filename needs a '.pyx' extension.</span>
+<span class="hljs-keyword">import</span> &lt;cython_script&gt;                 <span class="hljs-comment"># Script must be saved with '.pyx' extension.</span>
 &lt;cython_script&gt;.main()                 <span class="hljs-comment"># Main() isn't automatically executed.</span>
 </code></pre></div></div>
 
@@ -2934,7 +2934,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 25, 2024</aside>
+    <aside>December 26, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 90b769e18b3beaf6ab8f9216c20fd1cdb0239657 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 27 Dec 2024 10:34:01 +0100
Subject: [PATCH 062/186] Pandas file formats rewrite

---
 README.md  | 22 +++++++++++-----------
 index.html | 24 ++++++++++++------------
 2 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/README.md b/README.md
index 114b4550b..8d3d95d15 100644
--- a/README.md
+++ b/README.md
@@ -3345,27 +3345,27 @@ c  6  7
 ```python
 <DF>   = <DF>.xs(key, level=<int>)             # Rows with key on passed level of multi-index.
 <DF>   = <DF>.xs(keys, level=<ints>, axis=1)   # Cols that have first key on first level, etc.
-<DF>   = <DF>.set_index(col_keys)              # Combines multiple columns into a multi-index.
+<DF>   = <DF>.set_index(col_keys)              # Creates index from cols. Also `append=False`.
 <S/DF> = <DF>.stack/unstack(level=-1)          # Combines col keys with row keys or vice versa.
 <DF>   = <DF>.pivot_table(index=col_key/s)     # `columns=key/s, values=key/s, aggfunc='mean'`.
 ```
 
-#### DataFrame — Encode, Decode:
+### File Formats
 ```python
-<DF>   = pd.read_json/pickle(<path/url/file>)  # Also accepts io.StringIO/BytesIO(<str/bytes>).
-<DF>   = pd.read_csv(<path/url/file>)          # `header/index_col/dtype/usecols/…=<obj>`.
-<DF>   = pd.read_excel(<path/url/file>)        # `sheet_name=None` returns dict of all sheets.
-<DF>   = pd.read_sql('<table/query>', <conn>)  # SQLite3/SQLAlchemy connection (see #SQLite).
-<list> = pd.read_html(<path/url/file>)         # Run `$ pip3 install beautifulsoup4 lxml`.
+<S/DF> = pd.read_json/pickle(<path/url/file>)  # Also accepts io.StringIO/BytesIO(<str/bytes>).
+<DF>   = pd.read_csv/excel(<path/url/file>)    # Also `header/index_col/dtype/usecols/…=<obj>`.
+<list> = pd.read_html(<path/url/file>)         # Raises ImportError if webpage has zero tables.
+<S/DF> = pd.read_parquet/feather/hdf(<path…>)  # Read_hdf() accepts `key='<df_name>'` argument.
+<DF>   = pd.read_sql('<table/query>', <conn>)  # Pass SQLite3/Alchemy connection (see #SQLite).
 ```
 
 ```python
-<dict> = <DF>.to_dict('d/l/s/…')               # Returns columns as dicts, lists or series.
-<str>  = <DF>.to_json/csv/html/latex()         # Saves output to a file if path is passed.
-<DF>.to_pickle/excel(<path>)                   # Run `$ pip3 install "pandas[excel]" odfpy`.
+<DF>.to_json/csv/html/parquet/latex(<path>)    # Returns a string/bytes if path is omitted.
+<DF>.to_pickle/excel/feather/hdf(<path>)       # To_hdf() requires `key='<df_name>'` argument.
 <DF>.to_sql('<table_name>', <connection>)      # Also `if_exists='fail/replace/append'`.
 ```
-* **Read\_csv() only parses dates of columns that were specified by 'parse\_dates' argument. It automatically tries to detect the format, but it can be helped with 'date\_format' or 'datefirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.**
+* **`'$ pip3 install "pandas[excel]" odfpy lxml pyarrow'` installs dependencies.**
+* **Read\_csv() only parses dates of columns that were specified by 'parse\_dates' argument. It automatically tries to detect the format, but it can be helped with 'date\_format' or 'dayfirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.**
 * **If there's a single invalid date then it returns the whole column as a series of strings, unlike `'<S> = pd.to_datetime(<S>, errors="coerce")'`, which uses pd.NaT.**
 * **To get specific attributes from a series of Timestamps use `'<S>.dt.year/date/…'`.**
 
diff --git a/index.html b/index.html
index e9492d15f..eeb2d0e08 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 26, 2024</aside>
+    <aside>December 27, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2724,25 +2724,25 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </ul>
 <div><h4 id="dataframemultiindex">DataFrame — Multi-Index:</h4><pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt;.xs(key, level=&lt;int&gt;)             <span class="hljs-comment"># Rows with key on passed level of multi-index.</span>
 &lt;DF&gt;   = &lt;DF&gt;.xs(keys, level=&lt;ints&gt;, axis=<span class="hljs-number">1</span>)   <span class="hljs-comment"># Cols that have first key on first level, etc.</span>
-&lt;DF&gt;   = &lt;DF&gt;.set_index(col_keys)              <span class="hljs-comment"># Combines multiple columns into a multi-index.</span>
+&lt;DF&gt;   = &lt;DF&gt;.set_index(col_keys)              <span class="hljs-comment"># Creates index from cols. Also `append=False`.</span>
 &lt;S/DF&gt; = &lt;DF&gt;.stack/unstack(level=<span class="hljs-number">-1</span>)          <span class="hljs-comment"># Combines col keys with row keys or vice versa.</span>
 &lt;DF&gt;   = &lt;DF&gt;.pivot_table(index=col_key/s)     <span class="hljs-comment"># `columns=key/s, values=key/s, aggfunc='mean'`.</span>
 </code></pre></div>
 
-<div><h4 id="dataframeencodedecode">DataFrame — Encode, Decode:</h4><pre><code class="python language-python hljs">&lt;DF&gt;   = pd.read_json/pickle(&lt;path/url/file&gt;)  <span class="hljs-comment"># Also accepts io.StringIO/BytesIO(&lt;str/bytes&gt;).</span>
-&lt;DF&gt;   = pd.read_csv(&lt;path/url/file&gt;)          <span class="hljs-comment"># `header/index_col/dtype/usecols/…=&lt;obj&gt;`.</span>
-&lt;DF&gt;   = pd.read_excel(&lt;path/url/file&gt;)        <span class="hljs-comment"># `sheet_name=None` returns dict of all sheets.</span>
-&lt;DF&gt;   = pd.read_sql(<span class="hljs-string">'&lt;table/query&gt;'</span>, &lt;conn&gt;)  <span class="hljs-comment"># SQLite3/SQLAlchemy connection (see #SQLite).</span>
-&lt;list&gt; = pd.read_html(&lt;path/url/file&gt;)         <span class="hljs-comment"># Run `$ pip3 install beautifulsoup4 lxml`.</span>
+<div><h3 id="fileformats">File Formats</h3><pre><code class="python language-python hljs">&lt;S/DF&gt; = pd.read_json/pickle(&lt;path/url/file&gt;)  <span class="hljs-comment"># Also accepts io.StringIO/BytesIO(&lt;str/bytes&gt;).</span>
+&lt;DF&gt;   = pd.read_csv/excel(&lt;path/url/file&gt;)    <span class="hljs-comment"># Also `header/index_col/dtype/usecols/…=&lt;obj&gt;`.</span>
+&lt;list&gt; = pd.read_html(&lt;path/url/file&gt;)         <span class="hljs-comment"># Raises ImportError if webpage has zero tables.</span>
+&lt;S/DF&gt; = pd.read_parquet/feather/hdf(&lt;path…&gt;)  <span class="hljs-comment"># Read_hdf() accepts `key='&lt;df_name&gt;'` argument.</span>
+&lt;DF&gt;   = pd.read_sql(<span class="hljs-string">'&lt;table/query&gt;'</span>, &lt;conn&gt;)  <span class="hljs-comment"># Pass SQLite3/Alchemy connection (see #SQLite).</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs">&lt;dict&gt; = &lt;DF&gt;.to_dict(<span class="hljs-string">'d/l/s/…'</span>)               <span class="hljs-comment"># Returns columns as dicts, lists or series.</span>
-&lt;str&gt;  = &lt;DF&gt;.to_json/csv/html/latex()         <span class="hljs-comment"># Saves output to a file if path is passed.</span>
-&lt;DF&gt;.to_pickle/excel(&lt;path&gt;)                   <span class="hljs-comment"># Run `$ pip3 install "pandas[excel]" odfpy`.</span>
+<pre><code class="python language-python hljs">&lt;DF&gt;.to_json/csv/html/parquet/latex(&lt;path&gt;)    <span class="hljs-comment"># Returns a string/bytes if path is omitted.</span>
+&lt;DF&gt;.to_pickle/excel/feather/hdf(&lt;path&gt;)       <span class="hljs-comment"># To_hdf() requires `key='&lt;df_name&gt;'` argument.</span>
 &lt;DF&gt;.to_sql(<span class="hljs-string">'&lt;table_name&gt;'</span>, &lt;connection&gt;)      <span class="hljs-comment"># Also `if_exists='fail/replace/append'`.</span>
 </code></pre>
 <ul>
-<li><strong>Read_csv() only parses dates of columns that were specified by 'parse_dates' argument. It&nbsp;automatically tries to detect the format, but it can be helped with 'date_format' or 'datefirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.</strong></li>
+<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>Read_csv() only parses dates of columns that were specified by 'parse_dates' argument. It&nbsp;automatically tries to detect the format, but it can be helped with 'date_format' or 'dayfirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.</strong></li>
 <li><strong>If there's a single invalid date then it returns the whole column as a series of strings, unlike <code class="python hljs"><span class="hljs-string">'&lt;S&gt; = pd.to_datetime(&lt;S&gt;, errors="coerce")'</span></code>, which uses pd.NaT.</strong></li>
 <li><strong>To get specific attributes from a series of Timestamps use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.dt.year/date/…'</span></code>.</strong></li>
 </ul>
@@ -2934,7 +2934,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 26, 2024</aside>
+    <aside>December 27, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From ce0f8ae83844b6af07eed253432f4f85efc8b62d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 27 Dec 2024 10:57:13 +0100
Subject: [PATCH 063/186] Updated index

---
 pdf/index_for_pdf.html       | 14 +++++++-------
 pdf/index_for_pdf_print.html |  2 +-
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html
index 86a2722bb..735f3c206 100644
--- a/pdf/index_for_pdf.html
+++ b/pdf/index_for_pdf.html
@@ -25,12 +25,12 @@ <h3 id="c">C</h3>
 <strong>collections module, <a href="#dictionary">2</a>, <a href="#namedtuple">3</a>, <a href="#abstractbaseclasses">4</a>, <a href="#abcsequence">19</a>, <a href="#deque">29</a></strong><br>
 <strong>combinatorics, <a href="#combinatorics">8</a></strong><br>
 <strong>command line arguments, <a href="#commandlinearguments">22</a></strong><br>
-<strong>comprehensions, <a href="#comprehensions">11</a></strong><br>
+<strong>comprehensions, <a href="#list">1</a>, <a href="#dictionary">2</a>, <a href="#comprehensions">11</a></strong><br>
 <strong>context manager, <a href="#contextmanager">17</a>, <a href="#readtextfromfile">23</a>, <a href="#or">27</a>, <a href="#or-1">32</a></strong><br>
 <strong>copy function, <a href="#copy">15</a></strong><br>
 <strong>coroutine, <a href="#coroutines">33</a></strong><br>
 <strong>counter, <a href="#counter">2</a>, <a href="#generator">4</a>, <a href="#nonlocal">12</a>, <a href="#iterator-1">17</a></strong><br>
-<strong>csv, <a href="#csv">26</a>, <a href="#printsacsvspreadsheettotheconsole">34</a>, <a href="#dataframeencodedecode">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a></strong><br>
+<strong>csv, <a href="#csv">26</a>, <a href="#printsacsvspreadsheettotheconsole">34</a>, <a href="#fileformats">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a></strong><br>
 <strong>curses module, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a>, <a href="#consoleapp">34</a></strong><br>
 <strong>cython, <a href="#typeannotations">15</a>, <a href="#cython">49</a></strong>  </p>
 <h3 id="d">D</h3>
@@ -43,11 +43,11 @@ <h3 id="d">D</h3>
 <h3 id="e">E</h3>
 <p><strong>enum module, <a href="#enum">19</a>-<a href="#inline-1">20</a></strong><br>
 <strong>enumerate function, <a href="#enumerate">3</a></strong><br>
-<strong>excel, <a href="#dataframeencodedecode">46</a></strong><br>
+<strong>excel, <a href="#fileformats">46</a></strong><br>
 <strong>exceptions, <a href="#exceptions">20</a>-<a href="#exceptionobject">21</a>, <a href="#exceptions-1">23</a>, <a href="#logging">31</a></strong><br>
 <strong>exit function, <a href="#exit">21</a></strong>  </p>
 <h3 id="f">F</h3>
-<p><strong>files, <a href="#print">22</a>-<a href="#memoryview">29</a>, <a href="#runsabasicfileexplorerintheconsole">34</a>, <a href="#dataframeencodedecode">46</a></strong><br>
+<p><strong>files, <a href="#print">22</a>-<a href="#memoryview">29</a>, <a href="#runsabasicfileexplorerintheconsole">34</a>, <a href="#fileformats">46</a></strong><br>
 <strong>filter function, <a href="#mapfilterreduce">11</a></strong><br>
 <strong>flask library, <a href="#webapp">36</a></strong><br>
 <strong>floats, <a href="#abstractbaseclasses">4</a>, <a href="#floats">6</a>, <a href="#numbers">7</a></strong><br>
@@ -73,7 +73,7 @@ <h3 id="i">I</h3>
 <strong>iterator, <a href="#enumerate">3</a>-<a href="#generator">4</a>, <a href="#comprehensions">11</a>, <a href="#iterator-1">17</a></strong><br>
 <strong>itertools module, <a href="#itertools">3</a>, <a href="#combinatorics">8</a></strong>  </p>
 <h3 id="j">J</h3>
-<p><strong>json, <a href="#json">25</a>, <a href="#restrequest">36</a>, <a href="#dataframeencodedecode">46</a></strong>  </p>
+<p><strong>json, <a href="#json">25</a>, <a href="#restrequest">36</a>, <a href="#fileformats">46</a></strong>  </p>
 <h3 id="l">L</h3>
 <p><strong>lambda, <a href="#lambda">11</a></strong><br>
 <strong>lists, <a href="#list">1</a>-<a href="#list">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
@@ -119,14 +119,14 @@ <h3 id="r">R</h3>
 <strong>requests library, <a href="#scrapespythonsurlandlogofromitswikipediapage">35</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong>  </p>
 <h3 id="s">S</h3>
 <p><strong>scope, <a href="#insidefunctiondefinition">10</a>, <a href="#nonlocal">12</a>, <a href="#complexexample">20</a></strong><br>
-<strong>scraping, <a href="#scraping">35</a>, <a href="#basicmariobrothersexample">43</a>, <a href="#dataframeencodedecode">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
+<strong>scraping, <a href="#scraping">35</a>, <a href="#basicmariobrothersexample">43</a>, <a href="#fileformats">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
 <strong>sequence, <a href="#abstractbaseclasses">4</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a></strong><br>
 <strong>sets, <a href="#set">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
 <strong>shell commands, <a href="#shellcommands">25</a></strong><br>
 <strong>sleep function, <a href="#progressbar">34</a></strong><br>
 <strong>sortable, <a href="#list">1</a>, <a href="#sortable">16</a></strong><br>
 <strong>splat operator, <a href="#splatoperator">10</a>-<a href="#otheruses">11</a>, <a href="#readrowsfromcsvfile">26</a></strong><br>
-<strong>sql, <a href="#sqlite">27</a>, <a href="#dataframeencodedecode">46</a></strong><br>
+<strong>sql, <a href="#sqlite">27</a>, <a href="#fileformats">46</a></strong><br>
 <strong>statistics, <a href="#statistics">7</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#pandas">44</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
 <strong>strings, <a href="#abstractbaseclasses">4</a>-<a href="#comparisonofpresentationtypes">7</a>, <a href="#class">14</a></strong><br>
 <strong>struct module, <a href="#struct">28</a>-<a href="#integertypesuseacapitalletterforunsignedtypeminimumandstandardsizesareinbrackets">29</a></strong><br>
diff --git a/pdf/index_for_pdf_print.html b/pdf/index_for_pdf_print.html
index 41ecf8940..5c20dd81a 100644
--- a/pdf/index_for_pdf_print.html
+++ b/pdf/index_for_pdf_print.html
@@ -25,7 +25,7 @@ <h3 id="c">C</h3>
 <strong>collections module, 2, 3, 4, 19, 29</strong><br>
 <strong>combinatorics, 8</strong><br>
 <strong>command line arguments, 22</strong><br>
-<strong>comprehensions, 11</strong><br>
+<strong>comprehensions, 1, 2, 11</strong><br>
 <strong>context manager, 17, 23, 27, 32</strong><br>
 <strong>copy function, 15</strong><br>
 <strong>coroutine, 33</strong><br>

From 87cf50423366c545e82120e2c9957b07ac03f6cd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 27 Dec 2024 17:35:13 +0100
Subject: [PATCH 064/186] Plotly

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 8d3d95d15..a9dcb7431 100644
--- a/README.md
+++ b/README.md
@@ -3457,7 +3457,7 @@ px.line(df, x='Date', y='Total Deaths per Million', color='Continent').show()
 <div id="e23ccacc-a456-478b-b467-7282a2165921" class="plotly-graph-div" style="height:287px; width:935px;"></div>
 
 ```python
-# $ pip3 install pandas selenium plotly lxml
+# $ pip3 install pandas lxml selenium plotly
 import pandas as pd, selenium.webdriver, plotly.graph_objects as go
 
 
@@ -3500,7 +3500,7 @@ def display_data(df):
     figure = go.Figure()
     for col_name in reversed(df.columns):
         yaxis = 'y1' if col_name == 'Total Cases' else 'y2'
-        trace = go.Scatter(x=df.index, y=df[col_name], name=col_name, yaxis=yaxis)
+        trace = go.Scatter(x=df.index, y=df[col_name], yaxis=yaxis, name=col_name)
         figure.add_trace(trace)
     figure.update_layout(
         width=944,
diff --git a/index.html b/index.html
index eeb2d0e08..9adf4a24b 100644
--- a/index.html
+++ b/index.html
@@ -2805,7 +2805,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<div><h4 id="displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">Displays a multi-axis line chart of total coronavirus 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:287px; width:935px;"></div><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pandas selenium plotly lxml</span>
+<div><h4 id="displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">Displays a multi-axis line chart of total coronavirus 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:287px; 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, plotly.graph_objects <span class="hljs-keyword">as</span> go
 
 
@@ -2848,7 +2848,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     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], name=col_name, yaxis=yaxis)
+        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>,

From d889381ad6d6b67994e44d4436477d127ffacf33 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 27 Dec 2024 17:57:37 +0100
Subject: [PATCH 065/186] Plotly

---
 README.md  | 1 -
 index.html | 1 -
 2 files changed, 2 deletions(-)

diff --git a/README.md b/README.md
index a9dcb7431..dbbd3fad8 100644
--- a/README.md
+++ b/README.md
@@ -3460,7 +3460,6 @@ px.line(df, x='Date', y='Total Deaths per Million', color='Continent').show()
 # $ pip3 install pandas lxml selenium plotly
 import pandas as pd, selenium.webdriver, plotly.graph_objects as go
 
-
 def main():
     covid, (bitcoin, gold, dow) = get_covid_cases(), get_tickers()
     df = wrangle_data(covid, bitcoin, gold, dow)
diff --git a/index.html b/index.html
index 9adf4a24b..b22cdb9a8 100644
--- a/index.html
+++ b/index.html
@@ -2808,7 +2808,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <div><h4 id="displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">Displays a multi-axis line chart of total coronavirus 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:287px; 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, 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)

From 975da0c2645fa5a0b4868bc3bdb6b7a5d7ac9a1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 31 Dec 2024 20:14:11 +0100
Subject: [PATCH 066/186] Removed links to PDF

---
 README.md     | 3 +--
 index.html    | 9 ++++-----
 parse.js      | 5 ++---
 pdf/README.md | 1 -
 4 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/README.md b/README.md
index dbbd3fad8..284a7d0ee 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 Comprehensive Python Cheatsheet
 ===============================
-<sup>[Download text file](https://raw.githubusercontent.com/gto76/python-cheatsheet/main/README.md), [Buy PDF](https://transactions.sendowl.com/products/78175486/4422834F/view), [Fork me on GitHub](https://github.com/gto76/python-cheatsheet) or [Check out FAQ](https://github.com/gto76/python-cheatsheet/wiki/Frequently-Asked-Questions).
+<sup>[Download text file](https://raw.githubusercontent.com/gto76/python-cheatsheet/main/README.md), [Fork me on GitHub](https://github.com/gto76/python-cheatsheet) or [Check out FAQ](https://github.com/gto76/python-cheatsheet/wiki/Frequently-Asked-Questions).
 </sup>
 
 ![Monty Python](web/image_888.jpeg)
@@ -3591,7 +3591,6 @@ if __name__ == '__main__':
 
 Index
 -----
-* **Only available in the [PDF](https://transactions.sendowl.com/products/78175486/4422834F/view).**
 * **Ctrl+F / ⌘F is usually sufficient.**
 * **Searching `'#<title>'` on the [webpage](https://gto76.github.io/python-cheatsheet/) will limit the search to the titles.**
 * **Click on the title's `'🔗'` to get a link to its section.**
diff --git a/index.html b/index.html
index b22cdb9a8..ad587b8bb 100644
--- a/index.html
+++ b/index.html
@@ -55,11 +55,11 @@
 
 <body>
   <header>
-    <aside>December 27, 2024</aside>
+    <aside>December 31, 2024</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://transactions.sendowl.com/products/78175486/4422834F/view">Buy PDF</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>.
+   <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"></p><script>
   // Changes the image and link to theme if URL ends with "index.html?theme=dark". 
   if (window.location.search.search(/[?&]theme=dark/) !== -1) {
@@ -2925,15 +2925,14 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 
-<div><h2 id="index"><a href="#index" name="index">#</a>Index</h2><ul><li><strong>Only available in the <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">PDF</a>.</strong></li>
-<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>
+<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">'#&lt;title&gt;'</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>December 27, 2024</aside>
+    <aside>December 31, 2024</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 7ab29869b..eead0c905 100755
--- a/parse.js
+++ b/parse.js
@@ -334,7 +334,6 @@ const CYTHON_3 =
   '<span class="hljs-keyword">cdef</span> <span class="hljs-keyword">enum</span> &lt;enum_name&gt;: &lt;member_name&gt;, &lt;member_name&gt;, ...\n';
 
 const INDEX =
-  '<li><strong>Only available in the <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">PDF</a>.</strong></li>\n' +
   '<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>\n' +
   '<li><strong>Searching <code class="python hljs"><span class="hljs-string">\'#&lt;title&gt;\'</span></code> will limit the search to the titles.</strong></li>\n' +
   '<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>\n';
@@ -670,7 +669,7 @@ const DIAGRAM_18_B =
   "┃                 │  c  11  13  │   c  2  2   │             │               ┃\n" +
   "┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n";
 
-const MENU = '<a href="https://raw.githubusercontent.com/gto76/python-cheatsheet/main/README.md">Download text file</a>, <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">Buy PDF</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>.\n';
+const MENU = '<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>.\n';
 
 const DARK_THEME_SCRIPT =
   '<script>\n' +
@@ -854,7 +853,7 @@ function fixHighlights() {
   $(`code:contains(cdef <ctype/type> <var_name> [= <obj>])`).html(CYTHON_1);
   $(`code:contains(cdef class <class_name>:)`).html(CYTHON_2);
   $(`code:contains(cdef enum <enum_name>: <member_name>, <member_name>, ...)`).html(CYTHON_3);
-  $(`ul:contains(Only available in)`).html(INDEX);
+  $(`ul:contains(Ctrl+F / ⌘F is usually sufficient.)`).html(INDEX);
 }
 
 function preventPageBreaks() {
diff --git a/pdf/README.md b/pdf/README.md
index 6e806f125..3c6d59b6a 100644
--- a/pdf/README.md
+++ b/pdf/README.md
@@ -1,6 +1,5 @@
 How To Create PDF (on macOS)
 ============================
-**PDF file can also be purchased here: https://transactions.sendowl.com/products/78175486/4422834F/view**
 
 
 Setup

From 6a68eade1128121d5e1e4bb5e535902958854558 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 31 Dec 2024 20:23:21 +0100
Subject: [PATCH 067/186] Arithmetics syntax highlight

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 284a7d0ee..5ed44377e 100644
--- a/README.md
+++ b/README.md
@@ -660,7 +660,7 @@ import zoneinfo, dateutil.tz
 * **`'%Z'` accepts `'UTC/GMT'` and local timezone's code and returns timezone's name, `'UTC[±HH:MM]'` if timezone is nameless, or an empty string if datetime is naive.**
 
 ### Arithmetics
-```python
+```bash
 <bool>   = <D/T/DTn> > <D/T/DTn>            # Ignores time jumps (fold attribute). Also ==.
 <bool>   = <DTa>     > <DTa>                # Ignores jumps if they share tz object. Broken ==.
 <TD>     = <D/DTn>   - <D/DTn>              # Ignores jumps. Convert to UTC for actual delta.

From fc72916e781c1cfdbc9936f490b7724b70658d9f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 31 Dec 2024 20:26:27 +0100
Subject: [PATCH 068/186] Arithmetics syntax highlight

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 5ed44377e..17b6f7b55 100644
--- a/README.md
+++ b/README.md
@@ -660,7 +660,7 @@ import zoneinfo, dateutil.tz
 * **`'%Z'` accepts `'UTC/GMT'` and local timezone's code and returns timezone's name, `'UTC[±HH:MM]'` if timezone is nameless, or an empty string if datetime is naive.**
 
 ### Arithmetics
-```bash
+```perl
 <bool>   = <D/T/DTn> > <D/T/DTn>            # Ignores time jumps (fold attribute). Also ==.
 <bool>   = <DTa>     > <DTa>                # Ignores jumps if they share tz object. Broken ==.
 <TD>     = <D/DTn>   - <D/DTn>              # Ignores jumps. Convert to UTC for actual delta.

From f73254bb49739577c26e4243e66f34076619ffb0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 31 Dec 2024 20:30:45 +0100
Subject: [PATCH 069/186] Arithmetics syntax highlight

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 17b6f7b55..284a7d0ee 100644
--- a/README.md
+++ b/README.md
@@ -660,7 +660,7 @@ import zoneinfo, dateutil.tz
 * **`'%Z'` accepts `'UTC/GMT'` and local timezone's code and returns timezone's name, `'UTC[±HH:MM]'` if timezone is nameless, or an empty string if datetime is naive.**
 
 ### Arithmetics
-```perl
+```python
 <bool>   = <D/T/DTn> > <D/T/DTn>            # Ignores time jumps (fold attribute). Also ==.
 <bool>   = <DTa>     > <DTa>                # Ignores jumps if they share tz object. Broken ==.
 <TD>     = <D/DTn>   - <D/DTn>              # Ignores jumps. Convert to UTC for actual delta.

From 02e0f54a64ae88835bb9c33d9541d765105c9211 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 31 Dec 2024 20:34:07 +0100
Subject: [PATCH 070/186] Venvs syntax highlight

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 284a7d0ee..aa6c04cac 100644
--- a/README.md
+++ b/README.md
@@ -3548,7 +3548,7 @@ cdef class <class_name>:
 ### Virtual Environments
 **System for installing libraries directly into project's directory.**
 
-```bash
+```perl
 $ python3 -m venv NAME      # Creates virtual environment in current directory.
 $ source NAME/bin/activate  # Activates env. On Windows run `NAME\Scripts\activate`.
 $ pip3 install LIBRARY      # Installs the library into active environment.

From df7f7099bde7188b993c828ec127758784e30284 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 31 Dec 2024 20:36:22 +0100
Subject: [PATCH 071/186] Venvs syntax highlight

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index aa6c04cac..94b56e6b0 100644
--- a/README.md
+++ b/README.md
@@ -3548,7 +3548,7 @@ cdef class <class_name>:
 ### Virtual Environments
 **System for installing libraries directly into project's directory.**
 
-```perl
+```ruby
 $ python3 -m venv NAME      # Creates virtual environment in current directory.
 $ source NAME/bin/activate  # Activates env. On Windows run `NAME\Scripts\activate`.
 $ pip3 install LIBRARY      # Installs the library into active environment.

From 819aaef6243c1884800e01692a1f64cab0c4e38e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 31 Dec 2024 20:38:10 +0100
Subject: [PATCH 072/186] Venvs syntax highlight

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 94b56e6b0..a171df14a 100644
--- a/README.md
+++ b/README.md
@@ -3548,7 +3548,7 @@ cdef class <class_name>:
 ### Virtual Environments
 **System for installing libraries directly into project's directory.**
 
-```ruby
+```r
 $ python3 -m venv NAME      # Creates virtual environment in current directory.
 $ source NAME/bin/activate  # Activates env. On Windows run `NAME\Scripts\activate`.
 $ pip3 install LIBRARY      # Installs the library into active environment.

From 139e19ef40d79f90e24f92f2c6b2f71e2b3bea73 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 31 Dec 2024 20:48:54 +0100
Subject: [PATCH 073/186] Venvs syntax highlight

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index a171df14a..284a7d0ee 100644
--- a/README.md
+++ b/README.md
@@ -3548,7 +3548,7 @@ cdef class <class_name>:
 ### Virtual Environments
 **System for installing libraries directly into project's directory.**
 
-```r
+```bash
 $ python3 -m venv NAME      # Creates virtual environment in current directory.
 $ source NAME/bin/activate  # Activates env. On Windows run `NAME\Scripts\activate`.
 $ pip3 install LIBRARY      # Installs the library into active environment.

From 9246ee902a795f42428d1464a337b291be73d0db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 31 Dec 2024 20:50:07 +0100
Subject: [PATCH 074/186] Venvs syntax highlight

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 284a7d0ee..aa6c04cac 100644
--- a/README.md
+++ b/README.md
@@ -3548,7 +3548,7 @@ cdef class <class_name>:
 ### Virtual Environments
 **System for installing libraries directly into project's directory.**
 
-```bash
+```perl
 $ python3 -m venv NAME      # Creates virtual environment in current directory.
 $ source NAME/bin/activate  # Activates env. On Windows run `NAME\Scripts\activate`.
 $ pip3 install LIBRARY      # Installs the library into active environment.

From 84c0dd29a5c9d326a23a44b7166664df9142419f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 31 Dec 2024 20:57:08 +0100
Subject: [PATCH 075/186] Venvs syntax highlight

---
 index.html | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/index.html b/index.html
index ad587b8bb..b09b829d7 100644
--- a/index.html
+++ b/index.html
@@ -2887,8 +2887,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; &lt;arg_name&gt;)</span>:</span>
         self.&lt;attr_name&gt; = &lt;arg_name&gt;
 </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="bash language-bash hljs">$ python3 -m venv NAME      <span class="hljs-comment"># Creates virtual environment in current directory.</span>
-$ <span class="hljs-built_in">source</span> NAME/bin/activate  <span class="hljs-comment"># Activates env. On Windows run `NAME\Scripts\activate`.</span>
+<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 current directory.</span>
+$ source NAME/bin/activate  <span class="hljs-comment"># Activates env. On Windows run `NAME\Scripts\activate`.</span>
 $ pip3 install LIBRARY      <span class="hljs-comment"># Installs the library into active environment.</span>
 $ python3 FILE              <span class="hljs-comment"># Runs the script in active environment. Also `./FILE`.</span>
 $ deactivate                <span class="hljs-comment"># Deactivates the active virtual environment.</span>

From 116967dc8167d7e8e381f1d93692c9ad8b92b07c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 5 Jan 2025 17:06:44 +0100
Subject: [PATCH 076/186] Cleanup of parse.js

---
 parse.js | 8 --------
 1 file changed, 8 deletions(-)

diff --git a/parse.js b/parse.js
index eead0c905..6129c8cab 100755
--- a/parse.js
+++ b/parse.js
@@ -330,9 +330,6 @@ const CYTHON_2 =
   '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; &lt;arg_name&gt;)</span>:</span>\n' +
   '        self.&lt;attr_name&gt; = &lt;arg_name&gt;\n';
 
-const CYTHON_3 =
-  '<span class="hljs-keyword">cdef</span> <span class="hljs-keyword">enum</span> &lt;enum_name&gt;: &lt;member_name&gt;, &lt;member_name&gt;, ...\n';
-
 const INDEX =
   '<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>\n' +
   '<li><strong>Searching <code class="python hljs"><span class="hljs-string">\'#&lt;title&gt;\'</span></code> will limit the search to the titles.</strong></li>\n' +
@@ -778,7 +775,6 @@ function unindentBanner() {
 function updateDiagrams() {
   $(`code:contains(${DIAGRAM_1_A})`).html(DIAGRAM_1_B);
   $(`code:contains(${DIAGRAM_2_A})`).html(DIAGRAM_2_B);
-  $(`code:contains(${DIAGRAM_3_A})`).html(DIAGRAM_3_B);
   $(`code:contains(${DIAGRAM_4_A})`).html(DIAGRAM_4_B);
   $(`code:contains(${DIAGRAM_5_A})`).parent().remove();
   $(`code:contains(${DIAGRAM_6_A})`).html(DIAGRAM_6_B);
@@ -786,8 +782,6 @@ function updateDiagrams() {
   $(`code:contains(${DIAGRAM_8_A})`).html(DIAGRAM_8_B);
   $(`code:contains(${DIAGRAM_9_A})`).html(DIAGRAM_9_B);
   $(`code:contains(${DIAGRAM_95_A})`).html(DIAGRAM_95_B);
-  $(`code:contains(${DIAGRAM_10_A})`).html(DIAGRAM_10_B);
-  $(`code:contains(${DIAGRAM_11_A})`).html(DIAGRAM_11_B);
   $(`code:contains(${DIAGRAM_115_A})`).html(DIAGRAM_115_B);
   $(`code:contains(${DIAGRAM_12_A})`).html(DIAGRAM_12_B).removeClass("text").removeClass("language-text").addClass("python");
   $(`code:contains(${DIAGRAM_13_A})`).html(DIAGRAM_13_B).removeClass("text").removeClass("language-text").addClass("python");
@@ -795,7 +789,6 @@ function updateDiagrams() {
   $(`code:contains(${DIAGRAM_15_A})`).html(DIAGRAM_15_B).removeClass("text").removeClass("language-text").addClass("python");
   $(`code:contains(${DIAGRAM_16_A})`).html(DIAGRAM_16_B).removeClass("text").removeClass("language-text").addClass("python");
   $(`code:contains(${DIAGRAM_17_A})`).parent().remove();
-  $(`code:contains(${DIAGRAM_18_A})`).html(DIAGRAM_18_B).removeClass("text").removeClass("language-text").addClass("python");
 }
 
 function highlightCode() {
@@ -852,7 +845,6 @@ function fixHighlights() {
   $(`code:contains(>>> gb = df.groupby)`).html(GROUPBY);
   $(`code:contains(cdef <ctype/type> <var_name> [= <obj>])`).html(CYTHON_1);
   $(`code:contains(cdef class <class_name>:)`).html(CYTHON_2);
-  $(`code:contains(cdef enum <enum_name>: <member_name>, <member_name>, ...)`).html(CYTHON_3);
   $(`ul:contains(Ctrl+F / ⌘F is usually sufficient.)`).html(INDEX);
 }
 

From 1bb76d1285c8b6d4765e3aba8dbac3a745882463 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 11 Jan 2025 14:07:32 +0100
Subject: [PATCH 077/186] Datetime, Pandas big changes to Series

---
 README.md  | 20 ++++++++++----------
 index.html | 24 ++++++++++++------------
 2 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/README.md b/README.md
index aa6c04cac..9c863de60 100644
--- a/README.md
+++ b/README.md
@@ -662,12 +662,12 @@ import zoneinfo, dateutil.tz
 ### Arithmetics
 ```python
 <bool>   = <D/T/DTn> > <D/T/DTn>            # Ignores time jumps (fold attribute). Also ==.
-<bool>   = <DTa>     > <DTa>                # Ignores jumps if they share tz object. Broken ==.
+<bool>   = <DTa>     > <DTa>                # Ignores time jumps if they share tzinfo object.
 <TD>     = <D/DTn>   - <D/DTn>              # Ignores jumps. Convert to UTC for actual delta.
 <TD>     = <DTa>     - <DTa>                # Ignores jumps if they share tzinfo object.
 <D/DT>   = <D/DT>    ± <TD>                 # Returned datetime can fall into missing hour.
-<TD>     = <TD>      * <float>              # Also: <TD> = abs(<TD>) and <TD> = <TD> ±% <TD>.
-<float>  = <TD>      / <TD>                 # E.g. how many hours are in TD. Also //, divmod().
+<TD>     = <TD>      * <float>              # Also `<TD> = abs(<TD>)`, `<TD> = <TD> ± <TD>`.
+<float>  = <TD>      / <TD>                 # Also `<int>, <TD> = divmod(<TD>, <TD>)`.
 ```
 
 
@@ -3165,6 +3165,7 @@ Name: a, dtype: int64
 ```python
 <S>  = pd.Series(<list>)                       # Uses list's indices for 'index'.
 <S>  = pd.Series(<dict>)                       # Uses dictionary's keys for 'index'.
+<S>  = pd.concat(<coll_of_S>)                  # Also <S>.combine_first(<S>), <S>.update(<S>).
 ```
 
 ```python
@@ -3176,18 +3177,17 @@ Name: a, dtype: int64
 ```python
 <el> = <S>[key/i]                              # Or: <S>.<key>
 <S>  = <S>[coll_of_keys/coll_of_i]             # Or: <S>[key/i : key/i]
-<S>  = <S>[bools]                              # Or: <S>.loc/iloc[bools]
+<S>  = <S>[<S_of_bools>]                       # Or: <S>.loc/iloc[<S_of_bools>]
 ```
 
 ```python
-<S>  = <S> > <el/S>                            # Returns S of bools. Pairs items by keys.
+<S>  = <S> > <el/S>                            # Returns S of bools. For logic use &, |, ~.
 <S>  = <S> + <el/S>                            # Items with non-matching keys get value NaN.
 ```
 
 ```python
-<S> = pd.concat(<coll_of_S>)                   # Concats multiple series into one long Series.
-<S> = <S>.combine_first(<S>)                   # Adds items that are not yet present.
-<S>.update(<S>)                                # Updates items that are already present.
+<S>  = <S>.value_counts(normalize=False)       # Returns S of unique values and their counts.
+<S>  = <S>.str.strip/lower/contains/replace()  # Processes strings. For dates see File Formats.
 ```
 
 ```python
@@ -3199,7 +3199,7 @@ Name: a, dtype: int64
 
 #### Series — Aggregate, Transform, Map:
 ```python
-<el> = <S>.sum/max/mean/idxmax/all()           # Or: <S>.agg(lambda <S>: <el>)
+<el> = <S>.sum/max/mean/idxmax/all/count()     # Or: <S>.agg(lambda <S>: <el>)
 <S>  = <S>.rank/diff/cumsum/ffill/interpol…()  # Or: <S>.agg/transform(lambda <S>: <S>)
 <S>  = <S>.isna/fillna/isin([<el/coll>])       # Or: <S>.agg/transform/map(lambda <el>: <el>)
 ```
@@ -3314,7 +3314,7 @@ c  6  7
 
 #### DataFrame — Aggregate, Transform, Map:
 ```python
-<S>  = <DF>.sum/max/mean/idxmax/all()          # Or: <DF>.apply/agg(lambda <S>: <el>)
+<S>  = <DF>.sum/max/mean/idxmax/all/count()    # Or: <DF>.apply/agg(lambda <S>: <el>)
 <DF> = <DF>.rank/diff/cumsum/ffill/interpo…()  # Or: <DF>.apply/agg/transform(lambda <S>: <S>)
 <DF> = <DF>.isna/fillna/isin([<el/coll>])      # Or: <DF>.applymap(lambda <el>: <el>)
 ```
diff --git a/index.html b/index.html
index b09b829d7..a02afbee3 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>December 31, 2024</aside>
+    <aside>January 11, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -579,12 +579,12 @@
 <li><strong><code class="python hljs"><span class="hljs-string">'%Z'</span></code> accepts <code class="python hljs"><span class="hljs-string">'UTC/GMT'</span></code> and 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 datetime is naive.</strong></li>
 </ul>
 <div><h3 id="arithmetics">Arithmetics</h3><pre><code class="python language-python apache hljs">&lt;bool&gt;   = &lt;D/T/DTn&gt; &gt; &lt;D/T/DTn&gt;            <span class="hljs-comment"># Ignores time jumps (fold attribute). Also ==.</span>
-&lt;bool&gt;   = &lt;DTa&gt;     &gt; &lt;DTa&gt;                <span class="hljs-comment"># Ignores jumps if they share tz object. Broken ==.</span>
+&lt;bool&gt;   = &lt;DTa&gt;     &gt; &lt;DTa&gt;                <span class="hljs-comment"># Ignores time jumps if they share tzinfo object.</span>
 &lt;TD&gt;     = &lt;D/DTn&gt;   - &lt;D/DTn&gt;              <span class="hljs-comment"># Ignores jumps. Convert to UTC for actual delta.</span>
 &lt;TD&gt;     = &lt;DTa&gt;     - &lt;DTa&gt;                <span class="hljs-comment"># Ignores jumps if they share tzinfo object.</span>
 &lt;D/DT&gt;   = &lt;D/DT&gt;    ± &lt;TD&gt;                 <span class="hljs-comment"># Returned datetime can fall into missing hour.</span>
-&lt;TD&gt;     = &lt;TD&gt;      * &lt;float&gt;              <span class="hljs-comment"># Also: &lt;TD&gt; = abs(&lt;TD&gt;) and &lt;TD&gt; = &lt;TD&gt; ±% &lt;TD&gt;.</span>
-&lt;float&gt;  = &lt;TD&gt;      / &lt;TD&gt;                 <span class="hljs-comment"># E.g. how many hours are in TD. Also //, divmod().</span>
+&lt;TD&gt;     = &lt;TD&gt;      * &lt;float&gt;              <span class="hljs-comment"># Also `&lt;TD&gt; = abs(&lt;TD&gt;)`, `&lt;TD&gt; = &lt;TD&gt; ± &lt;TD&gt;`.</span>
+&lt;float&gt;  = &lt;TD&gt;      / &lt;TD&gt;                 <span class="hljs-comment"># Also `&lt;int&gt;, &lt;TD&gt; = divmod(&lt;TD&gt;, &lt;TD&gt;)`.</span>
 </code></pre></div>
 
 <div><h2 id="arguments"><a href="#arguments" name="arguments">#</a>Arguments</h2><div><h3 id="insidefunctioncall">Inside Function Call</h3><pre><code class="python language-python hljs">func(&lt;positional_args&gt;)                           <span class="hljs-comment"># func(0, 0)</span>
@@ -2582,6 +2582,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <pre><code class="python language-python hljs">&lt;S&gt;  = pd.Series(&lt;list&gt;)                       <span class="hljs-comment"># Uses list's indices for 'index'.</span>
 &lt;S&gt;  = pd.Series(&lt;dict&gt;)                       <span class="hljs-comment"># Uses dictionary's keys for 'index'.</span>
+&lt;S&gt;  = pd.concat(&lt;coll_of_S&gt;)                  <span class="hljs-comment"># Also &lt;S&gt;.combine_first(&lt;S&gt;), &lt;S&gt;.update(&lt;S&gt;).</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.loc[key]                            <span class="hljs-comment"># Or: &lt;S&gt;.iloc[i]</span>
 &lt;S&gt;  = &lt;S&gt;.loc[coll_of_keys]                   <span class="hljs-comment"># Or: &lt;S&gt;.iloc[coll_of_i]</span>
@@ -2589,14 +2590,13 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;[key/i]                              <span class="hljs-comment"># Or: &lt;S&gt;.&lt;key&gt;</span>
 &lt;S&gt;  = &lt;S&gt;[coll_of_keys/coll_of_i]             <span class="hljs-comment"># Or: &lt;S&gt;[key/i : key/i]</span>
-&lt;S&gt;  = &lt;S&gt;[bools]                              <span class="hljs-comment"># Or: &lt;S&gt;.loc/iloc[bools]</span>
+&lt;S&gt;  = &lt;S&gt;[&lt;S_of_bools&gt;]                       <span class="hljs-comment"># Or: &lt;S&gt;.loc/iloc[&lt;S_of_bools&gt;]</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt; &gt; &lt;el/S&gt;                            <span class="hljs-comment"># Returns S of bools. Pairs items by keys.</span>
+<pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt; &gt; &lt;el/S&gt;                            <span class="hljs-comment"># Returns S of bools. For logic use &amp;, |, ~.</span>
 &lt;S&gt;  = &lt;S&gt; + &lt;el/S&gt;                            <span class="hljs-comment"># Items with non-matching keys get value NaN.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;S&gt; = pd.concat(&lt;coll_of_S&gt;)                   <span class="hljs-comment"># Concats multiple series into one long Series.</span>
-&lt;S&gt; = &lt;S&gt;.combine_first(&lt;S&gt;)                   <span class="hljs-comment"># Adds items that are not yet present.</span>
-&lt;S&gt;.update(&lt;S&gt;)                                <span class="hljs-comment"># Updates items that are already present.</span>
+<pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt;.value_counts(normalize=<span class="hljs-keyword">False</span>)       <span class="hljs-comment"># Returns S of unique values and their counts.</span>
+&lt;S&gt;  = &lt;S&gt;.str.strip/lower/contains/replace()  <span class="hljs-comment"># Processes strings. For dates see File Formats.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. `plt.show()` displays it.</span>
 </code></pre>
@@ -2605,7 +2605,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
 <li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
 </ul>
-<div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.sum/max/mean/idxmax/all()           <span class="hljs-comment"># Or: &lt;S&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
+<div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.sum/max/mean/idxmax/all/count()     <span class="hljs-comment"># Or: &lt;S&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;S&gt;  = &lt;S&gt;.rank/diff/cumsum/ffill/interpol…()  <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
 &lt;S&gt;  = &lt;S&gt;.isna/fillna/isin([&lt;el/coll&gt;])       <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform/map(lambda &lt;el&gt;: &lt;el&gt;)</span>
 </code></pre></div>
@@ -2696,7 +2696,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 ┃                       │ 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">&lt;S&gt;  = &lt;DF&gt;.sum/max/mean/idxmax/all()          <span class="hljs-comment"># Or: &lt;DF&gt;.apply/agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
+<div><h4 id="dataframeaggregatetransformmap">DataFrame — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;S&gt;  = &lt;DF&gt;.sum/max/mean/idxmax/all/count()    <span class="hljs-comment"># Or: &lt;DF&gt;.apply/agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;DF&gt; = &lt;DF&gt;.rank/diff/cumsum/ffill/interpo…()  <span class="hljs-comment"># Or: &lt;DF&gt;.apply/agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
 &lt;DF&gt; = &lt;DF&gt;.isna/fillna/isin([&lt;el/coll&gt;])      <span class="hljs-comment"># Or: &lt;DF&gt;.applymap(lambda &lt;el&gt;: &lt;el&gt;)</span>
 </code></pre></div>
@@ -2932,7 +2932,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>December 31, 2024</aside>
+    <aside>January 11, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From dddae77ab7e197a21a2261c71bc22f818cff49cc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 24 Jan 2025 02:40:52 +0100
Subject: [PATCH 078/186] Pandas

---
 README.md  |  8 +++----
 index.html | 12 +++++-----
 parse.js   | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index 9c863de60..c2c1af162 100644
--- a/README.md
+++ b/README.md
@@ -3165,7 +3165,6 @@ Name: a, dtype: int64
 ```python
 <S>  = pd.Series(<list>)                       # Uses list's indices for 'index'.
 <S>  = pd.Series(<dict>)                       # Uses dictionary's keys for 'index'.
-<S>  = pd.concat(<coll_of_S>)                  # Also <S>.combine_first(<S>), <S>.update(<S>).
 ```
 
 ```python
@@ -3186,8 +3185,9 @@ Name: a, dtype: int64
 ```
 
 ```python
-<S>  = <S>.value_counts(normalize=False)       # Returns S of unique values and their counts.
-<S>  = <S>.str.strip/lower/contains/replace()  # Processes strings. For dates see File Formats.
+<S>  = <S>.head/describe/copy/sort_values()    # Also <S>.unique/value_counts/round/dropna().
+<S>  = <S>.str.strip/lower/contains/replace()  # Also split().str[<int>] and split().explode().
+<S>  = <S>.dt.year/month/day/hour              # Use pd.to_datetime(<S>) to get S of dates.
 ```
 
 ```python
@@ -3222,7 +3222,7 @@ Name: a, dtype: int64
 |              |    y  2.0   |   y   2.0   |      y  2.0   |
 +--------------+-------------+-------------+---------------+
 ```
-* **Methods ffill(), interpolate(), fillna() and dropna() accept `'inplace=True'`.**
+* **Methods sort_values(), dropna(), ffill(), interpolate() and fillna() accept `'inplace=True'`.**
 * **Agg() and transform() pass a Series to a function if it raises Type/Val/AttrError on a scalar.**
 * **Last result has a multi-index. Use `'<S>[key_1, key_2]'` to get its values.**
 
diff --git a/index.html b/index.html
index a02afbee3..c5ce500fe 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>January 11, 2025</aside>
+    <aside>January 24, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2582,7 +2582,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <pre><code class="python language-python hljs">&lt;S&gt;  = pd.Series(&lt;list&gt;)                       <span class="hljs-comment"># Uses list's indices for 'index'.</span>
 &lt;S&gt;  = pd.Series(&lt;dict&gt;)                       <span class="hljs-comment"># Uses dictionary's keys for 'index'.</span>
-&lt;S&gt;  = pd.concat(&lt;coll_of_S&gt;)                  <span class="hljs-comment"># Also &lt;S&gt;.combine_first(&lt;S&gt;), &lt;S&gt;.update(&lt;S&gt;).</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.loc[key]                            <span class="hljs-comment"># Or: &lt;S&gt;.iloc[i]</span>
 &lt;S&gt;  = &lt;S&gt;.loc[coll_of_keys]                   <span class="hljs-comment"># Or: &lt;S&gt;.iloc[coll_of_i]</span>
@@ -2595,8 +2594,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt; &gt; &lt;el/S&gt;                            <span class="hljs-comment"># Returns S of bools. For logic use &amp;, |, ~.</span>
 &lt;S&gt;  = &lt;S&gt; + &lt;el/S&gt;                            <span class="hljs-comment"># Items with non-matching keys get value NaN.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt;.value_counts(normalize=<span class="hljs-keyword">False</span>)       <span class="hljs-comment"># Returns S of unique values and their counts.</span>
-&lt;S&gt;  = &lt;S&gt;.str.strip/lower/contains/replace()  <span class="hljs-comment"># Processes strings. For dates see File Formats.</span>
+<pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt;.head/describe/copy/sort_values()    <span class="hljs-comment"># Also &lt;S&gt;.unique/value_counts/round/dropna().</span>
+&lt;S&gt;  = &lt;S&gt;.str.strip/lower/contains/replace()  <span class="hljs-comment"># Also split().str[&lt;int&gt;] and split().explode().</span>
+&lt;S&gt;  = &lt;S&gt;.dt.year/month/day/hour              <span class="hljs-comment"># Use pd.to_datetime(&lt;S&gt;) to get S of dates.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. `plt.show()` displays it.</span>
 </code></pre>
@@ -2627,7 +2627,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 
 <ul>
-<li><strong>Methods ffill(), interpolate(), fillna() and dropna() accept <code class="python hljs"><span class="hljs-string">'inplace=True'</span></code>.</strong></li>
+<li><strong>Methods sort_values(), dropna(), ffill(), interpolate() and fillna() accept <code class="python hljs"><span class="hljs-string">'inplace=True'</span></code>.</strong></li>
 <li><strong>Agg() and transform() pass a Series to a function if it raises Type/Val/AttrError on a scalar.</strong></li>
 <li><strong>Last result has a multi-index. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;[key_1, key_2]'</span></code> to get its values.</strong></li>
 </ul>
@@ -2932,7 +2932,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>January 11, 2025</aside>
+    <aside>January 24, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 6129c8cab..01e4be1ac 100755
--- a/parse.js
+++ b/parse.js
@@ -591,6 +591,72 @@ const DIAGRAM_13_B =
   "┃              │    y  2.0   │   y   2.0   │      y  2.0   ┃\n" +
   "┗━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n";
 
+const DIAGRAM_13_BB =
+  "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" +
+  "┃                │    'mean'   │   ['mean']  │ {'m': 'mean'} ┃\n" +
+  "┠────────────────┼─────────────┼─────────────┼───────────────┨\n" +
+  "┃ s.apply/agg(…) │     1.5     │  mean  1.5  │     m  1.5    ┃\n" +
+  "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n" +
+  "\n" +
+  "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" +
+  "┃                │    'rank'   │   ['rank']  │ {'r': 'rank'} ┃\n" +
+  "┠────────────────┼─────────────┼─────────────┼───────────────┨\n" +
+  "┃ s.apply/agg(…) │             │      rank   │               ┃\n" +
+  "┃                │    x  1.0   │   x   1.0   │   r  x  1.0   ┃\n" +
+  "┃                │    y  2.0   │   y   2.0   │      y  2.0   ┃\n" +
+  "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n";
+
+const DIAGRAM_13_XXX =
+  "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━┓\n" +
+  "┃                │   'sum'   │ ['sum', 'max'] │   'rank'  │ ['rank', 'diff'] ┃\n" +
+  "┠────────────────┼───────────┼────────────────┼───────────┼──────────────────┨\n" +
+  "┃ s.apply/agg(…) │     3     │    sum    3    │  x  1.0   │     rank  diff   ┃\n" +
+  "┃                │           │    max    2    │  y  2.0   │  x   1.0   NaN   ┃\n" +
+  "┃                │           │    Name: a     │  Name: a  │  y   2.0   1.0   ┃\n" +
+  "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┛\n";
+
+const DIAGRAM_13_XX =
+  "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┓\n" +
+  "┃                │   'sum'   │   'rank'  │ ['sum', 'max'] ┃\n" +
+  "┠────────────────┼───────────┼───────────┼────────────────┨\n" +
+  "┃ s.apply/agg(…) │     3     │  x  1.0   │    sum    3    ┃\n" +
+  "┃                │           │  y  2.0   │    max    2    ┃\n" +
+  "┃                │           │  Name: a  │    Name: a     ┃\n" +
+  "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┛\n";
+
+const DIAGRAM_13_X =
+  "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━┓\n" +
+  "┃                │   'sum'   │   'rank'  │ ['sum', 'max'] │ ['rank', 'diff'] ┃\n" +
+  "┠────────────────┼───────────┼───────────┼────────────────┼──────────────────┨\n" +
+  "┃ s.apply/agg(…) │     3     │  x  1.0   │    sum    3    │     rank  diff   ┃\n" +
+  "┃                │           │  y  2.0   │    max    2    │  x   1.0   NaN   ┃\n" +
+  "┃                │           │  Name: a  │    Name: a     │  y   2.0   1.0   ┃\n" +
+  "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┛\n";
+
+const DIAGRAM_13_Y =
+  "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┓\n" +
+  "┃                │   'sum'   │   'rank'  │  ['sum']  │ ['rank']  ┃\n" +
+  "┠────────────────┼───────────┼───────────┼───────────┼───────────┨\n" +
+  "┃ s.apply/agg(…) │     3     │  x  1.0   │  sum 3    │     rank  ┃\n" +
+  "┃                │           │  y  2.0   │  Name: a  │  x   1.0  ┃\n" +
+  "┃                │           │  Name: a  │           │  y   2.0  ┃\n" +
+  "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━━━━━━┛\n";
+
+const DIAGRAM_13_BBB =
+  "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" +
+  "┃                │    'sum'    │   ['sum']   │ {'s': 'sum'}  ┃\n" +
+  "┠────────────────┼─────────────┼─────────────┼───────────────┨\n" +
+  "┃ s.apply/agg(…) │      3      │    sum  3   │     s  3      ┃\n" +
+  "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n" +
+  "\n" +
+  "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" +
+  "┃                │    'rank'   │   ['rank']  │ {'r': 'rank'} ┃\n" +
+  "┠────────────────┼─────────────┼─────────────┼───────────────┨\n" +
+  "┃ s.apply/agg(…) │             │      rank   │               ┃\n" +
+  "┃                │    x  1.0   │   x   1.0   │   r  x  1.0   ┃\n" +
+  "┃                │    y  2.0   │   y   2.0   │      y  2.0   ┃\n" +
+  "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n";
+
 const DIAGRAM_14_A =
   "|              |    'rank'   |   ['rank']  | {'r': 'rank'} |";
 

From 34e7afc8725ade221b1d004607293c04e0ab0ef3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 24 Jan 2025 02:50:41 +0100
Subject: [PATCH 079/186] Pandas

---
 README.md  | 1 -
 index.html | 1 -
 2 files changed, 2 deletions(-)

diff --git a/README.md b/README.md
index c2c1af162..890afb15e 100644
--- a/README.md
+++ b/README.md
@@ -3367,7 +3367,6 @@ c  6  7
 * **`'$ pip3 install "pandas[excel]" odfpy lxml pyarrow'` installs dependencies.**
 * **Read\_csv() only parses dates of columns that were specified by 'parse\_dates' argument. It automatically tries to detect the format, but it can be helped with 'date\_format' or 'dayfirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.**
 * **If there's a single invalid date then it returns the whole column as a series of strings, unlike `'<S> = pd.to_datetime(<S>, errors="coerce")'`, which uses pd.NaT.**
-* **To get specific attributes from a series of Timestamps use `'<S>.dt.year/date/…'`.**
 
 ### GroupBy
 **Object that groups together rows of a dataframe based on the value of the passed column.**
diff --git a/index.html b/index.html
index c5ce500fe..3da7b50d6 100644
--- a/index.html
+++ b/index.html
@@ -2744,7 +2744,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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>Read_csv() only parses dates of columns that were specified by 'parse_dates' argument. It&nbsp;automatically tries to detect the format, but it can be helped with 'date_format' or 'dayfirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.</strong></li>
 <li><strong>If there's a single invalid date then it returns the whole column as a series of strings, unlike <code class="python hljs"><span class="hljs-string">'&lt;S&gt; = pd.to_datetime(&lt;S&gt;, errors="coerce")'</span></code>, which uses pd.NaT.</strong></li>
-<li><strong>To get specific attributes from a series of Timestamps use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.dt.year/date/…'</span></code>.</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">&lt;GB&gt; = &lt;DF&gt;.groupby(col_key/s)                 <span class="hljs-comment"># Splits DF into groups based on passed column.</span>
 &lt;DF&gt; = &lt;GB&gt;.apply/filter(&lt;func&gt;)               <span class="hljs-comment"># Filter drops a group if func returns False.</span>

From f72fe945c2bdaa9bf551dbdf2cd455659017bd4d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 24 Jan 2025 19:52:55 +0100
Subject: [PATCH 080/186] Pandas

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 890afb15e..736cd2cd1 100644
--- a/README.md
+++ b/README.md
@@ -3185,7 +3185,7 @@ Name: a, dtype: int64
 ```
 
 ```python
-<S>  = <S>.head/describe/copy/sort_values()    # Also <S>.unique/value_counts/round/dropna().
+<S>  = <S>.head/describe/sort_values()         # Also <S>.unique/value_counts/round/dropna().
 <S>  = <S>.str.strip/lower/contains/replace()  # Also split().str[<int>] and split().explode().
 <S>  = <S>.dt.year/month/day/hour              # Use pd.to_datetime(<S>) to get S of dates.
 ```
@@ -3193,6 +3193,7 @@ Name: a, dtype: int64
 ```python
 <S>.plot.line/area/bar/pie/hist()              # Generates a plot. `plt.show()` displays it.
 ```
+* **Also: `'pd.cut(<S>, bins=<int/coll>)'`, `'<S>.quantile(<float/coll>)'`.**
 * **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`.**
 * **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
 * **Series will silently overflow if we run `'pd.Series([100], dtype="int8") + 100'`!**
@@ -3222,7 +3223,6 @@ Name: a, dtype: int64
 |              |    y  2.0   |   y   2.0   |      y  2.0   |
 +--------------+-------------+-------------+---------------+
 ```
-* **Methods sort_values(), dropna(), ffill(), interpolate() and fillna() accept `'inplace=True'`.**
 * **Agg() and transform() pass a Series to a function if it raises Type/Val/AttrError on a scalar.**
 * **Last result has a multi-index. Use `'<S>[key_1, key_2]'` to get its values.**
 
diff --git a/index.html b/index.html
index 3da7b50d6..5ff18a38c 100644
--- a/index.html
+++ b/index.html
@@ -2594,13 +2594,14 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt; &gt; &lt;el/S&gt;                            <span class="hljs-comment"># Returns S of bools. For logic use &amp;, |, ~.</span>
 &lt;S&gt;  = &lt;S&gt; + &lt;el/S&gt;                            <span class="hljs-comment"># Items with non-matching keys get value NaN.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt;.head/describe/copy/sort_values()    <span class="hljs-comment"># Also &lt;S&gt;.unique/value_counts/round/dropna().</span>
+<pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt;.head/describe/sort_values()         <span class="hljs-comment"># Also &lt;S&gt;.unique/value_counts/round/dropna().</span>
 &lt;S&gt;  = &lt;S&gt;.str.strip/lower/contains/replace()  <span class="hljs-comment"># Also split().str[&lt;int&gt;] and split().explode().</span>
 &lt;S&gt;  = &lt;S&gt;.dt.year/month/day/hour              <span class="hljs-comment"># Use pd.to_datetime(&lt;S&gt;) to get S of dates.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. `plt.show()` displays it.</span>
 </code></pre>
 <ul>
+<li><strong>Also: <code class="python hljs"><span class="hljs-string">'pd.cut(&lt;S&gt;, bins=&lt;int/coll&gt;)'</span></code>, <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.quantile(&lt;float/coll&gt;)'</span></code>.</strong></li>
 <li><strong>Indexing objects can't be tuples 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>.</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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
 <li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
@@ -2627,7 +2628,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 
 <ul>
-<li><strong>Methods sort_values(), dropna(), ffill(), interpolate() and fillna() accept <code class="python hljs"><span class="hljs-string">'inplace=True'</span></code>.</strong></li>
 <li><strong>Agg() and transform() pass a Series to a function if it raises Type/Val/AttrError on a scalar.</strong></li>
 <li><strong>Last result has a multi-index. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;[key_1, key_2]'</span></code> to get its values.</strong></li>
 </ul>

From fdd75e725842cf2cfb02459ff04503c983f63772 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 24 Jan 2025 19:53:59 +0100
Subject: [PATCH 081/186] Pandas

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 736cd2cd1..c78afd80d 100644
--- a/README.md
+++ b/README.md
@@ -3193,7 +3193,7 @@ Name: a, dtype: int64
 ```python
 <S>.plot.line/area/bar/pie/hist()              # Generates a plot. `plt.show()` displays it.
 ```
-* **Also: `'pd.cut(<S>, bins=<int/coll>)'`, `'<S>.quantile(<float/coll>)'`.**
+* **Also: `'pd.cut(<S>, bins=<int/coll>)'` and `'<S>.quantile(<float/coll>)'`.**
 * **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`.**
 * **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
 * **Series will silently overflow if we run `'pd.Series([100], dtype="int8") + 100'`!**
diff --git a/index.html b/index.html
index 5ff18a38c..4d7c1a455 100644
--- a/index.html
+++ b/index.html
@@ -2601,7 +2601,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. `plt.show()` displays it.</span>
 </code></pre>
 <ul>
-<li><strong>Also: <code class="python hljs"><span class="hljs-string">'pd.cut(&lt;S&gt;, bins=&lt;int/coll&gt;)'</span></code>, <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.quantile(&lt;float/coll&gt;)'</span></code>.</strong></li>
+<li><strong>Also: <code class="python hljs"><span class="hljs-string">'pd.cut(&lt;S&gt;, bins=&lt;int/coll&gt;)'</span></code> and <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.quantile(&lt;float/coll&gt;)'</span></code>.</strong></li>
 <li><strong>Indexing objects can't be tuples 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>.</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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
 <li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>

From 917b82c7a0f7447ccf52d7572a6ea3c4226324e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 3 Feb 2025 21:59:24 +0100
Subject: [PATCH 082/186] CSV, Pandas multi-index

---
 README.md  | 14 +++++++-------
 index.html | 16 ++++++++--------
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/README.md b/README.md
index c78afd80d..1019b9aae 100644
--- a/README.md
+++ b/README.md
@@ -1104,7 +1104,7 @@ Duck Types
 
 ### Comparable
 * **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`.**
-* **That means all objects compare not equal by default.**
+* **That means all user-defined objects compare not equal by default.**
 * **Only the left side object has eq() method called, unless it returns NotImplemented, in which case the right object is consulted. False is returned if both return NotImplemented.**
 * **Ne() automatically works on any object that has eq() defined.**
 
@@ -3341,13 +3341,13 @@ c  6  7
 * **All methods operate on columns by default. Pass `'axis=1'` to process the rows instead.**
 * **Fifth result's columns are indexed with a multi-index. This means we need a tuple of column keys to specify a column: `'<DF>.loc[row_key, (col_key_1, col_key_2)]'`.**
 
-#### DataFrame — Multi-Index:
+### Multi-Index
 ```python
-<DF>   = <DF>.xs(key, level=<int>)             # Rows with key on passed level of multi-index.
-<DF>   = <DF>.xs(keys, level=<ints>, axis=1)   # Cols that have first key on first level, etc.
-<DF>   = <DF>.set_index(col_keys)              # Creates index from cols. Also `append=False`.
-<S/DF> = <DF>.stack/unstack(level=-1)          # Combines col keys with row keys or vice versa.
-<DF>   = <DF>.pivot_table(index=col_key/s)     # `columns=key/s, values=key/s, aggfunc='mean'`.
+<DF> = <DF>.loc[row_key_1]                     # Or: <DF>.xs(row_key_1)
+<DF> = <DF>.loc[:, (slice(None), col_key_2)]   # Or: <DF>.xs(col_key_2, axis=1, level=1)
+<DF> = <DF>.set_index(col_keys)                # Creates index from cols. Also `append=False`.
+<DF> = <DF>.pivot_table(index=col_key/s)       # `columns=key/s, values=key/s, aggfunc='mean'`.
+<S>  = <DF>.stack/unstack(level=-1)            # Combines col keys with row keys or vice versa.
 ```
 
 ### File Formats
diff --git a/index.html b/index.html
index 4d7c1a455..b36a787ab 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>January 24, 2025</aside>
+    <aside>February 3, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -919,7 +919,7 @@
 
 <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 has those methods defined 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>.</strong></li>
-<li><strong>That means all objects compare not equal by default.</strong></li>
+<li><strong>That means all user-defined objects compare not equal by default.</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. False is returned if both return NotImplemented.</strong></li>
 <li><strong>Ne() 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>
@@ -2722,11 +2722,11 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>All methods operate on columns by default. Pass <code class="python hljs"><span class="hljs-string">'axis=1'</span></code> to process the rows instead.</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">'&lt;DF&gt;.loc[row_key, (col_key_1, col_key_2)]'</span></code>.</strong></li>
 </ul>
-<div><h4 id="dataframemultiindex">DataFrame — Multi-Index:</h4><pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt;.xs(key, level=&lt;int&gt;)             <span class="hljs-comment"># Rows with key on passed level of multi-index.</span>
-&lt;DF&gt;   = &lt;DF&gt;.xs(keys, level=&lt;ints&gt;, axis=<span class="hljs-number">1</span>)   <span class="hljs-comment"># Cols that have first key on first level, etc.</span>
-&lt;DF&gt;   = &lt;DF&gt;.set_index(col_keys)              <span class="hljs-comment"># Creates index from cols. Also `append=False`.</span>
-&lt;S/DF&gt; = &lt;DF&gt;.stack/unstack(level=<span class="hljs-number">-1</span>)          <span class="hljs-comment"># Combines col keys with row keys or vice versa.</span>
-&lt;DF&gt;   = &lt;DF&gt;.pivot_table(index=col_key/s)     <span class="hljs-comment"># `columns=key/s, values=key/s, aggfunc='mean'`.</span>
+<div><h3 id="multiindex">Multi-Index</h3><pre><code class="python language-python hljs">&lt;DF&gt; = &lt;DF&gt;.loc[row_key_1]                     <span class="hljs-comment"># Or: &lt;DF&gt;.xs(row_key_1)</span>
+&lt;DF&gt; = &lt;DF&gt;.loc[:, (slice(<span class="hljs-keyword">None</span>), col_key_2)]   <span class="hljs-comment"># Or: &lt;DF&gt;.xs(col_key_2, axis=1, level=1)</span>
+&lt;DF&gt; = &lt;DF&gt;.set_index(col_keys)                <span class="hljs-comment"># Creates index from cols. Also `append=False`.</span>
+&lt;DF&gt; = &lt;DF&gt;.pivot_table(index=col_key/s)       <span class="hljs-comment"># `columns=key/s, values=key/s, aggfunc='mean'`.</span>
+&lt;S&gt;  = &lt;DF&gt;.stack/unstack(level=<span class="hljs-number">-1</span>)            <span class="hljs-comment"># Combines col keys with row keys or vice versa.</span>
 </code></pre></div>
 
 <div><h3 id="fileformats">File Formats</h3><pre><code class="python language-python hljs">&lt;S/DF&gt; = pd.read_json/pickle(&lt;path/url/file&gt;)  <span class="hljs-comment"># Also accepts io.StringIO/BytesIO(&lt;str/bytes&gt;).</span>
@@ -2931,7 +2931,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>January 24, 2025</aside>
+    <aside>February 3, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 2b0ea864e19c91b07740eebc106d4c9a65aef068 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 4 Feb 2025 03:31:53 +0100
Subject: [PATCH 083/186] Pandas

---
 README.md  |  6 +++---
 index.html | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 1019b9aae..9a157bf4e 100644
--- a/README.md
+++ b/README.md
@@ -3352,16 +3352,16 @@ c  6  7
 
 ### File Formats
 ```python
-<S/DF> = pd.read_json/pickle(<path/url/file>)  # Also accepts io.StringIO/BytesIO(<str/bytes>).
+<S/DF> = pd.read_json/pickle(<path/url/file>)  # Also io.StringIO(<str>), io.BytesIO(<bytes>).
 <DF>   = pd.read_csv/excel(<path/url/file>)    # Also `header/index_col/dtype/usecols/…=<obj>`.
 <list> = pd.read_html(<path/url/file>)         # Raises ImportError if webpage has zero tables.
-<S/DF> = pd.read_parquet/feather/hdf(<path…>)  # Read_hdf() accepts `key='<df_name>'` argument.
+<S/DF> = pd.read_parquet/feather/hdf(<path…>)  # Read_hdf() accepts `key=<s/df_name>` argument.
 <DF>   = pd.read_sql('<table/query>', <conn>)  # Pass SQLite3/Alchemy connection (see #SQLite).
 ```
 
 ```python
 <DF>.to_json/csv/html/parquet/latex(<path>)    # Returns a string/bytes if path is omitted.
-<DF>.to_pickle/excel/feather/hdf(<path>)       # To_hdf() requires `key='<df_name>'` argument.
+<DF>.to_pickle/excel/feather/hdf(<path>)       # To_hdf() requires `key=<s/df_name>` argument.
 <DF>.to_sql('<table_name>', <connection>)      # Also `if_exists='fail/replace/append'`.
 ```
 * **`'$ pip3 install "pandas[excel]" odfpy lxml pyarrow'` installs dependencies.**
diff --git a/index.html b/index.html
index b36a787ab..160edebd8 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>February 3, 2025</aside>
+    <aside>February 4, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2729,15 +2729,15 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;S&gt;  = &lt;DF&gt;.stack/unstack(level=<span class="hljs-number">-1</span>)            <span class="hljs-comment"># Combines col keys with row keys or vice versa.</span>
 </code></pre></div>
 
-<div><h3 id="fileformats">File Formats</h3><pre><code class="python language-python hljs">&lt;S/DF&gt; = pd.read_json/pickle(&lt;path/url/file&gt;)  <span class="hljs-comment"># Also accepts io.StringIO/BytesIO(&lt;str/bytes&gt;).</span>
+<div><h3 id="fileformats">File Formats</h3><pre><code class="python language-python hljs">&lt;S/DF&gt; = pd.read_json/pickle(&lt;path/url/file&gt;)  <span class="hljs-comment"># Also io.StringIO(&lt;str&gt;), io.BytesIO(&lt;bytes&gt;).</span>
 &lt;DF&gt;   = pd.read_csv/excel(&lt;path/url/file&gt;)    <span class="hljs-comment"># Also `header/index_col/dtype/usecols/…=&lt;obj&gt;`.</span>
 &lt;list&gt; = pd.read_html(&lt;path/url/file&gt;)         <span class="hljs-comment"># Raises ImportError if webpage has zero tables.</span>
-&lt;S/DF&gt; = pd.read_parquet/feather/hdf(&lt;path…&gt;)  <span class="hljs-comment"># Read_hdf() accepts `key='&lt;df_name&gt;'` argument.</span>
+&lt;S/DF&gt; = pd.read_parquet/feather/hdf(&lt;path…&gt;)  <span class="hljs-comment"># Read_hdf() accepts `key=&lt;s/df_name&gt;` argument.</span>
 &lt;DF&gt;   = pd.read_sql(<span class="hljs-string">'&lt;table/query&gt;'</span>, &lt;conn&gt;)  <span class="hljs-comment"># Pass SQLite3/Alchemy connection (see #SQLite).</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs">&lt;DF&gt;.to_json/csv/html/parquet/latex(&lt;path&gt;)    <span class="hljs-comment"># Returns a string/bytes if path is omitted.</span>
-&lt;DF&gt;.to_pickle/excel/feather/hdf(&lt;path&gt;)       <span class="hljs-comment"># To_hdf() requires `key='&lt;df_name&gt;'` argument.</span>
+&lt;DF&gt;.to_pickle/excel/feather/hdf(&lt;path&gt;)       <span class="hljs-comment"># To_hdf() requires `key=&lt;s/df_name&gt;` argument.</span>
 &lt;DF&gt;.to_sql(<span class="hljs-string">'&lt;table_name&gt;'</span>, &lt;connection&gt;)      <span class="hljs-comment"># Also `if_exists='fail/replace/append'`.</span>
 </code></pre>
 <ul>
@@ -2931,7 +2931,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 3, 2025</aside>
+    <aside>February 4, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 1e590add2048d0a629e29ed8627399608ed70638 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 5 Feb 2025 20:34:28 +0100
Subject: [PATCH 084/186] CSV, Pandas a lot of changes

---
 README.md  | 12 ++++++------
 index.html | 16 ++++++++--------
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/README.md b/README.md
index 9a157bf4e..cffe707b0 100644
--- a/README.md
+++ b/README.md
@@ -1844,8 +1844,8 @@ import csv
 ### Parameters
 * **`'dialect'` - Master parameter that sets the default values. String or a 'csv.Dialect' object.**
 * **`'delimiter'` - A one-character string used to separate fields.**
-* **`'lineterminator'` - How writer terminates rows. Reader is hardcoded to '\n', '\r', '\r\n'.**
-* **`'quotechar'` - Character for quoting fields that contain special characters.**
+* **`'lineterminator'` - How writer terminates rows. Reader looks for '\n', '\r' and '\r\n'.**
+* **`'quotechar'` - Character for quoting fields containing delimiters, quotechars, '\n' or '\r'.**
 * **`'escapechar'` - Character for escaping quotechars.**
 * **`'doublequote'` - Whether quotechars inside fields are/get doubled or escaped.**
 * **`'quoting'` - 0: As necessary, 1: All, 2: All but numbers which are read as floats, 3: None.**
@@ -3186,14 +3186,14 @@ Name: a, dtype: int64
 
 ```python
 <S>  = <S>.head/describe/sort_values()         # Also <S>.unique/value_counts/round/dropna().
-<S>  = <S>.str.strip/lower/contains/replace()  # Also split().str[<int>] and split().explode().
+<S>  = <S>.str.strip/lower/contains/replace()  # Also split().str[i] or split(expand=True).
 <S>  = <S>.dt.year/month/day/hour              # Use pd.to_datetime(<S>) to get S of dates.
 ```
 
 ```python
 <S>.plot.line/area/bar/pie/hist()              # Generates a plot. `plt.show()` displays it.
 ```
-* **Also: `'pd.cut(<S>, bins=<int/coll>)'` and `'<S>.quantile(<float/coll>)'`.**
+* **Also `'<S>.quantile(<float/coll>)'` and `'pd.cut(<S>, bins=<int/coll>)'`.**
 * **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`.**
 * **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
 * **Series will silently overflow if we run `'pd.Series([100], dtype="int8") + 100'`!**
@@ -3255,7 +3255,7 @@ b  3  4
 ```
 
 ```python
-<DF>   = <DF> > <el/S/DF>                      # Returns DF of bools. S is treated as a row.
+<DF>   = <DF> > <el/S/DF>                      # Returns DF of bools. Treats series as a row.
 <DF>   = <DF> + <el/S/DF>                      # Items with non-matching keys get value NaN.
 ```
 
@@ -3338,7 +3338,7 @@ c  6  7
 |                 |  b  2.0  2.0  |  b  2.0  2.0  |    b  2.0     |
 +-----------------+---------------+---------------+---------------+
 ```
-* **All methods operate on columns by default. Pass `'axis=1'` to process the rows instead.**
+* **Listed methods process the columns unless they receive `'axis=1'`. Exceptions to this rule are `'<DF>.dropna()'`, `'<DF>.drop(row_key/s)'` and `'<DF>.rename(<dict/func>)'`.**
 * **Fifth result's columns are indexed with a multi-index. This means we need a tuple of column keys to specify a column: `'<DF>.loc[row_key, (col_key_1, col_key_2)]'`.**
 
 ### Multi-Index
diff --git a/index.html b/index.html
index 160edebd8..66295695b 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>February 4, 2025</aside>
+    <aside>February 5, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1529,8 +1529,8 @@
 <div><h3 id="parameters">Parameters</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 'csv.Dialect' object.</strong></li>
 <li><strong><code class="python hljs"><span class="hljs-string">'delimiter'</span></code> - A one-character string used to separate fields.</strong></li>
-<li><strong><code class="python hljs"><span class="hljs-string">'lineterminator'</span></code> - How writer terminates rows. Reader is hardcoded to '\n', '\r', '\r\n'.</strong></li>
-<li><strong><code class="python hljs"><span class="hljs-string">'quotechar'</span></code> - Character for quoting fields that contain special characters.</strong></li>
+<li><strong><code class="python hljs"><span class="hljs-string">'lineterminator'</span></code> - 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.</strong></li>
 <li><strong><code class="python hljs"><span class="hljs-string">'doublequote'</span></code> - Whether quotechars inside fields are/get doubled or 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>
@@ -2595,13 +2595,13 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;S&gt;  = &lt;S&gt; + &lt;el/S&gt;                            <span class="hljs-comment"># Items with non-matching keys get value NaN.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt;.head/describe/sort_values()         <span class="hljs-comment"># Also &lt;S&gt;.unique/value_counts/round/dropna().</span>
-&lt;S&gt;  = &lt;S&gt;.str.strip/lower/contains/replace()  <span class="hljs-comment"># Also split().str[&lt;int&gt;] and split().explode().</span>
+&lt;S&gt;  = &lt;S&gt;.str.strip/lower/contains/replace()  <span class="hljs-comment"># Also split().str[i] or split(expand=True).</span>
 &lt;S&gt;  = &lt;S&gt;.dt.year/month/day/hour              <span class="hljs-comment"># Use pd.to_datetime(&lt;S&gt;) to get S of dates.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. `plt.show()` displays it.</span>
 </code></pre>
 <ul>
-<li><strong>Also: <code class="python hljs"><span class="hljs-string">'pd.cut(&lt;S&gt;, bins=&lt;int/coll&gt;)'</span></code> and <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.quantile(&lt;float/coll&gt;)'</span></code>.</strong></li>
+<li><strong>Also <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.quantile(&lt;float/coll&gt;)'</span></code> and <code class="python hljs"><span class="hljs-string">'pd.cut(&lt;S&gt;, bins=&lt;int/coll&gt;)'</span></code>.</strong></li>
 <li><strong>Indexing objects can't be tuples 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>.</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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
 <li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
@@ -2650,7 +2650,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;DF&gt;   = &lt;DF&gt;[&lt;S_of_bools&gt;]                    <span class="hljs-comment"># Filters rows. For example `df[df.x &gt; 1]`.</span>
 &lt;DF&gt;   = &lt;DF&gt;[&lt;DF_of_bools&gt;]                   <span class="hljs-comment"># Assigns NaN to items that are False in bools.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt; &gt; &lt;el/S/DF&gt;                      <span class="hljs-comment"># Returns DF of bools. S is treated as a row.</span>
+<pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt; &gt; &lt;el/S/DF&gt;                      <span class="hljs-comment"># Returns DF of bools. Treats series as a row.</span>
 &lt;DF&gt;   = &lt;DF&gt; + &lt;el/S/DF&gt;                      <span class="hljs-comment"># Items with non-matching keys get value NaN.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;DF&gt;   = &lt;DF&gt;.set_index(col_key)               <span class="hljs-comment"># Replaces row keys with column's values.</span>
@@ -2719,7 +2719,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 
 <ul>
-<li><strong>All methods operate on columns by default. Pass <code class="python hljs"><span class="hljs-string">'axis=1'</span></code> to process the rows instead.</strong></li>
+<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">'&lt;DF&gt;.dropna()'</span></code>, <code class="python hljs"><span class="hljs-string">'&lt;DF&gt;.drop(row_key/s)'</span></code> and <code class="python hljs"><span class="hljs-string">'&lt;DF&gt;.rename(&lt;dict/func&gt;)'</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">'&lt;DF&gt;.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">&lt;DF&gt; = &lt;DF&gt;.loc[row_key_1]                     <span class="hljs-comment"># Or: &lt;DF&gt;.xs(row_key_1)</span>
@@ -2931,7 +2931,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 4, 2025</aside>
+    <aside>February 5, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 4ac35a722dc285327720b38834b8718202196264 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 6 Feb 2025 15:45:54 +0100
Subject: [PATCH 085/186] Coroutines

---
 README.md  | 26 +++++++++++++-------------
 index.html | 30 +++++++++++++++---------------
 parse.js   | 12 ++++++------
 3 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/README.md b/README.md
index cffe707b0..9aaff64c5 100644
--- a/README.md
+++ b/README.md
@@ -2327,30 +2327,30 @@ import asyncio as aio
 ```
 
 ```python
-<coro> = <async_function>(<args>)         # Creates a coroutine by calling async def function.
-<obj>  = await <coroutine>                # Starts the coroutine and returns its result.
-<task> = aio.create_task(<coroutine>)     # Schedules the coroutine for execution.
-<obj>  = await <task>                     # Returns coroutine's result. Also <task>.cancel().
+<coro> = <async_function>(<args>)          # Creates a coroutine by calling async def function.
+<obj>  = await <coroutine>                 # Starts the coroutine and returns its result.
+<task> = aio.create_task(<coroutine>)      # Schedules the coroutine for execution.
+<obj>  = await <task>                      # Returns coroutine's result. Also <task>.cancel().
 ```
 
 ```python
-<coro> = aio.gather(<coro/task>, ...)     # Schedules coros. Returns list of results on await.
-<coro> = aio.wait(<tasks>, …)             # `aio.ALL/FIRST_COMPLETED`. Returns (done, pending).
-<iter> = aio.as_completed(<coros/tasks>)  # Iterator of coros. All return next result on await.
+<coro> = aio.gather(<coro/task>, ...)      # Schedules coros. Returns list of results on await.
+<coro> = aio.wait(<tasks>, return_when=…)  # `'ALL/FIRST_COMPLETED'`. Returns (done, pending).
+<iter> = aio.as_completed(<coros/tasks>)   # Iter of coros that return next result on await.
 ```
 
 #### Runs a terminal game where you control an asterisk that must avoid numbers:
 ```python
 import asyncio, collections, curses, curses.textpad, enum, random
 
-P = collections.namedtuple('P', 'x y')    # Position
-D = enum.Enum('D', 'n e s w')             # Direction
-W, H = 15, 7                              # Width, Height
+P = collections.namedtuple('P', 'x y')     # Position
+D = enum.Enum('D', 'n e s w')              # Direction
+W, H = 15, 7                               # Width, Height
 
 def main(screen):
-    curses.curs_set(0)                    # Makes cursor invisible.
-    screen.nodelay(True)                  # Makes getch() non-blocking.
-    asyncio.run(main_coroutine(screen))   # Starts running asyncio code.
+    curses.curs_set(0)                     # Makes cursor invisible.
+    screen.nodelay(True)                   # Makes getch() non-blocking.
+    asyncio.run(main_coroutine(screen))    # Starts running asyncio code.
 
 async def main_coroutine(screen):
     moves = asyncio.Queue()
diff --git a/index.html b/index.html
index 66295695b..cb29cbd8e 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>February 5, 2025</aside>
+    <aside>February 6, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1902,25 +1902,25 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 
-<pre><code class="python language-python hljs">&lt;coro&gt; = &lt;async_function&gt;(&lt;args&gt;)         <span class="hljs-comment"># Creates a coroutine by calling async def function.</span>
-&lt;obj&gt;  = <span class="hljs-keyword">await</span> &lt;coroutine&gt;                <span class="hljs-comment"># Starts the coroutine and returns its result.</span>
-&lt;task&gt; = aio.create_task(&lt;coroutine&gt;)     <span class="hljs-comment"># Schedules the coroutine for execution.</span>
-&lt;obj&gt;  = <span class="hljs-keyword">await</span> &lt;task&gt;                     <span class="hljs-comment"># Returns coroutine's result. Also &lt;task&gt;.cancel().</span>
+<pre><code class="python language-python hljs">&lt;coro&gt; = &lt;async_function&gt;(&lt;args&gt;)          <span class="hljs-comment"># Creates a coroutine by calling async def function.</span>
+&lt;obj&gt;  = <span class="hljs-keyword">await</span> &lt;coroutine&gt;                 <span class="hljs-comment"># Starts the coroutine and returns its result.</span>
+&lt;task&gt; = aio.create_task(&lt;coroutine&gt;)      <span class="hljs-comment"># Schedules the coroutine for execution.</span>
+&lt;obj&gt;  = <span class="hljs-keyword">await</span> &lt;task&gt;                      <span class="hljs-comment"># Returns coroutine's result. Also &lt;task&gt;.cancel().</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;coro&gt; = aio.gather(&lt;coro/task&gt;, ...)     <span class="hljs-comment"># Schedules coros. Returns list of results on await.</span>
-&lt;coro&gt; = aio.wait(&lt;tasks&gt;, …)             <span class="hljs-comment"># `aio.ALL/FIRST_COMPLETED`. Returns (done, pending).</span>
-&lt;iter&gt; = aio.as_completed(&lt;coros/tasks&gt;)  <span class="hljs-comment"># Iterator of coros. All return next result on await.</span>
+<pre><code class="python language-python hljs">&lt;coro&gt; = aio.gather(&lt;coro/task&gt;, ...)      <span class="hljs-comment"># Schedules coros. Returns list of results on await.</span>
+&lt;coro&gt; = aio.wait(&lt;tasks&gt;, return_when=…)  <span class="hljs-comment"># `'ALL/FIRST_COMPLETED'`. Returns (done, pending).</span>
+&lt;iter&gt; = aio.as_completed(&lt;coros/tasks&gt;)   <span class="hljs-comment"># Iter of coros that return next result on await.</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, collections, curses, curses.textpad, enum, random
 
-P = collections.namedtuple(<span class="hljs-string">'P'</span>, <span class="hljs-string">'x y'</span>)    <span class="hljs-comment"># Position</span>
-D = enum.Enum(<span class="hljs-string">'D'</span>, <span class="hljs-string">'n e s w'</span>)             <span class="hljs-comment"># Direction</span>
-W, H = <span class="hljs-number">15</span>, <span class="hljs-number">7</span>                              <span class="hljs-comment"># Width, Height</span>
+P = collections.namedtuple(<span class="hljs-string">'P'</span>, <span class="hljs-string">'x y'</span>)     <span class="hljs-comment"># Position</span>
+D = enum.Enum(<span class="hljs-string">'D'</span>, <span class="hljs-string">'n e s w'</span>)              <span class="hljs-comment"># Direction</span>
+W, H = <span class="hljs-number">15</span>, <span class="hljs-number">7</span>                               <span class="hljs-comment"># Width, Height</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 cursor invisible.</span>
-    screen.nodelay(<span class="hljs-keyword">True</span>)                  <span class="hljs-comment"># Makes getch() non-blocking.</span>
-    asyncio.run(main_coroutine(screen))   <span class="hljs-comment"># Starts running asyncio code.</span>
+    curses.curs_set(<span class="hljs-number">0</span>)                     <span class="hljs-comment"># Makes cursor invisible.</span>
+    screen.nodelay(<span class="hljs-keyword">True</span>)                   <span class="hljs-comment"># Makes getch() non-blocking.</span>
+    asyncio.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">(screen)</span>:</span>
     moves = asyncio.Queue()
@@ -2931,7 +2931,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 5, 2025</aside>
+    <aside>February 6, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 01e4be1ac..0e7496d63 100755
--- a/parse.js
+++ b/parse.js
@@ -115,14 +115,14 @@ const MATCH_EXAMPLE =
 const COROUTINES =
   '<span class="hljs-keyword">import</span> asyncio, collections, curses, curses.textpad, enum, random\n' +
   '\n' +
-  'P = collections.namedtuple(<span class="hljs-string">\'P\'</span>, <span class="hljs-string">\'x y\'</span>)    <span class="hljs-comment"># Position</span>\n' +
-  'D = enum.Enum(<span class="hljs-string">\'D\'</span>, <span class="hljs-string">\'n e s w\'</span>)             <span class="hljs-comment"># Direction</span>\n' +
-  'W, H = <span class="hljs-number">15</span>, <span class="hljs-number">7</span>                              <span class="hljs-comment"># Width, Height</span>\n' +
+  'P = collections.namedtuple(<span class="hljs-string">\'P\'</span>, <span class="hljs-string">\'x y\'</span>)     <span class="hljs-comment"># Position</span>\n' +
+  'D = enum.Enum(<span class="hljs-string">\'D\'</span>, <span class="hljs-string">\'n e s w\'</span>)              <span class="hljs-comment"># Direction</span>\n' +
+  'W, H = <span class="hljs-number">15</span>, <span class="hljs-number">7</span>                               <span class="hljs-comment"># Width, Height</span>\n' +
   '\n' +
   '<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">(screen)</span>:</span>\n' +
-  '    curses.curs_set(<span class="hljs-number">0</span>)                    <span class="hljs-comment"># Makes cursor invisible.</span>\n' +
-  '    screen.nodelay(<span class="hljs-keyword">True</span>)                  <span class="hljs-comment"># Makes getch() non-blocking.</span>\n' +
-  '    asyncio.run(main_coroutine(screen))   <span class="hljs-comment"># Starts running asyncio code.</span>\n' +
+  '    curses.curs_set(<span class="hljs-number">0</span>)                     <span class="hljs-comment"># Makes cursor invisible.</span>\n' +
+  '    screen.nodelay(<span class="hljs-keyword">True</span>)                   <span class="hljs-comment"># Makes getch() non-blocking.</span>\n' +
+  '    asyncio.run(main_coroutine(screen))    <span class="hljs-comment"># Starts running asyncio code.</span>\n' +
   '\n' +
   '<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">(screen)</span>:</span>\n' +
   '    moves = asyncio.Queue()\n' +

From 2f7033dbca7892124928d39d83b894bed6f06758 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 7 Feb 2025 13:30:01 +0100
Subject: [PATCH 086/186] JSON, Pickle

---
 README.md  |  8 ++++----
 index.html | 12 ++++++------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index 9aaff64c5..46875af84 100644
--- a/README.md
+++ b/README.md
@@ -1782,9 +1782,9 @@ def read_json_file(filename):
 
 ### Write Collection to JSON File
 ```python
-def write_to_json_file(filename, list_or_dict):
+def write_to_json_file(filename, collection):
     with open(filename, 'w', encoding='utf-8') as file:
-        json.dump(list_or_dict, file, ensure_ascii=False, indent=2)
+        json.dump(collection, file, ensure_ascii=False, indent=2)
 ```
 
 
@@ -1798,14 +1798,14 @@ import pickle
 <object> = pickle.loads(<bytes>)    # Converts bytes object to object.
 ```
 
-### Read Object from File
+### Read Object from Pickle File
 ```python
 def read_pickle_file(filename):
     with open(filename, 'rb') as file:
         return pickle.load(file)
 ```
 
-### Write Object to File
+### Write Object to Pickle File
 ```python
 def write_to_pickle_file(filename, an_object):
     with open(filename, 'wb') as file:
diff --git a/index.html b/index.html
index cb29cbd8e..10b709e16 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>February 6, 2025</aside>
+    <aside>February 7, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1481,9 +1481,9 @@
         <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, list_or_dict)</span>:</span>
+<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, collection)</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(list_or_dict, file, ensure_ascii=<span class="hljs-keyword">False</span>, indent=<span class="hljs-number">2</span>)
+        json.dump(collection, 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><p><strong>Binary file format for storing Python objects.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> pickle
@@ -1492,12 +1492,12 @@
 </code></pre></div>
 
 
-<div><h3 id="readobjectfromfile">Read Object 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_pickle_file</span><span class="hljs-params">(filename)</span>:</span>
+<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="writeobjecttofile">Write Object 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_pickle_file</span><span class="hljs-params">(filename, an_object)</span>:</span>
+<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>
@@ -2931,7 +2931,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 6, 2025</aside>
+    <aside>February 7, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 767d5e83818066bf1da9f15b7605617a04c9d657 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 9 Feb 2025 18:21:39 +0100
Subject: [PATCH 087/186] Threading, Web App

---
 README.md  |  6 +++---
 index.html | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 46875af84..b66227ba1 100644
--- a/README.md
+++ b/README.md
@@ -2263,7 +2263,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
 ```python
 <Thread> = Thread(target=<function>)           # Use `args=<collection>` to set the arguments.
 <Thread>.start()                               # Starts the thread. Also <Thread>.is_alive().
-<Thread>.join()                                # Waits for the thread to finish.
+<Thread>.join()                                # Waits for the thread to finish executing.
 ```
 * **Use `'kwargs=<dict>'` to pass keyword arguments to the function.**
 * **Use `'daemon=True'`, or the program will not be able to exit while the thread is alive.**
@@ -2563,7 +2563,7 @@ app.run(host=None, port=None, debug=None)  # Or: $ flask --app FILE run [--ARG[=
 ```python
 @app.route('/img/<path:filename>')
 def serve_file(filename):
-    return fl.send_from_directory('dirname/', filename)
+    return fl.send_from_directory('DIRNAME/', filename)
 ```
 
 ### Dynamic Request
@@ -2574,7 +2574,7 @@ def serve_html(sport):
 ```
 * **`'fl.render_template(filename, <kwargs>)'` renders a file located in 'templates' dir.**
 * **`'fl.abort(<int>)'` returns error code and `'return fl.redirect(<url>)'` redirects.**
-* **`'fl.request.args[<str>]'` returns parameter from the query string (URL right of '?').**
+* **`'fl.request.args[<str>]'` returns parameter from query string (URL part right of '?').**
 * **`'fl.session[<str>] = <obj>'` stores session data. It requires secret key to be set at the startup with `'app.secret_key = <str>'`.**
 
 ### REST Request
diff --git a/index.html b/index.html
index 10b709e16..f3582b540 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>February 7, 2025</aside>
+    <aside>February 9, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1850,7 +1850,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <div><h3 id="thread">Thread</h3><pre><code class="python language-python hljs">&lt;Thread&gt; = Thread(target=&lt;function&gt;)           <span class="hljs-comment"># Use `args=&lt;collection&gt;` to set the arguments.</span>
 &lt;Thread&gt;.start()                               <span class="hljs-comment"># Starts the thread. Also &lt;Thread&gt;.is_alive().</span>
-&lt;Thread&gt;.join()                                <span class="hljs-comment"># Waits for the thread to finish.</span>
+&lt;Thread&gt;.join()                                <span class="hljs-comment"># Waits for the thread to finish executing.</span>
 </code></pre></div>
 
 <ul>
@@ -2096,7 +2096,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </ul>
 <div><h3 id="staticrequest">Static Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/img/&lt;path:filename&gt;')</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)
+    <span class="hljs-keyword">return</span> fl.send_from_directory(<span class="hljs-string">'DIRNAME/'</span>, filename)
 </code></pre></div>
 
 <div><h3 id="dynamicrequest">Dynamic Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/&lt;sport&gt;')</span>
@@ -2107,7 +2107,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <ul>
 <li><strong><code class="python hljs"><span class="hljs-string">'fl.render_template(filename, &lt;kwargs&gt;)'</span></code> renders a file located in 'templates' dir.</strong></li>
 <li><strong><code class="python hljs"><span class="hljs-string">'fl.abort(&lt;int&gt;)'</span></code> returns error code and <code class="python hljs"><span class="hljs-string">'return fl.redirect(&lt;url&gt;)'</span></code> redirects.</strong></li>
-<li><strong><code class="python hljs"><span class="hljs-string">'fl.request.args[&lt;str&gt;]'</span></code> returns parameter from the query string (URL right of '?').</strong></li>
+<li><strong><code class="python hljs"><span class="hljs-string">'fl.request.args[&lt;str&gt;]'</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[&lt;str&gt;] = &lt;obj&gt;'</span></code> stores session data. It requires secret key to be set at the startup with <code class="python hljs"><span class="hljs-string">'app.secret_key = &lt;str&gt;'</span></code>.</strong></li>
 </ul>
 <div><h3 id="restrequest">REST Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.post('/&lt;sport&gt;/odds')</span>
@@ -2931,7 +2931,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 7, 2025</aside>
+    <aside>February 9, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 57dc6c523fbbb71e7ce245bdb7aebb9a1a8fb2c4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 16 Feb 2025 02:54:32 +0100
Subject: [PATCH 088/186] Fixed dark theme banner

---
 index.html | 6 +++---
 parse.js   | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/index.html b/index.html
index f3582b540..c718c836a 100644
--- a/index.html
+++ b/index.html
@@ -55,7 +55,7 @@
 
 <body>
   <header>
-    <aside>February 9, 2025</aside>
+    <aside>February 16, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -67,7 +67,7 @@
     var link_to_theme = document.createElement("a")
     link_to_theme.href = "index.html"
     link_to_theme.text = "Switch to light theme"
-    document.getElementsByClassName("banner")[0].firstChild.children[4].replaceWith(link_to_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";
@@ -2931,7 +2931,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 9, 2025</aside>
+    <aside>February 16, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 0e7496d63..5e78470d3 100755
--- a/parse.js
+++ b/parse.js
@@ -742,7 +742,7 @@ const DARK_THEME_SCRIPT =
   '    var link_to_theme = document.createElement("a")\n' +
   '    link_to_theme.href = "index.html"\n' +
   '    link_to_theme.text = "Switch to light theme"\n' +
-  '    document.getElementsByClassName("banner")[0].firstChild.children[4].replaceWith(link_to_theme)\n' +
+  '    document.getElementsByClassName("banner")[0].firstChild.children[3].replaceWith(link_to_theme)\n' +
   '\n' +
   '    var img_dark = document.createElement("img");\n' +
   '    img_dark.src = "web/image_orig_blue6.png";\n' +

From 091e04f3f72f11219f901cd621c0c34a478bd0e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 16 Feb 2025 05:33:26 +0100
Subject: [PATCH 089/186] Implemented automatic dark mode

---
 index.html        | 15 ++++++++++-----
 parse.js          | 10 +++++++---
 web/template.html |  5 +++--
 3 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/index.html b/index.html
index c718c836a..8b26394e7 100644
--- a/index.html
+++ b/index.html
@@ -13,8 +13,9 @@
   <link rel="stylesheet" href="web/style.css">
 
   <script>
-    // Checks if URL ends with "index.html?dark=true"
-    if (window.location.search.search(/[?&]theme=dark3/) !== -1) {
+    // 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\">");
     }
@@ -61,11 +62,15 @@
 
    <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"></p><script>
-  // Changes the image and link to theme if URL ends with "index.html?theme=dark". 
-  if (window.location.search.search(/[?&]theme=dark/) !== -1) {
+  // 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.
+  if ( (window.location.search.search(/[?&]theme=dark/) !== -1) || ((window.location.search.search(/[?&]theme=light/) == -1) && (window.matchMedia('(prefers-color-scheme: dark)').matches)) ) {
+    activateDarkMode();
+  }
 
+  function activateDarkMode() {
     var link_to_theme = document.createElement("a")
-    link_to_theme.href = "index.html"
+    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)
 
diff --git a/parse.js b/parse.js
index 5e78470d3..faee6bc38 100755
--- a/parse.js
+++ b/parse.js
@@ -736,11 +736,15 @@ const MENU = '<a href="https://raw.githubusercontent.com/gto76/python-cheatsheet
 
 const DARK_THEME_SCRIPT =
   '<script>\n' +
-  '  // Changes the image and link to theme if URL ends with "index.html?theme=dark". \n' +
-  '  if (window.location.search.search(/[?&]theme=dark/) !== -1) {\n' +
+  '  // Changes the banner image and link-to-theme if "theme=dark" is in query string\n' +
+  '  // or if browser prefers dark mode and theme is not explicitly set.\n' +
+  '  if ( (window.location.search.search(/[?&]theme=dark/) !== -1) || ((window.location.search.search(/[?&]theme=light/) == -1) && (window.matchMedia(\'(prefers-color-scheme: dark)\').matches)) ) {\n' +
+  '    activateDarkMode();\n' +
+  '  }\n' +
   '\n' +
+  '  function activateDarkMode() {\n' +
   '    var link_to_theme = document.createElement("a")\n' +
-  '    link_to_theme.href = "index.html"\n' +
+  '    link_to_theme.href = "index.html?theme=light"\n' +
   '    link_to_theme.text = "Switch to light theme"\n' +
   '    document.getElementsByClassName("banner")[0].firstChild.children[3].replaceWith(link_to_theme)\n' +
   '\n' +
diff --git a/web/template.html b/web/template.html
index ed249d980..9b8b5fd4c 100644
--- a/web/template.html
+++ b/web/template.html
@@ -13,8 +13,9 @@
   <link rel="stylesheet" href="web/style.css">
 
   <script>
-    // Checks if URL ends with "index.html?dark=true"
-    if (window.location.search.search(/[?&]theme=dark3/) !== -1) {
+    // 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\">");
     }

From 98846e0e6602f8b86b468584137425ad32e54242 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 16 Feb 2025 07:44:02 +0100
Subject: [PATCH 090/186] Fixed dark theme banner

---
 index.html | 10 ++++++++--
 parse.js   | 10 ++++++++--
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/index.html b/index.html
index 8b26394e7..bb366d166 100644
--- a/index.html
+++ b/index.html
@@ -64,7 +64,12 @@
 </sup></p><p class="banner" style="margin-bottom: 20px; padding-bottom: 7px;"><img src="web/image_888.jpeg" alt="Monty Python"></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.
-  if ( (window.location.search.search(/[?&]theme=dark/) !== -1) || ((window.location.search.search(/[?&]theme=light/) == -1) && (window.matchMedia('(prefers-color-scheme: dark)').matches)) ) {
+
+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();
   }
 
@@ -78,7 +83,8 @@
     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)) {
+        (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;";
diff --git a/parse.js b/parse.js
index faee6bc38..f7895a055 100755
--- a/parse.js
+++ b/parse.js
@@ -738,7 +738,12 @@ const DARK_THEME_SCRIPT =
   '<script>\n' +
   '  // Changes the banner image and link-to-theme if "theme=dark" is in query string\n' +
   '  // or if browser prefers dark mode and theme is not explicitly set.\n' +
-  '  if ( (window.location.search.search(/[?&]theme=dark/) !== -1) || ((window.location.search.search(/[?&]theme=light/) == -1) && (window.matchMedia(\'(prefers-color-scheme: dark)\').matches)) ) {\n' +
+  '\n' +
+  'const theme_not_set_in_query = window.location.search.search(/[?&]theme=light/) == -1\n' +
+  'const browser_prefers_dark = window.matchMedia(\'(prefers-color-scheme: dark)\').matches;\n' +
+  '\n' +
+  '  if ((window.location.search.search(/[?&]theme=dark/) !== -1) || \n' +
+  '      (theme_not_set_in_query && browser_prefers_dark)) {\n' +
   '    activateDarkMode();\n' +
   '  }\n' +
   '\n' +
@@ -752,7 +757,8 @@ const DARK_THEME_SCRIPT =
   '    img_dark.src = "web/image_orig_blue6.png";\n' +
   '    img_dark.alt = "Monthy Python";\n' +
   '    if ((window.location.search.search(/[?&]theme=dark2/) !== -1) ||\n' +
-  '        (window.location.search.search(/[?&]theme=dark3/) !== -1)) {\n' +
+  '        (window.location.search.search(/[?&]theme=dark3/) !== -1) ||\n' +
+  '        (theme_not_set_in_query && browser_prefers_dark)) {\n' +
   '      img_dark.style = "width: 910px;";\n' +
   '    } else {\n' +
   '      img_dark.style = "width: 960px;";\n' +

From 7605ef7e12b0dac0b6403506dcbc900d74b36d1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 17 Feb 2025 23:48:52 +0100
Subject: [PATCH 091/186] Pandas, added two DT functions

---
 README.md  |  6 +++---
 index.html | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index b66227ba1..dc4745fc9 100644
--- a/README.md
+++ b/README.md
@@ -3187,7 +3187,8 @@ Name: a, dtype: int64
 ```python
 <S>  = <S>.head/describe/sort_values()         # Also <S>.unique/value_counts/round/dropna().
 <S>  = <S>.str.strip/lower/contains/replace()  # Also split().str[i] or split(expand=True).
-<S>  = <S>.dt.year/month/day/hour              # Use pd.to_datetime(<S>) to get S of dates.
+<S>  = <S>.dt.year/month/day/hour              # Use pd.to_datetime(<S>) to get S of datetimes.
+<S>  = <S>.dt.to_period('y/m/d/h')             # Quantizes datetimes into Period objects.
 ```
 
 ```python
@@ -3223,7 +3224,6 @@ Name: a, dtype: int64
 |              |    y  2.0   |   y   2.0   |      y  2.0   |
 +--------------+-------------+-------------+---------------+
 ```
-* **Agg() and transform() pass a Series to a function if it raises Type/Val/AttrError on a scalar.**
 * **Last result has a multi-index. Use `'<S>[key_1, key_2]'` to get its values.**
 
 ### DataFrame
@@ -3366,7 +3366,7 @@ c  6  7
 ```
 * **`'$ pip3 install "pandas[excel]" odfpy lxml pyarrow'` installs dependencies.**
 * **Read\_csv() only parses dates of columns that were specified by 'parse\_dates' argument. It automatically tries to detect the format, but it can be helped with 'date\_format' or 'dayfirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.**
-* **If there's a single invalid date then it returns the whole column as a series of strings, unlike `'<S> = pd.to_datetime(<S>, errors="coerce")'`, which uses pd.NaT.**
+* **If 'parse\_dates' and 'index_col' are the same column, we get a DF with DatetimeIndex. Its `'resample("y/m/d/h")'` method returns a Resampler object that is similar to GroupBy.**
 
 ### GroupBy
 **Object that groups together rows of a dataframe based on the value of the passed column.**
diff --git a/index.html b/index.html
index bb366d166..252a61b7a 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>February 16, 2025</aside>
+    <aside>February 17, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2607,7 +2607,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <pre><code class="python language-python hljs">&lt;S&gt;  = &lt;S&gt;.head/describe/sort_values()         <span class="hljs-comment"># Also &lt;S&gt;.unique/value_counts/round/dropna().</span>
 &lt;S&gt;  = &lt;S&gt;.str.strip/lower/contains/replace()  <span class="hljs-comment"># Also split().str[i] or split(expand=True).</span>
-&lt;S&gt;  = &lt;S&gt;.dt.year/month/day/hour              <span class="hljs-comment"># Use pd.to_datetime(&lt;S&gt;) to get S of dates.</span>
+&lt;S&gt;  = &lt;S&gt;.dt.year/month/day/hour              <span class="hljs-comment"># Use pd.to_datetime(&lt;S&gt;) to get S of datetimes.</span>
+&lt;S&gt;  = &lt;S&gt;.dt.to_period(<span class="hljs-string">'y/m/d/h'</span>)             <span class="hljs-comment"># Quantizes datetimes into Period objects.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. `plt.show()` displays it.</span>
 </code></pre>
@@ -2639,7 +2640,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 
 <ul>
-<li><strong>Agg() and transform() pass a Series to a function if it raises Type/Val/AttrError on a scalar.</strong></li>
 <li><strong>Last result has a multi-index. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;[key_1, key_2]'</span></code> to get its values.</strong></li>
 </ul>
 <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">&gt;&gt;&gt; </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
@@ -2754,7 +2754,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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>Read_csv() only parses dates of columns that were specified by 'parse_dates' argument. It&nbsp;automatically tries to detect the format, but it can be helped with 'date_format' or 'dayfirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.</strong></li>
-<li><strong>If there's a single invalid date then it returns the whole column as a series of strings, unlike <code class="python hljs"><span class="hljs-string">'&lt;S&gt; = pd.to_datetime(&lt;S&gt;, errors="coerce")'</span></code>, which uses pd.NaT.</strong></li>
+<li><strong>If 'parse_dates' and 'index_col' are the same column, we get a DF with DatetimeIndex. Its <code class="python hljs"><span class="hljs-string">'resample("y/m/d/h")'</span></code> method returns a 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">&lt;GB&gt; = &lt;DF&gt;.groupby(col_key/s)                 <span class="hljs-comment"># Splits DF into groups based on passed column.</span>
 &lt;DF&gt; = &lt;GB&gt;.apply/filter(&lt;func&gt;)               <span class="hljs-comment"># Filter drops a group if func returns False.</span>
@@ -2942,7 +2942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 16, 2025</aside>
+    <aside>February 17, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From c4ae1b963d4140f636c08af404a95706e1dee9a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 18 Feb 2025 18:46:41 +0100
Subject: [PATCH 092/186] Pandas

---
 README.md  | 2 +-
 index.html | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index dc4745fc9..4c441e26a 100644
--- a/README.md
+++ b/README.md
@@ -3273,7 +3273,7 @@ b  3  4
 ```
 
 ```python
-<DF>.plot.line/area/bar/scatter(x=col_key, …)  # `y=col_key/s`. Also hist/box(by=col_key).
+<DF>.plot.line/area/bar/scatter(x=col_key, …)  # `y=col_key/s`. Also hist/box(column/by=col_k).
 plt.show()                                     # Displays the plot. Also plt.savefig(<path>).
 ```
 
diff --git a/index.html b/index.html
index 252a61b7a..615f797f5 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>February 17, 2025</aside>
+    <aside>February 18, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2673,7 +2673,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;DF&gt;   = &lt;DF&gt;.describe()                       <span class="hljs-comment"># Describes columns. Also info(), corr(), shape.</span>
 &lt;DF&gt;   = &lt;DF&gt;.query(<span class="hljs-string">'&lt;query&gt;'</span>)                 <span class="hljs-comment"># Filters rows. For example `df.query('x &gt; 1')`.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;DF&gt;.plot.line/area/bar/scatter(x=col_key, …)  <span class="hljs-comment"># `y=col_key/s`. Also hist/box(by=col_key).</span>
+<pre><code class="python language-python hljs">&lt;DF&gt;.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(&lt;path&gt;).</span>
 </code></pre>
 <div><h4 id="dataframemergejoinconcat">DataFrame — Merge, Join, Concat:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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
@@ -2942,7 +2942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 17, 2025</aside>
+    <aside>February 18, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 9d321c6719f480fbb16e0249c281e8124f1bc7f2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 19 Feb 2025 18:16:25 +0100
Subject: [PATCH 093/186] Pygame, mario

---
 README.md  | 12 ++++++------
 index.html | 16 ++++++++--------
 parse.js   | 12 ++++++------
 3 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/README.md b/README.md
index 4c441e26a..879c3a06d 100644
--- a/README.md
+++ b/README.md
@@ -3096,19 +3096,19 @@ def main():
 def run(screen, images, mario, tiles):
     clock = pg.time.Clock()
     pressed = set()
-    while not pg.event.get(pg.QUIT) and clock.tick(28):
-        keys = {pg.K_UP: D.n, pg.K_RIGHT: D.e, pg.K_DOWN: D.s, pg.K_LEFT: D.w}
-        pressed |= {keys.get(e.key) for e in pg.event.get(pg.KEYDOWN)}
-        pressed -= {keys.get(e.key) for e in pg.event.get(pg.KEYUP)}
+    while not pg.event.get(pg.QUIT):
+        clock.tick(28)
+        pressed |= {e.key for e in pg.event.get(pg.KEYDOWN)}
+        pressed -= {e.key for e in pg.event.get(pg.KEYUP)}
         update_speed(mario, tiles, pressed)
         update_position(mario, tiles)
         draw(screen, images, mario, tiles)
 
 def update_speed(mario, tiles, pressed):
     x, y = mario.spd
-    x += 2 * ((D.e in pressed) - (D.w in pressed))
+    x += 2 * ((pg.K_RIGHT in pressed) - (pg.K_LEFT in pressed))
     x += (x < 0) - (x > 0)
-    y += 1 if D.s not in get_boundaries(mario.rect, tiles) else (D.n in pressed) * -10
+    y += 1 if D.s not in get_boundaries(mario.rect, tiles) else (pg.K_UP in pressed) * -10
     mario.spd = P(x=max(-MAX_S.x, min(MAX_S.x, x)), y=max(-MAX_S.y, min(MAX_S.y, y)))
 
 def update_position(mario, tiles):
diff --git a/index.html b/index.html
index 615f797f5..eaeee485f 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>February 18, 2025</aside>
+    <aside>February 19, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2533,19 +2533,19 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run</span><span class="hljs-params">(screen, 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) <span class="hljs-keyword">and</span> clock.tick(<span class="hljs-number">28</span>):
-        keys = {pg.K_UP: D.n, pg.K_RIGHT: D.e, pg.K_DOWN: D.s, pg.K_LEFT: D.w}
-        pressed |= {keys.get(e.key) <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> pg.event.get(pg.KEYDOWN)}
-        pressed -= {keys.get(e.key) <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> pg.event.get(pg.KEYUP)}
+    <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_speed(mario, tiles, pressed)
         update_position(mario, tiles)
         draw(screen, images, mario, tiles)
 
 <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_speed</span><span class="hljs-params">(mario, tiles, pressed)</span>:</span>
     x, y = mario.spd
-    x += <span class="hljs-number">2</span> * ((D.e <span class="hljs-keyword">in</span> pressed) - (D.w <span class="hljs-keyword">in</span> pressed))
+    x += <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))
     x += (x &lt; <span class="hljs-number">0</span>) - (x &gt; <span class="hljs-number">0</span>)
-    y += <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> D.s <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> get_boundaries(mario.rect, tiles) <span class="hljs-keyword">else</span> (D.n <span class="hljs-keyword">in</span> pressed) * <span class="hljs-number">-10</span>
+    y += <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> D.s <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> get_boundaries(mario.rect, tiles) <span class="hljs-keyword">else</span> (pg.K_UP <span class="hljs-keyword">in</span> pressed) * <span class="hljs-number">-10</span>
     mario.spd = P(x=max(-MAX_S.x, min(MAX_S.x, x)), y=max(-MAX_S.y, min(MAX_S.y, y)))
 
 <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>
@@ -2942,7 +2942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 18, 2025</aside>
+    <aside>February 19, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index f7895a055..ec7fa744c 100755
--- a/parse.js
+++ b/parse.js
@@ -259,19 +259,19 @@ const MARIO =
   '<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">run</span><span class="hljs-params">(screen, images, mario, tiles)</span>:</span>\n' +
   '    clock = pg.time.Clock()\n' +
   '    pressed = set()\n' +
-  '    <span class="hljs-keyword">while</span> <span class="hljs-keyword">not</span> pg.event.get(pg.QUIT) <span class="hljs-keyword">and</span> clock.tick(<span class="hljs-number">28</span>):\n' +
-  '        keys = {pg.K_UP: D.n, pg.K_RIGHT: D.e, pg.K_DOWN: D.s, pg.K_LEFT: D.w}\n' +
-  '        pressed |= {keys.get(e.key) <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> pg.event.get(pg.KEYDOWN)}\n' +
-  '        pressed -= {keys.get(e.key) <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> pg.event.get(pg.KEYUP)}\n' +
+  '    <span class="hljs-keyword">while</span> <span class="hljs-keyword">not</span> pg.event.get(pg.QUIT):\n' +
+  '        clock.tick(<span class="hljs-number">28</span>)\n' +
+  '        pressed |= {e.key <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> pg.event.get(pg.KEYDOWN)}\n' +
+  '        pressed -= {e.key <span class="hljs-keyword">for</span> e <span class="hljs-keyword">in</span> pg.event.get(pg.KEYUP)}\n' +
   '        update_speed(mario, tiles, pressed)\n' +
   '        update_position(mario, tiles)\n' +
   '        draw(screen, images, mario, tiles)\n' +
   '\n' +
   '<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">update_speed</span><span class="hljs-params">(mario, tiles, pressed)</span>:</span>\n' +
   '    x, y = mario.spd\n' +
-  '    x += <span class="hljs-number">2</span> * ((D.e <span class="hljs-keyword">in</span> pressed) - (D.w <span class="hljs-keyword">in</span> pressed))\n' +
+  '    x += <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))\n' +
   '    x += (x &lt; <span class="hljs-number">0</span>) - (x &gt; <span class="hljs-number">0</span>)\n' +
-  '    y += <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> D.s <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> get_boundaries(mario.rect, tiles) <span class="hljs-keyword">else</span> (D.n <span class="hljs-keyword">in</span> pressed) * <span class="hljs-number">-10</span>\n' +
+  '    y += <span class="hljs-number">1</span> <span class="hljs-keyword">if</span> D.s <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> get_boundaries(mario.rect, tiles) <span class="hljs-keyword">else</span> (pg.K_UP <span class="hljs-keyword">in</span> pressed) * <span class="hljs-number">-10</span>\n' +
   '    mario.spd = P(x=max(-MAX_S.x, min(MAX_S.x, x)), y=max(-MAX_S.y, min(MAX_S.y, y)))\n' +
   '\n' +
   '<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>\n' +

From 37ab0353702bd90efeae15ff1126be9c8a1b790c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 19 Feb 2025 20:54:39 +0100
Subject: [PATCH 094/186] Image, Audio, Pygame

---
 README.md  | 6 +++---
 index.html | 6 +++---
 parse.js   | 2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index 879c3a06d..d3321c771 100644
--- a/README.md
+++ b/README.md
@@ -2799,7 +2799,7 @@ from PIL import Image
 ### Modes
 * **`'L'` - Lightness (greyscale image). Each pixel is an int between 0 and 255.**
 * **`'RGB'` - Red, green, blue (true color image). Each pixel is a tuple of three ints.**
-* **`'RGBA'` - RGB with alpha. Low alpha (i.e. forth int) makes pixels more transparent.**
+* **`'RGBA'` - RGB with alpha. Low alpha (i.e. forth int) makes pixel more transparent.**
 * **`'HSV'` - Hue, saturation, value. Three ints representing color in HSV color space.**
 
 
@@ -2874,7 +2874,7 @@ import wave
 <int>   = <Wave>.getnchannels()       # Returns number of samples per frame.
 <int>   = <Wave>.getsampwidth()       # Returns number of bytes per sample.
 <tuple> = <Wave>.getparams()          # Returns namedtuple of all parameters.
-<bytes> = <Wave>.readframes(nframes)  # Returns next n frames (-1 returns all).
+<bytes> = <Wave>.readframes(nframes)  # Returns all frames if -1 is passed.
 ```
 
 ```python
@@ -2919,7 +2919,7 @@ def read_wav_file(filename):
 def write_to_wav_file(filename, samples_f, p=None, nchannels=1, sampwidth=2, framerate=44100):
     def get_bytes(a_float):
         a_float = max(-1, min(1 - 2e-16, a_float))
-        a_float += p.sampwidth == 1
+        a_float += (p.sampwidth == 1)
         a_float *= pow(2, (p.sampwidth * 8) - 1)
         return int(a_float).to_bytes(p.sampwidth, 'little', signed=(p.sampwidth != 1))
     if p is None:
diff --git a/index.html b/index.html
index eaeee485f..13d8668f2 100644
--- a/index.html
+++ b/index.html
@@ -2290,7 +2290,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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 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 ints.</strong></li>
-<li><strong><code class="python hljs"><span class="hljs-string">'RGBA'</span></code> - RGB with alpha. Low alpha (i.e. forth int) makes pixels more transparent.</strong></li>
+<li><strong><code class="python hljs"><span class="hljs-string">'RGBA'</span></code> - RGB with alpha. Low alpha (i.e. forth 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">WIDTH, HEIGHT = <span class="hljs-number">100</span>, <span class="hljs-number">100</span>
 n_pixels = WIDTH * HEIGHT
@@ -2352,7 +2352,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;int&gt;   = &lt;Wave&gt;.getnchannels()       <span class="hljs-comment"># Returns number of samples per frame.</span>
 &lt;int&gt;   = &lt;Wave&gt;.getsampwidth()       <span class="hljs-comment"># Returns number of bytes per sample.</span>
 &lt;tuple&gt; = &lt;Wave&gt;.getparams()          <span class="hljs-comment"># Returns namedtuple of all parameters.</span>
-&lt;bytes&gt; = &lt;Wave&gt;.readframes(nframes)  <span class="hljs-comment"># Returns next n frames (-1 returns all).</span>
+&lt;bytes&gt; = &lt;Wave&gt;.readframes(nframes)  <span class="hljs-comment"># Returns all frames if -1 is passed.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Wave&gt; = wave.open(<span class="hljs-string">'&lt;path&gt;'</span>, <span class="hljs-string">'wb'</span>)    <span class="hljs-comment"># Creates/truncates a file for writing.</span>
 &lt;Wave&gt;.setframerate(&lt;int&gt;)            <span class="hljs-comment"># Pass 44100 for CD, 48000 for video.</span>
@@ -2390,7 +2390,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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>, framerate=<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))
-        a_float += p.sampwidth == <span class="hljs-number">1</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>:
diff --git a/parse.js b/parse.js
index ec7fa744c..7a1a3fdd4 100755
--- a/parse.js
+++ b/parse.js
@@ -215,7 +215,7 @@ const AUDIO_1 =
   '<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>, framerate=<span class="hljs-number">44100</span>)</span>:</span>\n' +
   '    <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>\n' +
   '        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))\n' +
-  '        a_float += p.sampwidth == <span class="hljs-number">1</span>\n' +
+  '        a_float += (p.sampwidth == <span class="hljs-number">1</span>)\n' +
   '        a_float *= pow(<span class="hljs-number">2</span>, (p.sampwidth * <span class="hljs-number">8</span>) - <span class="hljs-number">1</span>)\n' +
   '        <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>))\n' +
   '    <span class="hljs-keyword">if</span> p <span class="hljs-keyword">is</span> <span class="hljs-keyword">None</span>:\n' +

From c83653117623c2ba9e0270fb9fdca9babb17d06c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 25 Feb 2025 19:52:24 +0100
Subject: [PATCH 095/186] Plot, Console app

---
 README.md  | 12 ++++++------
 index.html | 16 ++++++++--------
 parse.js   |  9 +++++----
 3 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/README.md b/README.md
index d3321c771..34a553e6f 100644
--- a/README.md
+++ b/README.md
@@ -2419,8 +2419,7 @@ import matplotlib.pyplot as plt
 plt.plot/bar/scatter(x_data, y_data [, label=<str>])  # Also plt.plot(y_data).
 plt.legend()                                          # Adds a legend.
 plt.title/xlabel/ylabel(<str>)                        # Adds a title or label.
-plt.savefig(<path>)                                   # Saves the plot.
-plt.show()                                            # Displays the plot.
+plt.show()                                            # Also plt.savefig(<path>).
 plt.clf()                                             # Clears the plot.
 ```
 
@@ -2443,7 +2442,7 @@ Console App
 ```python
 # $ pip3 install windows-curses
 import curses, os
-from curses import A_REVERSE, KEY_DOWN, KEY_UP, KEY_LEFT, KEY_RIGHT, KEY_ENTER
+from curses import A_REVERSE, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER
 
 def main(screen):
     ch, first, selected, paths = 0, 0, 0, os.listdir()
@@ -2454,9 +2453,10 @@ def main(screen):
             color = A_REVERSE if filename == paths[selected] else 0
             screen.addnstr(y, 0, filename, width-1, color)
         ch = screen.getch()
-        selected += (ch == KEY_DOWN) - (ch == KEY_UP)
-        selected = max(0, min(len(paths)-1, selected))
-        first += (selected >= first + height) - (selected < first)
+        selected -= (ch == KEY_UP) and (selected > 0)
+        selected += (ch == KEY_DOWN) and (selected < len(paths)-1)
+        first = min(first, selected)
+        first = max(first, selected - (height-1))
         if ch in [KEY_LEFT, KEY_RIGHT, KEY_ENTER, ord('\n'), ord('\r')]:
             new_dir = '..' if ch == KEY_LEFT else paths[selected]
             if os.path.isdir(new_dir):
diff --git a/index.html b/index.html
index 13d8668f2..8757f5e3f 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>February 19, 2025</aside>
+    <aside>February 25, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1990,8 +1990,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 plt.plot/bar/scatter(x_data, y_data [, label=&lt;str&gt;])  <span class="hljs-comment"># Also plt.plot(y_data).</span>
 plt.legend()                                          <span class="hljs-comment"># Adds a legend.</span>
 plt.title/xlabel/ylabel(&lt;str&gt;)                        <span class="hljs-comment"># Adds a title or label.</span>
-plt.savefig(&lt;path&gt;)                                   <span class="hljs-comment"># Saves the plot.</span>
-plt.show()                                            <span class="hljs-comment"># Displays the plot.</span>
+plt.show()                                            <span class="hljs-comment"># Also plt.savefig(&lt;path&gt;).</span>
 plt.clf()                                             <span class="hljs-comment"># Clears the plot.</span>
 </code></pre></div>
 
@@ -2005,7 +2004,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <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_DOWN, KEY_UP, KEY_LEFT, KEY_RIGHT, KEY_ENTER
+<span class="hljs-keyword">from</span> curses <span class="hljs-keyword">import</span> A_REVERSE, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER
 
 <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()
@@ -2016,9 +2015,10 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
             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_DOWN) - (ch == KEY_UP)
-        selected = max(<span class="hljs-number">0</span>, min(len(paths)-<span class="hljs-number">1</span>, selected))
-        first += (selected &gt;= first + height) - (selected &lt; first)
+        selected -= (ch == KEY_UP) <span class="hljs-keyword">and</span> (selected &gt; <span class="hljs-number">0</span>)
+        selected += (ch == KEY_DOWN) <span class="hljs-keyword">and</span> (selected &lt; len(paths)-<span class="hljs-number">1</span>)
+        first = min(first, selected)
+        first = max(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, KEY_ENTER, ord(<span class="hljs-string">'\n'</span>), ord(<span class="hljs-string">'\r'</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):
@@ -2942,7 +2942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 19, 2025</aside>
+    <aside>February 25, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 7a1a3fdd4..1c660edec 100755
--- a/parse.js
+++ b/parse.js
@@ -168,7 +168,7 @@ const COROUTINES =
 const CURSES =
   '<span class="hljs-comment"># $ pip3 install windows-curses</span>\n' +
   '<span class="hljs-keyword">import</span> curses, os\n' +
-  '<span class="hljs-keyword">from</span> curses <span class="hljs-keyword">import</span> A_REVERSE, KEY_DOWN, KEY_UP, KEY_LEFT, KEY_RIGHT, KEY_ENTER\n' +
+  '<span class="hljs-keyword">from</span> curses <span class="hljs-keyword">import</span> A_REVERSE, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER\n' +
   '\n' +
   '<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">(screen)</span>:</span>\n' +
   '    ch, first, selected, paths = <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, os.listdir()\n' +
@@ -179,9 +179,10 @@ const CURSES =
   '            color = A_REVERSE <span class="hljs-keyword">if</span> filename == paths[selected] <span class="hljs-keyword">else</span> <span class="hljs-number">0</span>\n' +
   '            screen.addnstr(y, <span class="hljs-number">0</span>, filename, width-<span class="hljs-number">1</span>, color)\n' +
   '        ch = screen.getch()\n' +
-  '        selected += (ch == KEY_DOWN) - (ch == KEY_UP)\n' +
-  '        selected = max(<span class="hljs-number">0</span>, min(len(paths)-<span class="hljs-number">1</span>, selected))\n' +
-  '        first += (selected &gt;= first + height) - (selected &lt; first)\n' +
+  '        selected -= (ch == KEY_UP) <span class="hljs-keyword">and</span> (selected &gt; <span class="hljs-number">0</span>)\n' +
+  '        selected += (ch == KEY_DOWN) <span class="hljs-keyword">and</span> (selected &lt; len(paths)-<span class="hljs-number">1</span>)\n' +
+  '        first = min(first, selected)\n' +
+  '        first = max(first, selected - (height-<span class="hljs-number">1</span>))\n' +
   '        <span class="hljs-keyword">if</span> ch <span class="hljs-keyword">in</span> [KEY_LEFT, KEY_RIGHT, KEY_ENTER, ord(<span class="hljs-string">\'\\n\'</span>), ord(<span class="hljs-string">\'\\r\'</span>)]:\n' +
   '            new_dir = <span class="hljs-string">\'..\'</span> <span class="hljs-keyword">if</span> ch == KEY_LEFT <span class="hljs-keyword">else</span> paths[selected]\n' +
   '            <span class="hljs-keyword">if</span> os.path.isdir(new_dir):\n' +

From bc5fd5a2278ecc4730356b27d137bda9029664fe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 27 Feb 2025 03:24:21 +0100
Subject: [PATCH 096/186] Decorator

---
 README.md  | 2 +-
 index.html | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 34a553e6f..5e21337a0 100644
--- a/README.md
+++ b/README.md
@@ -932,7 +932,7 @@ from functools import cache
 def fib(n):
     return n if n < 2 else fib(n-2) + fib(n-1)
 ```
-* **Potential problem with cache is that it can grow indefinitely. To clear stored values run `'fib.cache_clear()'`, or use `'@lru_cache(maxsize=<int>)'` decorator instead.**
+* **Potential problem with cache is that it can grow indefinitely. To clear stored values run `'<func>.cache_clear()'`, or use `'@lru_cache(maxsize=<int>)'` decorator instead.**
 * **CPython interpreter limits recursion depth to 3000 by default. To increase it run `'sys.setrecursionlimit(<int>)'`.**
 
 ### Parametrized Decorator
diff --git a/index.html b/index.html
index 8757f5e3f..485825763 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>February 25, 2025</aside>
+    <aside>February 27, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -789,7 +789,7 @@
 
 
 <ul>
-<li><strong>Potential problem with cache is that it can grow indefinitely. To clear stored values run <code class="python hljs"><span class="hljs-string">'fib.cache_clear()'</span></code>, or use <code class="python hljs"><span class="hljs-string">'@lru_cache(maxsize=&lt;int&gt;)'</span></code> decorator instead.</strong></li>
+<li><strong>Potential problem with cache is that it can grow indefinitely. To clear stored values run <code class="python hljs"><span class="hljs-string">'&lt;func&gt;.cache_clear()'</span></code>, or use <code class="python hljs"><span class="hljs-string">'@lru_cache(maxsize=&lt;int&gt;)'</span></code> decorator instead.</strong></li>
 <li><strong>CPython interpreter limits recursion depth to 3000 by default. To increase it run <code class="python hljs"><span class="hljs-string">'sys.setrecursionlimit(&lt;int&gt;)'</span></code>.</strong></li>
 </ul>
 <div><h3 id="parametrizeddecorator">Parametrized Decorator</h3><p><strong>A decorator that accepts arguments and returns a normal decorator that accepts a function.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps
@@ -2942,7 +2942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 25, 2025</aside>
+    <aside>February 27, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From bbabc0c53cb2f6a075b135aafc0f074f95edb4db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 27 Feb 2025 08:19:46 +0100
Subject: [PATCH 097/186] Datetime, Pygame

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 5e21337a0..e7cfac7b2 100644
--- a/README.md
+++ b/README.md
@@ -667,7 +667,7 @@ import zoneinfo, dateutil.tz
 <TD>     = <DTa>     - <DTa>                # Ignores jumps if they share tzinfo object.
 <D/DT>   = <D/DT>    ± <TD>                 # Returned datetime can fall into missing hour.
 <TD>     = <TD>      * <float>              # Also `<TD> = abs(<TD>)`, `<TD> = <TD> ± <TD>`.
-<float>  = <TD>      / <TD>                 # Also `<int>, <TD> = divmod(<TD>, <TD>)`.
+<float>  = <TD>      / <TD>                 # Also `(<int>, <TD>) = divmod(<TD>, <TD>)`.
 ```
 
 
@@ -3062,7 +3062,7 @@ rect(<Surf>, color, <Rect>, width=0)            # Also polygon(<Surf>, color, po
 ### Sound
 ```python
 <Sound> = pg.mixer.Sound(<path/file/bytes>)     # WAV file or bytes/array of signed shorts.
-<Sound>.play/stop()                             # Also set_volume(<float>), fadeout(msec).
+<Sound>.play/stop()                             # Also set_volume(<float>) and fadeout(msec).
 ```
 
 ### Basic Mario Brothers Example
diff --git a/index.html b/index.html
index 485825763..50615d1e1 100644
--- a/index.html
+++ b/index.html
@@ -595,7 +595,7 @@
 &lt;TD&gt;     = &lt;DTa&gt;     - &lt;DTa&gt;                <span class="hljs-comment"># Ignores jumps if they share tzinfo object.</span>
 &lt;D/DT&gt;   = &lt;D/DT&gt;    ± &lt;TD&gt;                 <span class="hljs-comment"># Returned datetime can fall into missing hour.</span>
 &lt;TD&gt;     = &lt;TD&gt;      * &lt;float&gt;              <span class="hljs-comment"># Also `&lt;TD&gt; = abs(&lt;TD&gt;)`, `&lt;TD&gt; = &lt;TD&gt; ± &lt;TD&gt;`.</span>
-&lt;float&gt;  = &lt;TD&gt;      / &lt;TD&gt;                 <span class="hljs-comment"># Also `&lt;int&gt;, &lt;TD&gt; = divmod(&lt;TD&gt;, &lt;TD&gt;)`.</span>
+&lt;float&gt;  = &lt;TD&gt;      / &lt;TD&gt;                 <span class="hljs-comment"># Also `(&lt;int&gt;, &lt;TD&gt;) = divmod(&lt;TD&gt;, &lt;TD&gt;)`.</span>
 </code></pre></div>
 
 <div><h2 id="arguments"><a href="#arguments" name="arguments">#</a>Arguments</h2><div><h3 id="insidefunctioncall">Inside Function Call</h3><pre><code class="python language-python hljs">func(&lt;positional_args&gt;)                           <span class="hljs-comment"># func(0, 0)</span>
@@ -2501,7 +2501,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;Surf&gt; = &lt;Font&gt;.render(text, antialias, color)  <span class="hljs-comment"># Background color can be specified at the end.</span>
 </code></pre>
 <div><h3 id="sound">Sound</h3><pre><code class="python language-python hljs">&lt;Sound&gt; = pg.mixer.Sound(&lt;path/file/bytes&gt;)     <span class="hljs-comment"># WAV file or bytes/array of signed shorts.</span>
-&lt;Sound&gt;.play/stop()                             <span class="hljs-comment"># Also set_volume(&lt;float&gt;), fadeout(msec).</span>
+&lt;Sound&gt;.play/stop()                             <span class="hljs-comment"># Also set_volume(&lt;float&gt;) and fadeout(msec).</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> collections, dataclasses, enum, io, itertools <span class="hljs-keyword">as</span> it, pygame <span class="hljs-keyword">as</span> pg, urllib.request

From fa8a4c60e866e18660af72bd167e6c23ee2ca182 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 27 Feb 2025 08:23:37 +0100
Subject: [PATCH 098/186] Paths

---
 README.md  | 8 ++++----
 index.html | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index e7cfac7b2..15b63a81d 100644
--- a/README.md
+++ b/README.md
@@ -1685,15 +1685,15 @@ from pathlib import Path
 <Path> = Path()                     # Returns relative CWD. Also Path('.').
 <Path> = Path.cwd()                 # Returns absolute CWD. Also Path().resolve().
 <Path> = Path.home()                # Returns user's home directory (absolute).
-<Path> = Path(__file__).resolve()   # Returns script's path if CWD wasn't changed.
+<Path> = Path(__file__).resolve()   # Returns module's path if CWD wasn't changed.
 ```
 
 ```python
 <Path> = <Path>.parent              # Returns Path without the final component.
 <str>  = <Path>.name                # Returns final component as a string.
-<str>  = <Path>.stem                # Returns final component without extension.
-<str>  = <Path>.suffix              # Returns final component's extension.
-<tup.> = <Path>.parts               # Returns all components as strings.
+<str>  = <Path>.stem                # Returns final component w/o last extension.
+<str>  = <Path>.suffix              # Returns last extension prepended with a dot.
+<tup.> = <Path>.parts               # Returns all path's components as strings.
 ```
 
 ```python
diff --git a/index.html b/index.html
index 50615d1e1..85c60f097 100644
--- a/index.html
+++ b/index.html
@@ -1427,13 +1427,13 @@
 <pre><code class="python language-python hljs">&lt;Path&gt; = Path()                     <span class="hljs-comment"># Returns relative CWD. Also Path('.').</span>
 &lt;Path&gt; = Path.cwd()                 <span class="hljs-comment"># Returns absolute CWD. Also Path().resolve().</span>
 &lt;Path&gt; = Path.home()                <span class="hljs-comment"># Returns user's home directory (absolute).</span>
-&lt;Path&gt; = Path(__file__).resolve()   <span class="hljs-comment"># Returns script's path if CWD wasn't changed.</span>
+&lt;Path&gt; = Path(__file__).resolve()   <span class="hljs-comment"># Returns module's path if CWD wasn't changed.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Path&gt; = &lt;Path&gt;.parent              <span class="hljs-comment"># Returns Path without the final component.</span>
 &lt;str&gt;  = &lt;Path&gt;.name                <span class="hljs-comment"># Returns final component as a string.</span>
-&lt;str&gt;  = &lt;Path&gt;.stem                <span class="hljs-comment"># Returns final component without extension.</span>
-&lt;str&gt;  = &lt;Path&gt;.suffix              <span class="hljs-comment"># Returns final component's extension.</span>
-&lt;tup.&gt; = &lt;Path&gt;.parts               <span class="hljs-comment"># Returns all components as strings.</span>
+&lt;str&gt;  = &lt;Path&gt;.stem                <span class="hljs-comment"># Returns final component w/o last extension.</span>
+&lt;str&gt;  = &lt;Path&gt;.suffix              <span class="hljs-comment"># Returns last extension prepended with a dot.</span>
+&lt;tup.&gt; = &lt;Path&gt;.parts               <span class="hljs-comment"># Returns all path's components as strings.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;iter&gt; = &lt;Path&gt;.iterdir()           <span class="hljs-comment"># Returns directory contents as Path objects.</span>
 &lt;iter&gt; = &lt;Path&gt;.glob(<span class="hljs-string">'&lt;pattern&gt;'</span>)   <span class="hljs-comment"># Returns Paths matching the wildcard pattern.</span>

From 8447a11ca02ca649091969bbadff88ae2b02b0c8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 28 Feb 2025 23:58:49 +0100
Subject: [PATCH 099/186] Web, Virtual environments

---
 README.md           | 4 ++--
 index.html          | 8 ++++----
 pdf/remove_links.py | 2 +-
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md
index 15b63a81d..e646a6c15 100644
--- a/README.md
+++ b/README.md
@@ -2563,7 +2563,7 @@ app.run(host=None, port=None, debug=None)  # Or: $ flask --app FILE run [--ARG[=
 ```python
 @app.route('/img/<path:filename>')
 def serve_file(filename):
-    return fl.send_from_directory('DIRNAME/', filename)
+    return fl.send_from_directory('DIRNAME', filename)
 ```
 
 ### Dynamic Request
@@ -3549,7 +3549,7 @@ cdef class <class_name>:
 
 ```perl
 $ python3 -m venv NAME      # Creates virtual environment in current directory.
-$ source NAME/bin/activate  # Activates env. On Windows run `NAME\Scripts\activate`.
+$ source NAME/bin/activate  # Activates it. On Windows run `NAME\Scripts\activate`.
 $ pip3 install LIBRARY      # Installs the library into active environment.
 $ python3 FILE              # Runs the script in active environment. Also `./FILE`.
 $ deactivate                # Deactivates the active virtual environment.
diff --git a/index.html b/index.html
index 85c60f097..75c7b34cc 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>February 27, 2025</aside>
+    <aside>February 28, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2107,7 +2107,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </ul>
 <div><h3 id="staticrequest">Static Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/img/&lt;path:filename&gt;')</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)
+    <span class="hljs-keyword">return</span> fl.send_from_directory(<span class="hljs-string">'DIRNAME'</span>, filename)
 </code></pre></div>
 
 <div><h3 id="dynamicrequest">Dynamic Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/&lt;sport&gt;')</span>
@@ -2898,7 +2898,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
         self.&lt;attr_name&gt; = &lt;arg_name&gt;
 </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 current directory.</span>
-$ source NAME/bin/activate  <span class="hljs-comment"># Activates env. On Windows run `NAME\Scripts\activate`.</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 environment.</span>
 $ python3 FILE              <span class="hljs-comment"># Runs the script in active environment. Also `./FILE`.</span>
 $ deactivate                <span class="hljs-comment"># Deactivates the active virtual environment.</span>
@@ -2942,7 +2942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 27, 2025</aside>
+    <aside>February 28, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index df3153140..891cb6bcb 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -8,7 +8,7 @@
 
 MATCHES = {
     '<strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">Sortable</a>.</strong>': '<strong>For details about sort(), sorted(), min() and max() see Sortable (p. 16).</strong>',
-    '<strong>Module <a href="#operator">operator</a> has function itemgetter() that can replace listed <a href="#lambda">lambdas</a>.</strong>': '<strong>Module \'operator\' (p. 31) has function itemgetter() that can replace listed lambdas (p. 11).</strong>',
+    '<strong>Module <a href="#operator">operator</a> has function itemgetter() that can replace listed <a href="#lambda">lambdas</a>.</strong>': '<strong>Module \'operator\' has function itemgetter() that can replace listed lambdas (p. 31).</strong>',
     '<strong>This text uses the term collection instead of iterable. For rationale see <a href="#collection">Collection</a>.</strong>': '<strong>This text uses the term collection instead of iterable. For rationale see Collection (p. 18).</strong>',
     '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its <a href="#class">repr()</a> method.</strong>': '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its repr() method.</strong>',
     '<strong>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>': '<strong>It can be any callable, but is usually implemented as a function that returns a closure.</strong>',

From c62e8a8a898f1229f6b93a52ede6b28e9d41c959 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 2 Mar 2025 05:23:19 +0100
Subject: [PATCH 100/186] Image, Plotly, Cython

---
 README.md  | 14 +++++++-------
 index.html | 18 +++++++++---------
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/README.md b/README.md
index e646a6c15..8614d7bf0 100644
--- a/README.md
+++ b/README.md
@@ -2828,11 +2828,11 @@ img.show()
 from PIL import ImageDraw
 <Draw> = ImageDraw.Draw(<Image>)                # Object for adding 2D graphics to the image.
 <Draw>.point((x, y))                            # Draws a point. Truncates floats into ints.
-<Draw>.line((x1, y1, x2, y2 [, ...]))           # To get anti-aliasing use Image's resize().
+<Draw>.line((x1, y1, x2, y2 [, ...]))           # For anti-aliasing use <Image>.resize((w, h)).
 <Draw>.arc((x1, y1, x2, y2), deg1, deg2)        # Draws in clockwise dir. Also pieslice().
 <Draw>.rectangle((x1, y1, x2, y2))              # Also rounded_rectangle(), regular_polygon().
-<Draw>.polygon((x1, y1, x2, y2, ...))           # Last point gets connected to the first.
-<Draw>.ellipse((x1, y1, x2, y2))                # To rotate use Image's rotate() and paste().
+<Draw>.polygon((x1, y1, x2, y2, ...))           # Last point gets connected to the first one.
+<Draw>.ellipse((x1, y1, x2, y2))                # To rotate use <Image>.rotate(anticlock_deg).
 <Draw>.text((x, y), <str>, font=<Font>)         # `<Font> = ImageFont.truetype(<path>, size)`.
 ```
 * **Use `'fill=<color>'` to set the primary color.**
@@ -3457,7 +3457,7 @@ px.line(df, x='Date', y='Total Deaths per Million', color='Continent').show()
 
 ```python
 # $ pip3 install pandas lxml selenium plotly
-import pandas as pd, selenium.webdriver, plotly.graph_objects as go
+import pandas as pd, selenium.webdriver, io, plotly.graph_objects as go
 
 def main():
     covid, (bitcoin, gold, dow) = get_covid_cases(), get_tickers()
@@ -3466,7 +3466,7 @@ def main():
 
 def get_covid_cases():
     url = 'https://covid.ourworldindata.org/data/owid-covid-data.csv'
-    df = pd.read_csv(url, usecols=['location', 'date', 'total_cases'], parse_dates=['date'])
+    df = pd.read_csv(url, parse_dates=['date'])
     df = df[df.location == 'World']
     s = df.set_index('date').total_cases
     return s.rename('Total Cases')
@@ -3482,7 +3482,7 @@ def get_ticker(driver, name, symbol):
     driver.get(url + '?period1=1579651200&period2=9999999999')
     if buttons := driver.find_elements('xpath', '//button[@name="reject"]'):
         buttons[0].click()
-    dataframes = pd.read_html(driver.page_source, parse_dates=['Date'])
+    dataframes = pd.read_html(io.StringIO(driver.page_source), parse_dates=['Date'])
     s = dataframes[0].set_index('Date').Open
     return s.rename(name)
 
@@ -3529,7 +3529,7 @@ import <cython_script>                 # Script must be saved with '.pyx' extens
 
 #### Definitions:
 * **All `'cdef'` definitions are optional, but they contribute to the speed-up.**
-* **Also supports C pointers via `'*'` and `'&'`, structs, unions, and enums.**
+* **Also supports C pointers (via `'*'` and `'&'`), structs, unions and enums.**
 
 ```python
 cdef <ctype/type> <var_name> [= <obj>]
diff --git a/index.html b/index.html
index 75c7b34cc..3dac48a4b 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>February 28, 2025</aside>
+    <aside>March 2, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2313,11 +2313,11 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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
 &lt;Draw&gt; = ImageDraw.Draw(&lt;Image&gt;)                <span class="hljs-comment"># Object for adding 2D graphics to the image.</span>
 &lt;Draw&gt;.point((x, y))                            <span class="hljs-comment"># Draws a point. Truncates floats into ints.</span>
-&lt;Draw&gt;.line((x1, y1, x2, y2 [, ...]))           <span class="hljs-comment"># To get anti-aliasing use Image's resize().</span>
+&lt;Draw&gt;.line((x1, y1, x2, y2 [, ...]))           <span class="hljs-comment"># For anti-aliasing use &lt;Image&gt;.resize((w, h)).</span>
 &lt;Draw&gt;.arc((x1, y1, x2, y2), deg1, deg2)        <span class="hljs-comment"># Draws in clockwise dir. Also pieslice().</span>
 &lt;Draw&gt;.rectangle((x1, y1, x2, y2))              <span class="hljs-comment"># Also rounded_rectangle(), regular_polygon().</span>
-&lt;Draw&gt;.polygon((x1, y1, x2, y2, ...))           <span class="hljs-comment"># Last point gets connected to the first.</span>
-&lt;Draw&gt;.ellipse((x1, y1, x2, y2))                <span class="hljs-comment"># To rotate use Image's rotate() and paste().</span>
+&lt;Draw&gt;.polygon((x1, y1, x2, y2, ...))           <span class="hljs-comment"># Last point gets connected to the first one.</span>
+&lt;Draw&gt;.ellipse((x1, y1, x2, y2))                <span class="hljs-comment"># To rotate use &lt;Image&gt;.rotate(anticlock_deg).</span>
 &lt;Draw&gt;.text((x, y), &lt;str&gt;, font=&lt;Font&gt;)         <span class="hljs-comment"># `&lt;Font&gt; = ImageFont.truetype(&lt;path&gt;, size)`.</span>
 </code></pre></div>
 
@@ -2816,7 +2816,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 <div><h4 id="displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">Displays a multi-axis line chart of total coronavirus 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:287px; 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, plotly.graph_objects <span class="hljs-keyword">as</span> go
+<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()
@@ -2825,7 +2825,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <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://covid.ourworldindata.org/data/owid-covid-data.csv'</span>
-    df = pd.read_csv(url, usecols=[<span class="hljs-string">'location'</span>, <span class="hljs-string">'date'</span>, <span class="hljs-string">'total_cases'</span>], parse_dates=[<span class="hljs-string">'date'</span>])
+    df = pd.read_csv(url, parse_dates=[<span class="hljs-string">'date'</span>])
     df = df[df.location == <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>)
@@ -2841,7 +2841,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     driver.get(url + <span class="hljs-string">'?period1=1579651200&amp;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()
-    dataframes = pd.read_html(driver.page_source, parse_dates=[<span class="hljs-string">'Date'</span>])
+    dataframes = pd.read_html(io.StringIO(driver.page_source), 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)
 
@@ -2885,7 +2885,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <div><h4 id="definitions">Definitions:</h4><ul>
 <li><strong>All <code class="python hljs"><span class="hljs-string">'cdef'</span></code> definitions are optional, but they contribute to the speed-up.</strong></li>
-<li><strong>Also supports C pointers via <code class="python hljs"><span class="hljs-string">'*'</span></code> and <code class="python hljs"><span class="hljs-string">'&amp;'</span></code>, structs, unions, and enums.</strong></li>
+<li><strong>Also supports C pointers (via <code class="python hljs"><span class="hljs-string">'*'</span></code> and <code class="python hljs"><span class="hljs-string">'&amp;'</span></code>), structs, unions and enums.</strong></li>
 </ul><pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; &lt;var_name&gt; [= &lt;obj&gt;]
 <span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;coll_of_nums&gt;]
 <span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; &lt;arg_name&gt;): ...
@@ -2942,7 +2942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>February 28, 2025</aside>
+    <aside>March 2, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From ae8c00201188d9c38678415ec1b5447fc405bd8d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 3 Mar 2025 01:45:02 +0100
Subject: [PATCH 101/186] Audio

---
 README.md  | 4 ++--
 index.html | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 8614d7bf0..a43e495c1 100644
--- a/README.md
+++ b/README.md
@@ -2078,7 +2078,7 @@ Memory View
 ```
 
 ```python
-<list>  = list(<mview>)                        # Returns a list of ints, floats, or bytes.
+<list>  = list(<mview>)                        # Returns a list of ints, floats or bytes.
 <str>   = str(<mview>, 'utf-8')                # Treats memoryview as a bytes object.
 <str>   = <mview>.hex()                        # Returns hex pairs. Accepts `sep=<str>`.
 ```
@@ -2942,7 +2942,7 @@ write_to_wav_file('test.wav', samples_f)
 from random import uniform
 samples_f, params = read_wav_file('test.wav')
 samples_f = (f + uniform(-0.05, 0.05) for f in samples_f)
-write_to_wav_file('test.wav', samples_f, params)
+write_to_wav_file('test.wav', samples_f, p=params)
 ```
 
 #### Plays the WAV file:
diff --git a/index.html b/index.html
index 3dac48a4b..ea6618c4c 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 2, 2025</aside>
+    <aside>March 3, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1721,7 +1721,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;mview&gt;)         <span class="hljs-comment"># Treats memoryview as a sequence of numbers.</span>
 &lt;file&gt;.write(&lt;mview&gt;)                          <span class="hljs-comment"># Writes `bytes(&lt;mview&gt;)` to the binary file.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;list&gt;  = list(&lt;mview&gt;)                        <span class="hljs-comment"># Returns a list of ints, floats, or bytes.</span>
+<pre><code class="python language-python hljs">&lt;list&gt;  = list(&lt;mview&gt;)                        <span class="hljs-comment"># Returns a list of ints, floats or bytes.</span>
 &lt;str&gt;   = str(&lt;mview&gt;, <span class="hljs-string">'utf-8'</span>)                <span class="hljs-comment"># Treats memoryview as a bytes object.</span>
 &lt;str&gt;   = &lt;mview&gt;.hex()                        <span class="hljs-comment"># Returns hex pairs. Accepts `sep=&lt;str&gt;`.</span>
 </code></pre>
@@ -2409,7 +2409,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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, params = read_wav_file(<span class="hljs-string">'test.wav'</span>)
 samples_f = (f + uniform(<span class="hljs-number">-0.05</span>, <span class="hljs-number">0.05</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, params)
+write_to_wav_file(<span class="hljs-string">'test.wav'</span>, samples_f, p=params)
 </code></pre></div>
 
 <div><h4 id="playsthewavfile">Plays the WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install simpleaudio</span>
@@ -2942,7 +2942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 2, 2025</aside>
+    <aside>March 3, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 2fcfaa039b56fd967bf28fcf0e033a1af4dc6bd9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 3 Mar 2025 06:05:45 +0100
Subject: [PATCH 102/186] Pandas

---
 README.md  | 10 +++++-----
 index.html | 10 +++++-----
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index a43e495c1..35b6f3572 100644
--- a/README.md
+++ b/README.md
@@ -3201,7 +3201,7 @@ Name: a, dtype: int64
 
 #### Series — Aggregate, Transform, Map:
 ```python
-<el> = <S>.sum/max/mean/idxmax/all/count()     # Or: <S>.agg(lambda <S>: <el>)
+<el> = <S>.sum/max/mean/std/idxmax/count()     # Or: <S>.agg(lambda <S>: <el>)
 <S>  = <S>.rank/diff/cumsum/ffill/interpol…()  # Or: <S>.agg/transform(lambda <S>: <S>)
 <S>  = <S>.isna/fillna/isin([<el/coll>])       # Or: <S>.agg/transform/map(lambda <el>: <el>)
 ```
@@ -3314,7 +3314,7 @@ c  6  7
 
 #### DataFrame — Aggregate, Transform, Map:
 ```python
-<S>  = <DF>.sum/max/mean/idxmax/all/count()    # Or: <DF>.apply/agg(lambda <S>: <el>)
+<S>  = <DF>.sum/max/mean/std/idxmax/count()    # Or: <DF>.apply/agg(lambda <S>: <el>)
 <DF> = <DF>.rank/diff/cumsum/ffill/interpo…()  # Or: <DF>.apply/agg/transform(lambda <S>: <S>)
 <DF> = <DF>.isna/fillna/isin([<el/coll>])      # Or: <DF>.applymap(lambda <el>: <el>)
 ```
@@ -3355,13 +3355,13 @@ c  6  7
 <S/DF> = pd.read_json/pickle(<path/url/file>)  # Also io.StringIO(<str>), io.BytesIO(<bytes>).
 <DF>   = pd.read_csv/excel(<path/url/file>)    # Also `header/index_col/dtype/usecols/…=<obj>`.
 <list> = pd.read_html(<path/url/file>)         # Raises ImportError if webpage has zero tables.
-<S/DF> = pd.read_parquet/feather/hdf(<path…>)  # Read_hdf() accepts `key=<s/df_name>` argument.
+<S/DF> = pd.read_parquet/feather/hdf(<path…>)  # Function read_hdf() accepts `key=<s/df_name>`.
 <DF>   = pd.read_sql('<table/query>', <conn>)  # Pass SQLite3/Alchemy connection (see #SQLite).
 ```
 
 ```python
 <DF>.to_json/csv/html/parquet/latex(<path>)    # Returns a string/bytes if path is omitted.
-<DF>.to_pickle/excel/feather/hdf(<path>)       # To_hdf() requires `key=<s/df_name>` argument.
+<DF>.to_pickle/excel/feather/hdf(<path>)       # Method to_hdf() requires `key=<s/df_name>`.
 <DF>.to_sql('<table_name>', <connection>)      # Also `if_exists='fail/replace/append'`.
 ```
 * **`'$ pip3 install "pandas[excel]" odfpy lxml pyarrow'` installs dependencies.**
@@ -3380,7 +3380,7 @@ c  6  7
 ```
 
 ```python
-<DF> = <GB>.sum/max/mean/idxmax/all()          # Or: <GB>.agg(lambda <S>: <el>)
+<DF> = <GB>.sum/max/mean/std/idxmax/count()    # Or: <GB>.agg(lambda <S>: <el>)
 <DF> = <GB>.rank/diff/cumsum/ffill()           # Or: <GB>.transform(lambda <S>: <S>)
 <DF> = <GB>.fillna(<el>)                       # Or: <GB>.transform(lambda <S>: <S>)
 ```
diff --git a/index.html b/index.html
index ea6618c4c..2f4deb3be 100644
--- a/index.html
+++ b/index.html
@@ -2618,7 +2618,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
 <li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
 </ul>
-<div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.sum/max/mean/idxmax/all/count()     <span class="hljs-comment"># Or: &lt;S&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
+<div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.sum/max/mean/std/idxmax/count()     <span class="hljs-comment"># Or: &lt;S&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;S&gt;  = &lt;S&gt;.rank/diff/cumsum/ffill/interpol…()  <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
 &lt;S&gt;  = &lt;S&gt;.isna/fillna/isin([&lt;el/coll&gt;])       <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform/map(lambda &lt;el&gt;: &lt;el&gt;)</span>
 </code></pre></div>
@@ -2707,7 +2707,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 ┃                       │ 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">&lt;S&gt;  = &lt;DF&gt;.sum/max/mean/idxmax/all/count()    <span class="hljs-comment"># Or: &lt;DF&gt;.apply/agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
+<div><h4 id="dataframeaggregatetransformmap">DataFrame — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;S&gt;  = &lt;DF&gt;.sum/max/mean/std/idxmax/count()    <span class="hljs-comment"># Or: &lt;DF&gt;.apply/agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;DF&gt; = &lt;DF&gt;.rank/diff/cumsum/ffill/interpo…()  <span class="hljs-comment"># Or: &lt;DF&gt;.apply/agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
 &lt;DF&gt; = &lt;DF&gt;.isna/fillna/isin([&lt;el/coll&gt;])      <span class="hljs-comment"># Or: &lt;DF&gt;.applymap(lambda &lt;el&gt;: &lt;el&gt;)</span>
 </code></pre></div>
@@ -2743,12 +2743,12 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <div><h3 id="fileformats">File Formats</h3><pre><code class="python language-python hljs">&lt;S/DF&gt; = pd.read_json/pickle(&lt;path/url/file&gt;)  <span class="hljs-comment"># Also io.StringIO(&lt;str&gt;), io.BytesIO(&lt;bytes&gt;).</span>
 &lt;DF&gt;   = pd.read_csv/excel(&lt;path/url/file&gt;)    <span class="hljs-comment"># Also `header/index_col/dtype/usecols/…=&lt;obj&gt;`.</span>
 &lt;list&gt; = pd.read_html(&lt;path/url/file&gt;)         <span class="hljs-comment"># Raises ImportError if webpage has zero tables.</span>
-&lt;S/DF&gt; = pd.read_parquet/feather/hdf(&lt;path…&gt;)  <span class="hljs-comment"># Read_hdf() accepts `key=&lt;s/df_name&gt;` argument.</span>
+&lt;S/DF&gt; = pd.read_parquet/feather/hdf(&lt;path…&gt;)  <span class="hljs-comment"># Function read_hdf() accepts `key=&lt;s/df_name&gt;`.</span>
 &lt;DF&gt;   = pd.read_sql(<span class="hljs-string">'&lt;table/query&gt;'</span>, &lt;conn&gt;)  <span class="hljs-comment"># Pass SQLite3/Alchemy connection (see #SQLite).</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs">&lt;DF&gt;.to_json/csv/html/parquet/latex(&lt;path&gt;)    <span class="hljs-comment"># Returns a string/bytes if path is omitted.</span>
-&lt;DF&gt;.to_pickle/excel/feather/hdf(&lt;path&gt;)       <span class="hljs-comment"># To_hdf() requires `key=&lt;s/df_name&gt;` argument.</span>
+&lt;DF&gt;.to_pickle/excel/feather/hdf(&lt;path&gt;)       <span class="hljs-comment"># Method to_hdf() requires `key=&lt;s/df_name&gt;`.</span>
 &lt;DF&gt;.to_sql(<span class="hljs-string">'&lt;table_name&gt;'</span>, &lt;connection&gt;)      <span class="hljs-comment"># Also `if_exists='fail/replace/append'`.</span>
 </code></pre>
 <ul>
@@ -2764,7 +2764,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 
-<pre><code class="python language-python hljs">&lt;DF&gt; = &lt;GB&gt;.sum/max/mean/idxmax/all()          <span class="hljs-comment"># Or: &lt;GB&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
+<pre><code class="python language-python hljs">&lt;DF&gt; = &lt;GB&gt;.sum/max/mean/std/idxmax/count()    <span class="hljs-comment"># Or: &lt;GB&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;DF&gt; = &lt;GB&gt;.rank/diff/cumsum/ffill()           <span class="hljs-comment"># Or: &lt;GB&gt;.transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
 &lt;DF&gt; = &lt;GB&gt;.fillna(&lt;el&gt;)                       <span class="hljs-comment"># Or: &lt;GB&gt;.transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
 </code></pre>

From 79c7cf8dd03d8288220a92f43f095d843b32a80a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 3 Mar 2025 18:05:20 +0100
Subject: [PATCH 103/186] Operator

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 35b6f3572..b4259e53c 100644
--- a/README.md
+++ b/README.md
@@ -2103,7 +2103,7 @@ from collections import deque
 
 Operator
 --------
-**Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence, from least to most binding. Logical and arithmetic operators in lines 1, 3 and 5 are also ordered by precedence within their own group.**
+**Module of functions that provide the functionality of operators. Functions are grouped by operator precedence, from least to most binding. Functions and operators in lines 1, 3 and 5 are also ordered by precedence within a group.**
 ```python
 import operator as op
 ```
diff --git a/index.html b/index.html
index 2f4deb3be..06f1fca6d 100644
--- a/index.html
+++ b/index.html
@@ -1735,7 +1735,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;deque&gt;.rotate(n=<span class="hljs-number">1</span>)                            <span class="hljs-comment"># Last element becomes first.</span>
 &lt;el&gt; = &lt;deque&gt;.popleft()                       <span class="hljs-comment"># Raises IndexError if deque is empty.</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 ordered and grouped by operator precedence, from least to most binding. Logical and arithmetic operators in lines 1, 3 and 5 are also ordered by precedence within their own group.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> operator <span class="hljs-keyword">as</span> op
+<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 and operators in lines 1, 3 and 5 are also ordered by precedence within a group.</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>
 
 

From d7e95926713745cada4d776efab8ffcea8b8c528 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 8 Mar 2025 13:31:12 +0100
Subject: [PATCH 104/186] Pandas csv bullets

---
 README.md  | 5 +++--
 index.html | 9 +++++----
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index b4259e53c..7a4b022a3 100644
--- a/README.md
+++ b/README.md
@@ -3365,8 +3365,9 @@ c  6  7
 <DF>.to_sql('<table_name>', <connection>)      # Also `if_exists='fail/replace/append'`.
 ```
 * **`'$ pip3 install "pandas[excel]" odfpy lxml pyarrow'` installs dependencies.**
-* **Read\_csv() only parses dates of columns that were specified by 'parse\_dates' argument. It automatically tries to detect the format, but it can be helped with 'date\_format' or 'dayfirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.**
-* **If 'parse\_dates' and 'index_col' are the same column, we get a DF with DatetimeIndex. Its `'resample("y/m/d/h")'` method returns a Resampler object that is similar to GroupBy.**
+* **Csv functions use the same dialect as standard library's csv module (e.g. `'sep=","'`).**
+* **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.**
+* **We get a dataframe with DatetimeIndex if 'parse_dates' argument includes 'index\_col'. Its `'resample("y/m/d/h")'` method returns Resampler object that is similar to GroupBy.**
 
 ### GroupBy
 **Object that groups together rows of a dataframe based on the value of the passed column.**
diff --git a/index.html b/index.html
index 06f1fca6d..b8998d7e9 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 3, 2025</aside>
+    <aside>March 8, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2753,8 +2753,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </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>Read_csv() only parses dates of columns that were specified by 'parse_dates' argument. It&nbsp;automatically tries to detect the format, but it can be helped with 'date_format' or 'dayfirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.</strong></li>
-<li><strong>If 'parse_dates' and 'index_col' are the same column, we get a DF with DatetimeIndex. Its <code class="python hljs"><span class="hljs-string">'resample("y/m/d/h")'</span></code> method returns a Resampler object that is similar to GroupBy.</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">&lt;GB&gt; = &lt;DF&gt;.groupby(col_key/s)                 <span class="hljs-comment"># Splits DF into groups based on passed column.</span>
 &lt;DF&gt; = &lt;GB&gt;.apply/filter(&lt;func&gt;)               <span class="hljs-comment"># Filter drops a group if func returns False.</span>
@@ -2942,7 +2943,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 3, 2025</aside>
+    <aside>March 8, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 3721a7151b399004b878ccc11a8ad25e981720db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 9 Mar 2025 18:21:38 +0100
Subject: [PATCH 105/186] Class, Plotly

---
 README.md  | 19 ++++++++++---------
 index.html | 23 ++++++++++++-----------
 parse.js   |  2 +-
 3 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/README.md b/README.md
index 7a4b022a3..d07d6bf26 100644
--- a/README.md
+++ b/README.md
@@ -999,7 +999,7 @@ raise Exception(<obj>)
 print/str/repr([<obj>])
 print/str/repr({<obj>: <obj>})
 f'{<obj>!r}'
-Z = dataclasses.make_dataclass('Z', ['a']); print/str/repr(Z(<obj>))
+Z = make_dataclass('Z', ['a']); print/str/repr(Z(<obj>))
 >>> <obj>
 ```
 
@@ -1034,9 +1034,9 @@ class C(A, B): pass
 ```python
 from collections import abc
 
-<name>: <type> [| ...] [= <obj>]                              # `|` since 3.10.
-<name>: list/set/abc.Iterable/abc.Sequence[<type>] [= <obj>]  # Since 3.9.
-<name>: dict/tuple[<type>, ...] [= <obj>]                     # Since 3.9.
+<name>: <type> [| ...] [= <obj>]
+<name>: list/set/abc.Iterable/abc.Sequence[<type>] [= <obj>]
+<name>: dict/tuple[<type>, ...] [= <obj>]
 ```
 
 ### Dataclass
@@ -1056,9 +1056,9 @@ class <class_name>:
 * **For attributes of arbitrary type use `'typing.Any'`.**
 
 ```python
-Point = make_dataclass('Point', ['x', 'y'])
-Point = make_dataclass('Point', [('x', float), ('y', float)])
-Point = make_dataclass('Point', [('x', float, 0), ('y', float, 0)])
+P = make_dataclass('P', ['x', 'y'])
+P = make_dataclass('P', [('x', float), ('y', float)])
+P = make_dataclass('P', [('x', float, 0), ('y', float, 0)])
 ```
 
 ### Property
@@ -3440,7 +3440,7 @@ import plotly.express as px, pandas as pd
 ```python
 covid = pd.read_csv('https://raw.githubusercontent.com/owid/covid-19-data/8dde8ca49b'
                     '6e648c17dd420b2726ca0779402651/public/data/owid-covid-data.csv',
-                    usecols=['iso_code', 'date', 'total_deaths', 'population'])
+                    usecols=['iso_code', 'date', 'population', 'total_deaths'])
 continents = pd.read_csv('https://gto76.github.io/python-cheatsheet/web/continents.csv',
                          usecols=['Three_Letter_Country_Code', 'Continent_Name'])
 df = pd.merge(covid, continents, left_on='iso_code', right_on='Three_Letter_Country_Code')
@@ -3483,7 +3483,8 @@ def get_ticker(driver, name, symbol):
     driver.get(url + '?period1=1579651200&period2=9999999999')
     if buttons := driver.find_elements('xpath', '//button[@name="reject"]'):
         buttons[0].click()
-    dataframes = pd.read_html(io.StringIO(driver.page_source), parse_dates=['Date'])
+    html = io.StringIO(driver.page_source)
+    dataframes = pd.read_html(html, parse_dates=['Date'])
     s = dataframes[0].set_index('Date').Open
     return s.rename(name)
 
diff --git a/index.html b/index.html
index b8998d7e9..e685859cd 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 8, 2025</aside>
+    <aside>March 9, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -847,7 +847,7 @@
 <div><h4 id="expressionsthatcallthereprmethod">Expressions that call the repr() method:</h4><pre><code class="python language-python hljs">print/str/repr([&lt;obj&gt;])
 print/str/repr({&lt;obj&gt;: &lt;obj&gt;})
 <span class="hljs-string">f'<span class="hljs-subst">{&lt;obj&gt;!r}</span>'</span>
-Z = dataclasses.make_dataclass(<span class="hljs-string">'Z'</span>, [<span class="hljs-string">'a'</span>]); print/str/repr(Z(&lt;obj&gt;))
+Z = make_dataclass(<span class="hljs-string">'Z'</span>, [<span class="hljs-string">'a'</span>]); print/str/repr(Z(&lt;obj&gt;))
 <span class="hljs-meta">&gt;&gt;&gt; </span>&lt;obj&gt;
 </code></pre></div>
 
@@ -875,9 +875,9 @@
 <li><strong>Hints are used by type checkers like <a href="https://pypi.org/project/mypy/">mypy</a>, data validation libraries such as <a href="https://pypi.org/project/pydantic/">Pydantic</a> and lately also by <a href="https://pypi.org/project/Cython/">Cython</a> compiler. However, they are not enforced by CPython interpreter.</strong></li>
 </ul><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> abc
 
-&lt;name&gt;: &lt;type&gt; [| ...] [= &lt;obj&gt;]                              <span class="hljs-comment"># `|` since 3.10.</span>
-&lt;name&gt;: list/set/abc.Iterable/abc.Sequence[&lt;type&gt;] [= &lt;obj&gt;]  <span class="hljs-comment"># Since 3.9.</span>
-&lt;name&gt;: dict/tuple[&lt;type&gt;, ...] [= &lt;obj&gt;]                     <span class="hljs-comment"># Since 3.9.</span>
+&lt;name&gt;: &lt;type&gt; [| ...] [= &lt;obj&gt;]
+&lt;name&gt;: list/set/abc.Iterable/abc.Sequence[&lt;type&gt;] [= &lt;obj&gt;]
+&lt;name&gt;: dict/tuple[&lt;type&gt;, ...] [= &lt;obj&gt;]
 </code></pre></div>
 
 
@@ -897,9 +897,9 @@
 <li><strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">'&lt;attr_name&gt;: list = []'</span></code> would make a list that is shared among all instances. Its 'default_factory' argument can be any <a href="#callable">callable</a>.</strong></li>
 <li><strong>For attributes of arbitrary type use <code class="python hljs"><span class="hljs-string">'typing.Any'</span></code>.</strong></li>
 </ul>
-<pre><code class="python language-python hljs">Point = make_dataclass(<span class="hljs-string">'Point'</span>, [<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>])
-Point = make_dataclass(<span class="hljs-string">'Point'</span>, [(<span class="hljs-string">'x'</span>, float), (<span class="hljs-string">'y'</span>, float)])
-Point = make_dataclass(<span class="hljs-string">'Point'</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>)])
+<pre><code class="python language-python hljs">P = make_dataclass(<span class="hljs-string">'P'</span>, [<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>])
+P = make_dataclass(<span class="hljs-string">'P'</span>, [(<span class="hljs-string">'x'</span>, float), (<span class="hljs-string">'y'</span>, float)])
+P = 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><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>
@@ -2803,7 +2803,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <div><h4 id="displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">Displays a line chart of total coronavirus 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">'total_deaths'</span>, <span class="hljs-string">'population'</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>)
@@ -2842,7 +2842,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     driver.get(url + <span class="hljs-string">'?period1=1579651200&amp;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()
-    dataframes = pd.read_html(io.StringIO(driver.page_source), parse_dates=[<span class="hljs-string">'Date'</span>])
+    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)
 
@@ -2943,7 +2944,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 8, 2025</aside>
+    <aside>March 9, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 1c660edec..51a02ab01 100755
--- a/parse.js
+++ b/parse.js
@@ -76,7 +76,7 @@ const REPR_USE_CASES =
   'print/str/repr([&lt;obj&gt;])\n' +
   'print/str/repr({&lt;obj&gt;: &lt;obj&gt;})\n' +
   '<span class="hljs-string">f\'<span class="hljs-subst">{&lt;obj&gt;!r}</span>\'</span>\n' +
-  'Z = dataclasses.make_dataclass(<span class="hljs-string">\'Z\'</span>, [<span class="hljs-string">\'a\'</span>]); print/str/repr(Z(&lt;obj&gt;))\n' +
+  'Z = make_dataclass(<span class="hljs-string">\'Z\'</span>, [<span class="hljs-string">\'a\'</span>]); print/str/repr(Z(&lt;obj&gt;))\n' +
   '<span class="hljs-meta">&gt;&gt;&gt; </span>&lt;obj&gt;\n';
 
 const CONSTRUCTOR_OVERLOADING =

From d8cd43a0ac56f44e812b6e3e3230d7a466588181 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 9 Mar 2025 21:55:51 +0100
Subject: [PATCH 106/186] Plotly

---
 README.md  | 14 +++++++-------
 index.html | 16 ++++++++--------
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/README.md b/README.md
index d07d6bf26..adaf7d1ad 100644
--- a/README.md
+++ b/README.md
@@ -3420,16 +3420,16 @@ import plotly.express as px, pandas as pd
 ```
 
 ```python
-<Fig> = px.line(<DF>, x=col_key, y=col_key)            # Or: px.line(x=<list>, y=<list>)
-<Fig>.update_layout(margin=dict(t=0, r=0, b=0, l=0))   # Also `paper_bgcolor='rgb(0, 0, 0)'`.
-<Fig>.write_html/json/image('<path>')                  # <Fig>.show() displays the plot.
+<Fig> = px.line(<DF>, x=col_key, y=col_key)           # Or: px.line(x=<list>, y=<list>)
+<Fig>.update_layout(margin=dict(t=0, r=0, b=0, l=0))  # Also `paper_bgcolor='rgb(0, 0, 0)'`.
+<Fig>.write_html/json/image('<path>')                 # <Fig>.show() displays the plot.
 ```
 
 ```python
-<Fig> = px.area/bar/box(<DF>, x=col_key, y=col_key)    # Also `color=col_key`.
-<Fig> = px.scatter(<DF>, x=col_key, y=col_key)         # Also `color/size/symbol=col_key`.
-<Fig> = px.scatter_3d(<DF>, x=col_key, y=col_key, …)   # `z=col_key`. Also color/size/symbol.
-<Fig> = px.histogram(<DF>, x=col_key [, nbins=<int>])  # Number of bins depends on DF size.
+<Fig> = px.area/bar/box(<DF>, x=col_key, y=col_key)   # Also `color=col_key`.
+<Fig> = px.scatter(<DF>, x=col_key, y=col_key)        # Also `color/size/symbol=col_key`.
+<Fig> = px.scatter_3d(<DF>, x=col_key, y=col_key, …)  # `z=col_key`. Also color/size/symbol.
+<Fig> = px.histogram(<DF>, x=col_key)                 # Also `nbins=<int>`.
 ```
 
 #### Displays a line chart of total coronavirus deaths per million grouped by continent:
diff --git a/index.html b/index.html
index e685859cd..0e471192d 100644
--- a/index.html
+++ b/index.html
@@ -2792,14 +2792,14 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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">&lt;Fig&gt; = px.line(&lt;DF&gt;, x=col_key, y=col_key)            <span class="hljs-comment"># Or: px.line(x=&lt;list&gt;, y=&lt;list&gt;)</span>
-&lt;Fig&gt;.update_layout(margin=dict(t=<span class="hljs-number">0</span>, r=<span class="hljs-number">0</span>, b=<span class="hljs-number">0</span>, l=<span class="hljs-number">0</span>))   <span class="hljs-comment"># Also `paper_bgcolor='rgb(0, 0, 0)'`.</span>
-&lt;Fig&gt;.write_html/json/image(<span class="hljs-string">'&lt;path&gt;'</span>)                  <span class="hljs-comment"># &lt;Fig&gt;.show() displays the plot.</span>
-</code></pre>
-<pre><code class="python language-python hljs">&lt;Fig&gt; = px.area/bar/box(&lt;DF&gt;, x=col_key, y=col_key)    <span class="hljs-comment"># Also `color=col_key`.</span>
-&lt;Fig&gt; = px.scatter(&lt;DF&gt;, x=col_key, y=col_key)         <span class="hljs-comment"># Also `color/size/symbol=col_key`.</span>
-&lt;Fig&gt; = px.scatter_3d(&lt;DF&gt;, x=col_key, y=col_key, …)   <span class="hljs-comment"># `z=col_key`. Also color/size/symbol.</span>
-&lt;Fig&gt; = px.histogram(&lt;DF&gt;, x=col_key [, nbins=&lt;int&gt;])  <span class="hljs-comment"># Number of bins depends on DF size.</span>
+<pre><code class="python language-python hljs">&lt;Fig&gt; = px.line(&lt;DF&gt;, x=col_key, y=col_key)           <span class="hljs-comment"># Or: px.line(x=&lt;list&gt;, y=&lt;list&gt;)</span>
+&lt;Fig&gt;.update_layout(margin=dict(t=<span class="hljs-number">0</span>, r=<span class="hljs-number">0</span>, b=<span class="hljs-number">0</span>, l=<span class="hljs-number">0</span>))  <span class="hljs-comment"># Also `paper_bgcolor='rgb(0, 0, 0)'`.</span>
+&lt;Fig&gt;.write_html/json/image(<span class="hljs-string">'&lt;path&gt;'</span>)                 <span class="hljs-comment"># &lt;Fig&gt;.show() displays the plot.</span>
+</code></pre>
+<pre><code class="python language-python hljs">&lt;Fig&gt; = px.area/bar/box(&lt;DF&gt;, x=col_key, y=col_key)   <span class="hljs-comment"># Also `color=col_key`.</span>
+&lt;Fig&gt; = px.scatter(&lt;DF&gt;, x=col_key, y=col_key)        <span class="hljs-comment"># Also `color/size/symbol=col_key`.</span>
+&lt;Fig&gt; = px.scatter_3d(&lt;DF&gt;, x=col_key, y=col_key, …)  <span class="hljs-comment"># `z=col_key`. Also color/size/symbol.</span>
+&lt;Fig&gt; = px.histogram(&lt;DF&gt;, x=col_key)                 <span class="hljs-comment"># Also `nbins=&lt;int&gt;`.</span>
 </code></pre>
 <div><h4 id="displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">Displays a line chart of total coronavirus 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>,

From 889b34f5df9cf54e86258ba47fb847ce404ca0b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 10 Mar 2025 00:22:34 +0100
Subject: [PATCH 107/186] Second plot height reduction

---
 README.md  | 2 +-
 index.html | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index adaf7d1ad..dc2e84d0f 100644
--- a/README.md
+++ b/README.md
@@ -3454,7 +3454,7 @@ px.line(df, x='Date', y='Total Deaths per Million', color='Continent').show()
 #### Displays a multi-axis line chart of total coronavirus cases and changes in prices of Bitcoin, Dow Jones and gold:
 
 ![Covid Cases](web/covid_cases.png)
-<div id="e23ccacc-a456-478b-b467-7282a2165921" class="plotly-graph-div" style="height:287px; width:935px;"></div>
+<div id="e23ccacc-a456-478b-b467-7282a2165921" class="plotly-graph-div" style="height:285px; width:935px;"></div>
 
 ```python
 # $ pip3 install pandas lxml selenium plotly
diff --git a/index.html b/index.html
index 0e471192d..c7e8d10a9 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 9, 2025</aside>
+    <aside>March 10, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2816,7 +2816,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<div><h4 id="displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">Displays a multi-axis line chart of total coronavirus 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:287px; width:935px;"></div><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pandas lxml selenium plotly</span>
+<div><h4 id="displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">Displays a multi-axis line chart of total coronavirus 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>
@@ -2944,7 +2944,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 9, 2025</aside>
+    <aside>March 10, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 020bbb197029720b319e4c1edfa78754a35adf3b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 16 Mar 2025 16:30:37 +0100
Subject: [PATCH 108/186] Renamed Arguments to Function, big changes in Splat
 and Inline

---
 README.md                    | 104 +++++++++++++++++------------------
 index.html                   | 103 +++++++++++++++++-----------------
 parse.js                     |  30 ++++++++--
 pdf/index_for_pdf.html       |  16 +++---
 pdf/index_for_pdf_print.html |  12 ++--
 web/script_2.js              |   4 +-
 6 files changed, 142 insertions(+), 127 deletions(-)

diff --git a/README.md b/README.md
index dc2e84d0f..2e3342eaf 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ Contents
 --------
 **&nbsp;&nbsp;&nbsp;** **1. Collections:** **&nbsp;** **[`List`](#list)**__,__ **[`Dictionary`](#dictionary)**__,__ **[`Set`](#set)**__,__ **[`Tuple`](#tuple)**__,__ **[`Range`](#range)**__,__ **[`Enumerate`](#enumerate)**__,__ **[`Iterator`](#iterator)**__,__ **[`Generator`](#generator)**__.__  
 **&nbsp;&nbsp;&nbsp;** **2. Types:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`Type`](#type)**__,__ **[`String`](#string)**__,__ **[`Regular_Exp`](#regex)**__,__ **[`Format`](#format)**__,__ **[`Numbers`](#numbers-1)**__,__ **[`Combinatorics`](#combinatorics)**__,__ **[`Datetime`](#datetime)**__.__  
-**&nbsp;&nbsp;&nbsp;** **3. Syntax:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`Args`](#arguments)**__,__ **[`Inline`](#inline)**__,__ **[`Import`](#imports)**__,__ **[`Decorator`](#decorator)**__,__ **[`Class`](#class)**__,__ **[`Duck_Types`](#duck-types)**__,__ **[`Enum`](#enum)**__,__ **[`Exception`](#exceptions)**__.__  
+**&nbsp;&nbsp;&nbsp;** **3. Syntax:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`Function`](#function)**__,__ **[`Inline`](#inline)**__,__ **[`Import`](#imports)**__,__ **[`Decorator`](#decorator)**__,__ **[`Class`](#class)**__,__ **[`Duck_Type`](#duck-types)**__,__ **[`Enum`](#enum)**__,__ **[`Except`](#exceptions)**__.__  
 **&nbsp;&nbsp;&nbsp;** **4. System:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`Exit`](#exit)**__,__ **[`Print`](#print)**__,__ **[`Input`](#input)**__,__ **[`Command_Line_Arguments`](#command-line-arguments)**__,__ **[`Open`](#open)**__,__ **[`Path`](#paths)**__,__ **[`OS_Commands`](#os-commands)**__.__  
 **&nbsp;&nbsp;&nbsp;** **5. Data:** **&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**  **[`JSON`](#json)**__,__ **[`Pickle`](#pickle)**__,__ **[`CSV`](#csv)**__,__ **[`SQLite`](#sqlite)**__,__ **[`Bytes`](#bytes)**__,__ **[`Struct`](#struct)**__,__ **[`Array`](#array)**__,__ **[`Memory_View`](#memory-view)**__,__ **[`Deque`](#deque)**__.__  
 **&nbsp;&nbsp;&nbsp;** **6. Advanced:** **&nbsp;&nbsp;&nbsp;**  **[`Operator`](#operator)**__,__ **[`Match_Stmt`](#match-statement)**__,__ **[`Logging`](#logging)**__,__ **[`Introspection`](#introspection)**__,__ **[`Threading`](#threading)**__,__ **[`Coroutines`](#coroutines)**__.__  
@@ -671,86 +671,72 @@ import zoneinfo, dateutil.tz
 ```
 
 
-Arguments
----------
-### Inside Function Call
+Function
+--------
+**Independent block of code that returns a value when called.**
 ```python
-func(<positional_args>)                           # func(0, 0)
-func(<keyword_args>)                              # func(x=0, y=0)
-func(<positional_args>, <keyword_args>)           # func(0, y=0)
+def <func_name>(<nondefault_args>): ...                  # E.g. `def func(x, y): ...`.
+def <func_name>(<default_args>): ...                     # E.g. `def func(x=0, y=0): ...`.
+def <func_name>(<nondefault_args>, <default_args>): ...  # E.g. `def func(x, y=0): ...`.
 ```
+* **Function returns None if it doesn't encounter `'return <obj/exp>'` statement.**
+* **Before modifying a global variable from within the function run `'global <var_name>'`.**
+* **Default values are evaluated when function is first encountered in the scope. Any mutation of a mutable default value will persist between invocations!**
+
+### Function Call
 
-### Inside Function Definition
 ```python
-def func(<nondefault_args>): ...                  # def func(x, y): ...
-def func(<default_args>): ...                     # def func(x=0, y=0): ...
-def func(<nondefault_args>, <default_args>): ...  # def func(x, y=0): ...
+<obj> = <function>(<positional_args>)                    # E.g. `func(0, 0)`.
+<obj> = <function>(<keyword_args>)                       # E.g. `func(x=0, y=0)`.
+<obj> = <function>(<positional_args>, <keyword_args>)    # E.g. `func(0, y=0)`.
 ```
-* **Default values are evaluated when function is first encountered in the scope.**
-* **Any mutation of a mutable default value will persist between invocations!**
 
 
 Splat Operator
 --------------
-### Inside Function Call
 **Splat expands a collection into positional arguments, while splatty-splat expands a dictionary into keyword arguments.**
 ```python
-args   = (1, 2)
-kwargs = {'x': 3, 'y': 4, 'z': 5}
+args, kwargs = (1, 2), {'z': 3}
 func(*args, **kwargs)
 ```
 
 #### Is the same as:
 ```python
-func(1, 2, x=3, y=4, z=5)
+func(1, 2, z=3)
 ```
 
 ### Inside Function Definition
 **Splat combines zero or more positional arguments into a tuple, while splatty-splat combines zero or more keyword arguments into a dictionary.**
 ```python
-def add(*a):
-    return sum(a)
-```
-
-```python
+>>> def add(*a):
+...     return sum(a)
+...
 >>> add(1, 2, 3)
 6
 ```
 
-#### Legal argument combinations:
-```python
-def f(*args): ...               # f(1, 2, 3)
-def f(x, *args): ...            # f(1, 2, 3)
-def f(*args, z): ...            # f(1, 2, z=3)
-```
-
-```python
-def f(**kwargs): ...            # f(x=1, y=2, z=3)
-def f(x, **kwargs): ...         # f(x=1, y=2, z=3) | f(1, y=2, z=3)
-```
-
+#### Allowed compositions of arguments inside function definition and the ways they can be called:
 ```python
-def f(*args, **kwargs): ...     # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3) | f(1, 2, 3)
-def f(x, *args, **kwargs): ...  # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3) | f(1, 2, 3)
-def f(*args, y, **kwargs): ...  # f(x=1, y=2, z=3) | f(1, y=2, z=3)
-```
-
-```python
-def f(*, x, y, z): ...          # f(x=1, y=2, z=3)
-def f(x, *, y, z): ...          # f(x=1, y=2, z=3) | f(1, y=2, z=3)
-def f(x, y, *, z): ...          # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3)
++--------------------+------------+--------------+----------------+------------------+
+|                    | f(1, 2, 3) | f(1, 2, z=3) | f(1, y=2, z=3) | f(x=1, y=2, z=3) |
++--------------------+------------+--------------+----------------+------------------+
+| f(x, *args, **kw): |     yes    |     yes      |       yes      |       yes        |
+| f(*args, z, **kw): |            |     yes      |       yes      |       yes        |
+| f(x, **kw):        |            |              |       yes      |       yes        |
+| f(*, x, **kw):     |            |              |                |       yes        |
++--------------------+------------+--------------+----------------+------------------+
 ```
 
 ### Other Uses
 ```python
-<list>  = [*<coll.> [, ...]]    # Or: list(<collection>) [+ ...]
-<tuple> = (*<coll.>, [...])     # Or: tuple(<collection>) [+ ...]
-<set>   = {*<coll.> [, ...]}    # Or: set(<collection>) [| ...]
-<dict>  = {**<dict> [, ...]}    # Or: <dict> | ...
+<list>  = [*<collection> [, ...]]  # Or: list(<collection>) [+ ...]
+<tuple> = (*<collection>, [...])   # Or: tuple(<collection>) [+ ...]
+<set>   = {*<collection> [, ...]}  # Or: set(<collection>) [| ...]
+<dict>  = {**<dict> [, ...]}       # Or: <dict> | ...
 ```
 
 ```python
-head, *body, tail = <coll.>     # Head or tail can be omitted.
+head, *body, tail = <collection>   # Head or tail can be omitted.
 ```
 
 
@@ -798,24 +784,32 @@ from functools import reduce
 ```
 
 ```python
->>> [a if a else 'zero' for a in (0, 1, 2, 3)]      # `any([0, '', [], None]) == False`
+>>> [i if i else 'zero' for i in (0, 1, 2, 3)]      # `any([0, '', [], None]) == False`
 ['zero', 1, 2, 3]
 ```
 
+### And, Or
+```python
+<obj> = <exp> and <exp> [and ...]                   # Returns first false or last operand.
+<obj> = <exp> or <exp> [or ...]                     # Returns first true or last operand.
+```
+
+### Walrus Operator
+```python
+>>> [i for a in '0123' if (i := int(a)) > 0]        # Assigns to variable mid-sentence.
+[1, 2, 3]
+```
+
 ### Named Tuple, Enum, Dataclass
 ```python
 from collections import namedtuple
-Point = namedtuple('Point', 'x y')                  # Creates a tuple's subclass.
+Point = namedtuple('Point', 'x y')                  # Creates tuple's subclass.
 point = Point(0, 0)                                 # Returns its instance.
-```
 
-```python
 from enum import Enum
-Direction = Enum('Direction', 'N E S W')            # Creates an enum.
+Direction = Enum('Direction', 'N E S W')            # Creates Enum's subclass.
 direction = Direction.N                             # Returns its member.
-```
 
-```python
 from dataclasses import make_dataclass
 Player = make_dataclass('Player', ['loc', 'dir'])   # Creates a class.
 player = Player(point, direction)                   # Returns its instance.
diff --git a/index.html b/index.html
index c7e8d10a9..a0dbf7797 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 10, 2025</aside>
+    <aside>March 16, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -94,7 +94,7 @@
 </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. 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'</span></span></strong>:      [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>],
+    <strong><span class="hljs-string"><span class="hljs-string">'3. Syntax'</span></span></strong>:      [<a href="#function">Function</a>, <a href="#inline">Inline</a>, <a href="#imports">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'</span></span></strong>:      [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">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'</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. Advanced'</span></span></strong>:    [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],
@@ -598,62 +598,55 @@
 &lt;float&gt;  = &lt;TD&gt;      / &lt;TD&gt;                 <span class="hljs-comment"># Also `(&lt;int&gt;, &lt;TD&gt;) = divmod(&lt;TD&gt;, &lt;TD&gt;)`.</span>
 </code></pre></div>
 
-<div><h2 id="arguments"><a href="#arguments" name="arguments">#</a>Arguments</h2><div><h3 id="insidefunctioncall">Inside Function Call</h3><pre><code class="python language-python hljs">func(&lt;positional_args&gt;)                           <span class="hljs-comment"># func(0, 0)</span>
-func(&lt;keyword_args&gt;)                              <span class="hljs-comment"># func(x=0, y=0)</span>
-func(&lt;positional_args&gt;, &lt;keyword_args&gt;)           <span class="hljs-comment"># func(0, y=0)</span>
-</code></pre></div></div>
-
-
-<div><h3 id="insidefunctiondefinition">Inside Function Definition</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func</span><span class="hljs-params">(&lt;nondefault_args&gt;)</span>:</span> ...                  <span class="hljs-comment"># def func(x, y): ...</span>
-<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func</span><span class="hljs-params">(&lt;default_args&gt;)</span>:</span> ...                     <span class="hljs-comment"># def func(x=0, y=0): ...</span>
-<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">func</span><span class="hljs-params">(&lt;nondefault_args&gt;, &lt;default_args&gt;)</span>:</span> ...  <span class="hljs-comment"># def func(x, y=0): ...</span>
+<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> &lt;<span class="hljs-title">func_name</span>&gt;<span class="hljs-params">(&lt;nondefault_args&gt;)</span>:</span> ...                  <span class="hljs-comment"># E.g. `def func(x, y): ...`.</span>
+<span class="hljs-function"><span class="hljs-keyword">def</span> &lt;<span class="hljs-title">func_name</span>&gt;<span class="hljs-params">(&lt;default_args&gt;)</span>:</span> ...                     <span class="hljs-comment"># E.g. `def func(x=0, y=0): ...`.</span>
+<span class="hljs-function"><span class="hljs-keyword">def</span> &lt;<span class="hljs-title">func_name</span>&gt;<span class="hljs-params">(&lt;nondefault_args&gt;, &lt;default_args&gt;)</span>:</span> ...  <span class="hljs-comment"># E.g. `def func(x, y=0): ...`.</span>
 </code></pre></div>
 
+
 <ul>
-<li><strong>Default values are evaluated when function is first encountered in the scope.</strong></li>
-<li><strong>Any mutation of a mutable default value will persist between invocations!</strong></li>
+<li><strong>Function returns None if it doesn't encounter <code class="python hljs"><span class="hljs-string">'return &lt;obj/exp&gt;'</span></code> statement.</strong></li>
+<li><strong>Before modifying a global variable from within the function run <code class="python hljs"><span class="hljs-string">'global &lt;var_name&gt;'</span></code>.</strong></li>
+<li><strong>Default values are evaluated when function is first encountered in the scope. Any mutation of a mutable default value will persist between invocations!</strong></li>
 </ul>
-<div><h2 id="splatoperator"><a href="#splatoperator" name="splatoperator">#</a>Splat Operator</h2><div><h3 id="insidefunctioncall-1">Inside Function Call</h3><p><strong>Splat expands a collection into positional arguments, while splatty-splat expands a dictionary into keyword arguments.</strong></p><pre><code class="python language-python hljs">args   = (<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)
-kwargs = {<span class="hljs-string">'x'</span>: <span class="hljs-number">3</span>, <span class="hljs-string">'y'</span>: <span class="hljs-number">4</span>, <span class="hljs-string">'z'</span>: <span class="hljs-number">5</span>}
-func(*args, **kwargs)
-</code></pre></div></div>
+<div><h3 id="functioncall">Function Call</h3><pre><code class="python language-python hljs">&lt;obj&gt; = &lt;function&gt;(&lt;positional_args&gt;)                    <span class="hljs-comment"># E.g. `func(0, 0)`.</span>
+&lt;obj&gt; = &lt;function&gt;(&lt;keyword_args&gt;)                       <span class="hljs-comment"># E.g. `func(x=0, y=0)`.</span>
+&lt;obj&gt; = &lt;function&gt;(&lt;positional_args&gt;, &lt;keyword_args&gt;)    <span class="hljs-comment"># E.g. `func(0, y=0)`.</span>
+</code></pre></div>
 
+<div><h2 id="splatoperator"><a href="#splatoperator" name="splatoperator">#</a>Splat Operator</h2><p><strong>Splat expands a collection into positional arguments, while splatty-splat 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>, x=<span class="hljs-number">3</span>, y=<span class="hljs-number">4</span>, z=<span class="hljs-number">5</span>)
+<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="insidefunctiondefinition-1">Inside Function Definition</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">(*a)</span>:</span>
-    <span class="hljs-keyword">return</span> sum(a)
+<div><h3 id="insidefunctiondefinition">Inside Function Definition</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-meta">&gt;&gt;&gt; </span><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span><span class="hljs-params">(*a)</span>:</span>
+<span class="hljs-meta">... </span>    <span class="hljs-keyword">return</span> sum(a)
+<span class="hljs-meta">... </span>
+<span class="hljs-meta">&gt;&gt;&gt; </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></div>
 
 
-<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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>
-<div><h4 id="legalargumentcombinations">Legal argument combinations:</h4><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(*args)</span>:</span> ...               <span class="hljs-comment"># f(1, 2, 3)</span>
-<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(x, *args)</span>:</span> ...            <span class="hljs-comment"># f(1, 2, 3)</span>
-<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(*args, z)</span>:</span> ...            <span class="hljs-comment"># f(1, 2, z=3)</span>
+<div><h4 id="allowedcompositionsofargumentsinsidefunctiondefinitionandthewaystheycanbecalled">Allowed compositions of arguments inside function definition and the ways they can be called:</h4><pre><code class="python language-python hljs">┏━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━┓
+┃                    │ f(<span class="hljs-number"><span class="hljs-number">1</span></span>, <span class="hljs-number"><span class="hljs-number">2</span></span>, <span class="hljs-number"><span class="hljs-number">3</span></span>) │ f(<span class="hljs-number"><span class="hljs-number">1</span></span>, <span class="hljs-number"><span class="hljs-number">2</span></span>, z=<span class="hljs-number"><span class="hljs-number">3</span></span>) │ f(<span class="hljs-number"><span class="hljs-number">1</span></span>, y=<span class="hljs-number"><span class="hljs-number">2</span></span>, z=<span class="hljs-number"><span class="hljs-number">3</span></span>) │ f(x=<span class="hljs-number"><span class="hljs-number">1</span></span>, y=<span class="hljs-number"><span class="hljs-number">2</span></span>, z=<span class="hljs-number"><span class="hljs-number">3</span></span>) ┃
+┠────────────────────┼────────────┼──────────────┼────────────────┼──────────────────┨
+┃ <span class="hljs-title">f</span>(x, *args, **kw): │      ✓     │      ✓       │        ✓       │        ✓         ┃
+┃ <span class="hljs-title">f</span>(*args, z, **kw): │            │      ✓       │        ✓       │        ✓         ┃
+┃ <span class="hljs-title">f</span>(x, **kw):        │            │              │        ✓       │        ✓         ┃
+┃ <span class="hljs-title">f</span>(*, x, **kw):     │            │              │                │        ✓         ┃
+┗━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┛
 </code></pre></div>
 
-<pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(**kwargs)</span>:</span> ...            <span class="hljs-comment"># f(x=1, y=2, z=3)</span>
-<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(x, **kwargs)</span>:</span> ...         <span class="hljs-comment"># f(x=1, y=2, z=3) | f(1, y=2, z=3)</span>
-</code></pre>
-<pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(*args, **kwargs)</span>:</span> ...     <span class="hljs-comment"># f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3) | f(1, 2, 3)</span>
-<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(x, *args, **kwargs)</span>:</span> ...  <span class="hljs-comment"># f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3) | f(1, 2, 3)</span>
-<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(*args, y, **kwargs)</span>:</span> ...  <span class="hljs-comment"># f(x=1, y=2, z=3) | f(1, y=2, z=3)</span>
-</code></pre>
-<pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(*, x, y, z)</span>:</span> ...          <span class="hljs-comment"># f(x=1, y=2, z=3)</span>
-<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(x, *, y, z)</span>:</span> ...          <span class="hljs-comment"># f(x=1, y=2, z=3) | f(1, y=2, z=3)</span>
-<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">f</span><span class="hljs-params">(x, y, *, z)</span>:</span> ...          <span class="hljs-comment"># f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3)</span>
-</code></pre>
-<div><h3 id="otheruses">Other Uses</h3><pre><code class="python language-python hljs">&lt;list&gt;  = [*&lt;coll.&gt; [, ...]]    <span class="hljs-comment"># Or: list(&lt;collection&gt;) [+ ...]</span>
-&lt;tuple&gt; = (*&lt;coll.&gt;, [...])     <span class="hljs-comment"># Or: tuple(&lt;collection&gt;) [+ ...]</span>
-&lt;set&gt;   = {*&lt;coll.&gt; [, ...]}    <span class="hljs-comment"># Or: set(&lt;collection&gt;) [| ...]</span>
-&lt;dict&gt;  = {**&lt;dict&gt; [, ...]}    <span class="hljs-comment"># Or: &lt;dict&gt; | ...</span>
+<div><h3 id="otheruses">Other Uses</h3><pre><code class="python language-python hljs">&lt;list&gt;  = [*&lt;collection&gt; [, ...]]  <span class="hljs-comment"># Or: list(&lt;collection&gt;) [+ ...]</span>
+&lt;tuple&gt; = (*&lt;collection&gt;, [...])   <span class="hljs-comment"># Or: tuple(&lt;collection&gt;) [+ ...]</span>
+&lt;set&gt;   = {*&lt;collection&gt; [, ...]}  <span class="hljs-comment"># Or: set(&lt;collection&gt;) [| ...]</span>
+&lt;dict&gt;  = {**&lt;dict&gt; [, ...]}       <span class="hljs-comment"># Or: &lt;dict&gt; | ...</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs">head, *body, tail = &lt;coll.&gt;     <span class="hljs-comment"># Head or tail can be omitted.</span>
+<pre><code class="python language-python hljs">head, *body, tail = &lt;collection&gt;   <span class="hljs-comment"># Head or tail can be omitted.</span>
 </code></pre>
 <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">&lt;func&gt; = <span class="hljs-keyword">lambda</span>: &lt;return_value&gt;                     <span class="hljs-comment"># A single statement function.</span>
 &lt;func&gt; = <span class="hljs-keyword">lambda</span> &lt;arg_1&gt;, &lt;arg_2&gt;: &lt;return_value&gt;    <span class="hljs-comment"># Also allows default arguments.</span>
@@ -683,22 +676,30 @@
 <div><h3 id="conditionalexpression">Conditional Expression</h3><pre><code class="python language-python hljs">&lt;obj&gt; = &lt;exp&gt; <span class="hljs-keyword">if</span> &lt;condition&gt; <span class="hljs-keyword">else</span> &lt;exp&gt;             <span class="hljs-comment"># Only one expression is evaluated.</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>[a <span class="hljs-keyword">if</span> a <span class="hljs-keyword">else</span> <span class="hljs-string">'zero'</span> <span class="hljs-keyword">for</span> a <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-number">3</span>)]      <span class="hljs-comment"># `any([0, '', [], None]) == False`</span>
+<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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-number">3</span>)]      <span class="hljs-comment"># `any([0, '', [], None]) == False`</span>
 [<span class="hljs-string">'zero'</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
 </code></pre>
+<div><h3 id="andor">And, Or</h3><pre><code class="python language-python hljs">&lt;obj&gt; = &lt;exp&gt; <span class="hljs-keyword">and</span> &lt;exp&gt; [<span class="hljs-keyword">and</span> ...]                   <span class="hljs-comment"># Returns first false or last operand.</span>
+&lt;obj&gt; = &lt;exp&gt; <span class="hljs-keyword">or</span> &lt;exp&gt; [<span class="hljs-keyword">or</span> ...]                     <span class="hljs-comment"># Returns first true or last operand.</span>
+</code></pre></div>
+
+<div><h3 id="walrusoperator">Walrus Operator</h3><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>[i <span class="hljs-keyword">for</span> a <span class="hljs-keyword">in</span> <span class="hljs-string">'0123'</span> <span class="hljs-keyword">if</span> (i := int(a)) &gt; <span class="hljs-number">0</span>]        <span class="hljs-comment"># Assigns to variable 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 a tuple's subclass.</span>
+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>
-</code></pre></div>
 
-<pre><code class="python language-python hljs"><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 enum.</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 Enum's subclass.</span>
 direction = Direction.N                             <span class="hljs-comment"># Returns its member.</span>
-</code></pre>
-<pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> dataclasses <span class="hljs-keyword">import</span> make_dataclass
+
+<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">'loc'</span>, <span class="hljs-string">'dir'</span>])   <span class="hljs-comment"># Creates a class.</span>
 player = Player(point, direction)                   <span class="hljs-comment"># Returns its instance.</span>
-</code></pre>
+</code></pre></div>
+
 <div><h2 id="imports"><a href="#imports" name="imports">#</a>Imports</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> &lt;module&gt;            <span class="hljs-comment"># Imports a built-in or '&lt;module&gt;.py'.</span>
 <span class="hljs-keyword">import</span> &lt;package&gt;           <span class="hljs-comment"># Imports a built-in or '&lt;package&gt;/__init__.py'.</span>
 <span class="hljs-keyword">import</span> &lt;package&gt;.&lt;module&gt;  <span class="hljs-comment"># Imports a built-in or '&lt;package&gt;/&lt;module&gt;.py'.</span>
@@ -2944,7 +2945,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 10, 2025</aside>
+    <aside>March 16, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 51a02ab01..c83b9d4f6 100755
--- a/parse.js
+++ b/parse.js
@@ -33,7 +33,7 @@ const TOC =
   '<pre style="border-left: none;padding-left: 1.9px;"><code class="hljs bash" style="line-height: 1.327em;"><strong>ToC</strong> = {\n' +
   '    <strong><span class="hljs-string">\'1. Collections\'</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>],\n' +
   '    <strong><span class="hljs-string">\'2. Types\'</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>],\n' +
-  '    <strong><span class="hljs-string">\'3. Syntax\'</span></strong>:      [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>],\n' +
+  '    <strong><span class="hljs-string">\'3. Syntax\'</span></strong>:      [<a href="#function">Function</a>, <a href="#inline">Inline</a>, <a href="#imports">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>],\n' +
   '    <strong><span class="hljs-string">\'4. System\'</span></strong>:      [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">Command_Line_Arguments</a>, <a href="#open">Open</a>, <a href="#paths">Path</a>, <a href="#oscommands">OS_Commands</a>],\n' +
   '    <strong><span class="hljs-string">\'5. Data\'</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>],\n' +
   '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],\n' +
@@ -55,6 +55,13 @@ const CACHE =
   '<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fib</span><span class="hljs-params">(n)</span>:</span>\n' +
   '    <span class="hljs-keyword">return</span> n <span class="hljs-keyword">if</span> n &lt; <span class="hljs-number">2</span> <span class="hljs-keyword">else</span> fib(n-<span class="hljs-number">2</span>) + fib(n-<span class="hljs-number">1</span>)';
 
+const SPLAT =
+  '<span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span><span class="hljs-params">(*a)</span>:</span>\n' +
+  '<span class="hljs-meta">... </span>    <span class="hljs-keyword">return</span> sum(a)\n' +
+  '<span class="hljs-meta">... </span>\n' +
+  '<span class="hljs-meta">&gt;&gt;&gt; </span>add(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>)\n' +
+  '<span class="hljs-number">6</span>\n';
+
 const PARAMETRIZED_DECORATOR =
   '<span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps\n' +
   '\n' +
@@ -416,6 +423,19 @@ const DIAGRAM_5_A =
   "|              |  {<float>:.2}  |  {<float>:.2f} |  {<float>:.2e} |  {<float>:.2%} |\n" +
   "+--------------+----------------+----------------+----------------+----------------+\n";
 
+const DIAGRAM_55_A =
+  "+--------------------+------------+--------------+----------------+------------------+\n";
+
+const DIAGRAM_55_B =
+  '┏━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━┓\n' +
+  '┃                    │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) ┃\n' +
+  '┠────────────────────┼────────────┼──────────────┼────────────────┼──────────────────┨\n' +
+  '┃ <span class="hljs-title">f</span>(x, *args, **kw): │      ✓     │      ✓       │        ✓       │        ✓         ┃\n' +
+  '┃ <span class="hljs-title">f</span>(*args, z, **kw): │            │      ✓       │        ✓       │        ✓         ┃\n' +
+  '┃ <span class="hljs-title">f</span>(x, **kw):        │            │              │        ✓       │        ✓         ┃\n' +
+  '┃ <span class="hljs-title">f</span>(*, x, **kw):     │            │              │                │        ✓         ┃\n' +
+  '┗━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┛\n';
+
 const DIAGRAM_6_A =
   '+------------+------------+------------+------------+--------------+\n' +
   '|            |  Iterable  | Collection |  Sequence  | abc.Sequence |\n' +
@@ -690,7 +710,6 @@ const DIAGRAM_15_B =
   "┃                       │ c  .  .  6  7 │            │            │ treated as a column.      ┃\n" +
   "┗━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n";
 
-
 const DIAGRAM_16_A =
   '| df.apply(…)     |      x  4     |        x  y   |     x  4      |';
 
@@ -854,6 +873,7 @@ function updateDiagrams() {
   $(`code:contains(${DIAGRAM_2_A})`).html(DIAGRAM_2_B);
   $(`code:contains(${DIAGRAM_4_A})`).html(DIAGRAM_4_B);
   $(`code:contains(${DIAGRAM_5_A})`).parent().remove();
+  $(`code:contains(${DIAGRAM_55_A})`).html(DIAGRAM_55_B);
   $(`code:contains(${DIAGRAM_6_A})`).html(DIAGRAM_6_B);
   $(`code:contains(${DIAGRAM_7_A})`).html(DIAGRAM_7_B);
   $(`code:contains(${DIAGRAM_8_A})`).html(DIAGRAM_8_B);
@@ -904,18 +924,18 @@ function fixClasses() {
 function fixHighlights() {
   $(`code:contains(<int> = ±0b<bin>)`).html(BIN_HEX);
   $(`code:contains( + fib(n)`).html(CACHE);
+  $(`code:contains(>>> def add)`).html(SPLAT);
   $(`code:contains(@debug(print_result=True))`).html(PARAMETRIZED_DECORATOR);
   $(`code:contains(print/str/repr([<obj>]))`).html(REPR_USE_CASES);
-  $(`code:contains((self, a=None):)`).html(CONSTRUCTOR_OVERLOADING);
   $(`code:contains(shutil.copy)`).html(SHUTIL_COPY);
   $(`code:contains(os.rename)`).html(OS_RENAME);
   $(`code:contains(\'<n>s\')`).html(STRUCT_FORMAT);
   $(`code:contains(match <object/expression>:)`).html(MATCH);
   $(`code:contains(>>> match Path)`).html(MATCH_EXAMPLE);
+  $(`code:contains(>>> log.basicConfig()`).html(LOGGING_EXAMPLE);
   $(`code:contains(import asyncio, collections, curses, curses.textpad, enum, random)`).html(COROUTINES);
-  $(`code:contains(import curses, os)`).html(CURSES);
   $(`code:contains(pip3 install tqdm)`).html(PROGRESS_BAR);
-  $(`code:contains(>>> log.basicConfig()`).html(LOGGING_EXAMPLE);
+  $(`code:contains(import curses, os)`).html(CURSES);
   $(`code:contains(a_float = max()`).html(AUDIO_1);
   $(`code:contains(samples_f = (sin(i *)`).html(AUDIO_2);
   $(`code:contains(collections, dataclasses, enum, io, itertools)`).html(MARIO);
diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html
index 735f3c206..5642d828a 100644
--- a/pdf/index_for_pdf.html
+++ b/pdf/index_for_pdf.html
@@ -7,7 +7,7 @@ <h3 id="a">A</h3>
 <p><strong>abstract base classes, <a href="#abstractbaseclasses">4</a>, <a href="#abcsequence">19</a></strong><br>
 <strong>animation, <a href="#animation">40</a>, <a href="#pygame">42</a>-<a href="#basicmariobrothersexample">43</a></strong><br>
 <strong>argparse module, <a href="#argumentparser">22</a></strong><br>
-<strong>arguments, <a href="#arguments">10</a>, <a href="#partial">12</a>, <a href="#commandlinearguments">22</a></strong><br>
+<strong>arguments, <a href="#function">10</a>, <a href="#partial">12</a>, <a href="#commandlinearguments">22</a></strong><br>
 <strong>arrays, <a href="#array">29</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a></strong><br>
 <strong>asyncio module, <a href="#coroutines">33</a></strong><br>
 <strong>audio, <a href="#audio">40</a>-<a href="#synthesizer">41</a>, <a href="#sound">42</a></strong>  </p>
@@ -34,11 +34,11 @@ <h3 id="c">C</h3>
 <strong>curses module, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a>, <a href="#consoleapp">34</a></strong><br>
 <strong>cython, <a href="#typeannotations">15</a>, <a href="#cython">49</a></strong>  </p>
 <h3 id="d">D</h3>
-<p><strong>dataclasses module, <a href="#namedtupleenumdataclass">12</a>, <a href="#dataclass">15</a></strong><br>
+<p><strong>dataclasses module, <a href="#namedtupleenumdataclass">11</a>, <a href="#dataclass">15</a></strong><br>
 <strong>datetime module, <a href="#datetime">8</a>-<a href="#now">9</a></strong><br>
 <strong>decorator, <a href="#decorator">13</a>, <a href="#class">14</a>, <a href="#dataclass">15</a>, <a href="#sortable">16</a></strong><br>
 <strong>deques, <a href="#deque">29</a></strong><br>
-<strong>dictionaries, <a href="#dictionary">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
+<strong>dictionaries, <a href="#dictionary">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">10</a>-<a href="#comprehensions">11</a>, <a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
 <strong>duck types, <a href="#ducktypes">16</a>-<a href="#abcsequence">19</a></strong>  </p>
 <h3 id="e">E</h3>
 <p><strong>enum module, <a href="#enum">19</a>-<a href="#inline-1">20</a></strong><br>
@@ -64,7 +64,7 @@ <h3 id="h">H</h3>
 <h3 id="i">I</h3>
 <p><strong>image, <a href="#scrapespythonsurlandlogofromitswikipediapage">35</a>, <a href="#image">39</a>-<a href="#animation">40</a>, <a href="#surface">42</a>-<a href="#basicmariobrothersexample">43</a></strong><br>
 <strong>imports, <a href="#imports">12</a></strong><br>
-<strong>inline, <a href="#otheruses">11</a>, <a href="#dataclass">15</a>, <a href="#inline-1">20</a></strong><br>
+<strong>inline, <a href="#inline">11</a>, <a href="#dataclass">15</a>, <a href="#inline-1">20</a></strong><br>
 <strong>input function, <a href="#input">22</a></strong><br>
 <strong>introspection,  <a href="#exceptionobject">21</a>, <a href="#introspection">31</a></strong><br>
 <strong>ints, <a href="#abstractbaseclasses">4</a>, <a href="#ints">7</a>-<a href="#random">8</a>, <a href="#encode-1">28</a></strong><br>
@@ -76,7 +76,7 @@ <h3 id="j">J</h3>
 <p><strong>json, <a href="#json">25</a>, <a href="#restrequest">36</a>, <a href="#fileformats">46</a></strong>  </p>
 <h3 id="l">L</h3>
 <p><strong>lambda, <a href="#lambda">11</a></strong><br>
-<strong>lists, <a href="#list">1</a>-<a href="#list">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
+<strong>lists, <a href="#list">1</a>-<a href="#list">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">10</a>-<a href="#comprehensions">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
 <strong>locale module, <a href="#sortable">16</a></strong><br>
 <strong>logging, <a href="#logging">31</a></strong>  </p>
 <h3 id="m">M</h3>
@@ -121,11 +121,11 @@ <h3 id="s">S</h3>
 <p><strong>scope, <a href="#insidefunctiondefinition">10</a>, <a href="#nonlocal">12</a>, <a href="#complexexample">20</a></strong><br>
 <strong>scraping, <a href="#scraping">35</a>, <a href="#basicmariobrothersexample">43</a>, <a href="#fileformats">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
 <strong>sequence, <a href="#abstractbaseclasses">4</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a></strong><br>
-<strong>sets, <a href="#set">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
+<strong>sets, <a href="#set">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">10</a>-<a href="#comprehensions">11</a>, <a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
 <strong>shell commands, <a href="#shellcommands">25</a></strong><br>
 <strong>sleep function, <a href="#progressbar">34</a></strong><br>
 <strong>sortable, <a href="#list">1</a>, <a href="#sortable">16</a></strong><br>
-<strong>splat operator, <a href="#splatoperator">10</a>-<a href="#otheruses">11</a>, <a href="#readrowsfromcsvfile">26</a></strong><br>
+<strong>splat operator, <a href="#splatoperator">10</a>, <a href="#readrowsfromcsvfile">26</a></strong><br>
 <strong>sql, <a href="#sqlite">27</a>, <a href="#fileformats">46</a></strong><br>
 <strong>statistics, <a href="#statistics">7</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#pandas">44</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
 <strong>strings, <a href="#abstractbaseclasses">4</a>-<a href="#comparisonofpresentationtypes">7</a>, <a href="#class">14</a></strong><br>
@@ -138,7 +138,7 @@ <h3 id="t">T</h3>
 <strong>template, <a href="#format">6</a>, <a href="#dynamicrequest">36</a></strong><br>
 <strong>threading module, <a href="#threading">32</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong><br>
 <strong>time module, <a href="#progressbar">34</a>, <a href="#profiling">36</a></strong><br>
-<strong>tuples, <a href="#tuple">3</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a></strong><br>
+<strong>tuples, <a href="#tuple">3</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">10</a>-<a href="#comprehensions">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a></strong><br>
 <strong>type, <a href="#type">4</a>, <a href="#ducktypes">16</a>, <a href="#matchstatement">30</a></strong><br>
 <strong>type annotations, <a href="#typeannotations">15</a>, <a href="#introspection">31</a></strong>  </p>
 <h3 id="w">W</h3>
diff --git a/pdf/index_for_pdf_print.html b/pdf/index_for_pdf_print.html
index 5c20dd81a..a27f6764e 100644
--- a/pdf/index_for_pdf_print.html
+++ b/pdf/index_for_pdf_print.html
@@ -34,11 +34,11 @@ <h3 id="c">C</h3>
 <strong>curses module, 33, 34</strong><br>
 <strong>cython, 15, 49</strong>  </p>
 <h3 id="d">D</h3>
-<p><strong>dataclasses module, 12, 15</strong><br>
+<p><strong>dataclasses module, 11, 15</strong><br>
 <strong>datetime module, 8-9</strong><br>
 <strong>decorator, 13, 14, 15, 16</strong><br>
 <strong>deques, 29</strong><br>
-<strong>dictionaries, 2, 4, 11, 19, 21</strong><br>
+<strong>dictionaries, 2, 4, 10-11, 19, 21</strong><br>
 <strong>duck types, 16-19</strong>  </p>
 <h3 id="e">E</h3>
 <p><strong>enum module, 19-20</strong><br>
@@ -76,7 +76,7 @@ <h3 id="j">J</h3>
 <p><strong>json, 25, 36, 46</strong>  </p>
 <h3 id="l">L</h3>
 <p><strong>lambda, 11</strong><br>
-<strong>lists, 1-2, 4, 11, 18-19, 21</strong><br>
+<strong>lists, 1-2, 4, 10-11, 18-19, 21</strong><br>
 <strong>locale module, 16</strong><br>
 <strong>logging, 31</strong>  </p>
 <h3 id="m">M</h3>
@@ -121,11 +121,11 @@ <h3 id="s">S</h3>
 <p><strong>scope, 10, 12, 20</strong><br>
 <strong>scraping, 35, 43, 46, 47-48</strong><br>
 <strong>sequence, 4, 18-19</strong><br>
-<strong>sets, 2, 4, 11, 19, 21</strong><br>
+<strong>sets, 2, 4, 10-11, 19, 21</strong><br>
 <strong>shell commands, 25</strong><br>
 <strong>sleep function, 34</strong><br>
 <strong>sortable, 1, 16</strong><br>
-<strong>splat operator, 10-11, 26</strong><br>
+<strong>splat operator, 10, 26</strong><br>
 <strong>sql, 27, 46</strong><br>
 <strong>statistics, 7, 37-38, 44-48</strong><br>
 <strong>strings, 4-7, 14</strong><br>
@@ -138,7 +138,7 @@ <h3 id="t">T</h3>
 <strong>template, 6, 36</strong><br>
 <strong>threading module, 32, 36</strong><br>
 <strong>time module, 34, 36</strong><br>
-<strong>tuples, 3, 4, 11, 18-19</strong><br>
+<strong>tuples, 3, 4, 10-11, 18-19</strong><br>
 <strong>type, 4, 16, 30</strong><br>
 <strong>type annotations, 15, 31</strong>  </p>
 <h3 id="w">W</h3>
diff --git a/web/script_2.js b/web/script_2.js
index 12ff725a2..d0a46acb3 100644
--- a/web/script_2.js
+++ b/web/script_2.js
@@ -2,7 +2,7 @@ const TOC =
   '<strong>ToC</strong> = {\n' +
   '    <strong><span class="hljs-string">\'1. Collections\'</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>],\n' +
   '    <strong><span class="hljs-string">\'2. Types\'</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>],\n' +
-  '    <strong><span class="hljs-string">\'3. Syntax\'</span></strong>:      [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>],\n' +
+  '    <strong><span class="hljs-string">\'3. Syntax\'</span></strong>:      [<a href="#function">Function</a>, <a href="#inline">Inline</a>, <a href="#imports">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>],\n' +
   '    <strong><span class="hljs-string">\'4. System\'</span></strong>:      [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">Command_Line_Arguments</a>, <a href="#open">Open</a>, <a href="#paths">Path</a>, <a href="#oscommands">OS_Commands</a>],\n' +
   '    <strong><span class="hljs-string">\'5. Data\'</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>],\n' +
   '    <strong><span class="hljs-string">\'6. Advanced\'</span></strong>:    [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],\n' +
@@ -18,7 +18,7 @@ const TOC_MOBILE =
   '    <strong><span class="hljs-string">\'2. Types\'</span></strong>:       [<a href="#type">Type</a>, <a href="#string">String</a>, <a href="#regex">Regular_Exp</a>,\n' +
   '                       <a href="#format">Format</a>, <a href="#numbers">Numbers</a>,\n' +
   '                       <a href="#combinatorics">Combinatorics</a>, <a href="#datetime">Datetime</a>],\n' +
-  '    <strong><span class="hljs-string">\'3. Syntax\'</span></strong>:      [<a href="#arguments">Arguments</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>,\n' +
+  '    <strong><span class="hljs-string">\'3. Syntax\'</span></strong>:      [<a href="#function">Function</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>,\n' +
   '                       <a href="#decorator">Decorator</a>, <a href="#class">Class</a>,\n' +
   '                       <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Except</a>],\n' +
   '    <strong><span class="hljs-string">\'4. System\'</span></strong>:      [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>,\n' +

From 86d395e3c2399f998384aac149d28746cadad0b4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 16 Mar 2025 16:37:39 +0100
Subject: [PATCH 109/186] Removed highlights from splat table

---
 README.md  | 2 +-
 index.html | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 2e3342eaf..eb47db966 100644
--- a/README.md
+++ b/README.md
@@ -716,7 +716,7 @@ func(1, 2, z=3)
 ```
 
 #### Allowed compositions of arguments inside function definition and the ways they can be called:
-```python
+```text
 +--------------------+------------+--------------+----------------+------------------+
 |                    | f(1, 2, 3) | f(1, 2, z=3) | f(1, y=2, z=3) | f(x=1, y=2, z=3) |
 +--------------------+------------+--------------+----------------+------------------+
diff --git a/index.html b/index.html
index a0dbf7797..f280ede9e 100644
--- a/index.html
+++ b/index.html
@@ -630,8 +630,8 @@
 </code></pre></div>
 
 
-<div><h4 id="allowedcompositionsofargumentsinsidefunctiondefinitionandthewaystheycanbecalled">Allowed compositions of arguments inside function definition and the ways they can be called:</h4><pre><code class="python language-python hljs">┏━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━┓
-┃                    │ f(<span class="hljs-number"><span class="hljs-number">1</span></span>, <span class="hljs-number"><span class="hljs-number">2</span></span>, <span class="hljs-number"><span class="hljs-number">3</span></span>) │ f(<span class="hljs-number"><span class="hljs-number">1</span></span>, <span class="hljs-number"><span class="hljs-number">2</span></span>, z=<span class="hljs-number"><span class="hljs-number">3</span></span>) │ f(<span class="hljs-number"><span class="hljs-number">1</span></span>, y=<span class="hljs-number"><span class="hljs-number">2</span></span>, z=<span class="hljs-number"><span class="hljs-number">3</span></span>) │ f(x=<span class="hljs-number"><span class="hljs-number">1</span></span>, y=<span class="hljs-number"><span class="hljs-number">2</span></span>, z=<span class="hljs-number"><span class="hljs-number">3</span></span>) ┃
+<div><h4 id="allowedcompositionsofargumentsinsidefunctiondefinitionandthewaystheycanbecalled">Allowed compositions of arguments inside function definition and the ways they can be called:</h4><pre><code class="text language-text">┏━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━┓
+┃                    │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) ┃
 ┠────────────────────┼────────────┼──────────────┼────────────────┼──────────────────┨
 ┃ <span class="hljs-title">f</span>(x, *args, **kw): │      ✓     │      ✓       │        ✓       │        ✓         ┃
 ┃ <span class="hljs-title">f</span>(*args, z, **kw): │            │      ✓       │        ✓       │        ✓         ┃

From 0c960cb5d4ffd50b4b7209b49a4e4dc84c80af41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 16 Mar 2025 17:00:20 +0100
Subject: [PATCH 110/186] Index

---
 pdf/index_for_pdf.html       | 2 +-
 pdf/index_for_pdf_print.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html
index 5642d828a..cb62ed1c3 100644
--- a/pdf/index_for_pdf.html
+++ b/pdf/index_for_pdf.html
@@ -56,7 +56,7 @@ <h3 id="f">F</h3>
 <h3 id="g">G</h3>
 <p><strong>games, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a>, <a href="#pygame">42</a>-<a href="#basicmariobrothersexample">43</a></strong><br>
 <strong>generators, <a href="#generator">4</a>, <a href="#comprehensions">11</a>, <a href="#iterator-1">17</a></strong><br>
-<strong>global keyword, <a href="#nonlocal">12</a></strong><br>
+<strong>global keyword, <a href="#function">10</a>, <a href="#nonlocal">12</a></strong><br>
 <strong>gui app, <a href="#guiapp">35</a></strong>  </p>
 <h3 id="h">H</h3>
 <p><strong>hashable, <a href="#dataclass">15</a>, <a href="#hashable">16</a></strong><br>
diff --git a/pdf/index_for_pdf_print.html b/pdf/index_for_pdf_print.html
index a27f6764e..5e9622832 100644
--- a/pdf/index_for_pdf_print.html
+++ b/pdf/index_for_pdf_print.html
@@ -56,7 +56,7 @@ <h3 id="f">F</h3>
 <h3 id="g">G</h3>
 <p><strong>games, 33, 42-43</strong><br>
 <strong>generators, 4, 11, 17</strong><br>
-<strong>global keyword, 12</strong><br>
+<strong>global keyword, 10, 12</strong><br>
 <strong>gui, 35</strong>  </p>
 <h3 id="h">H</h3>
 <p><strong>hashable, 15, 16</strong><br>

From 73c6f32135ac6432a299117fda1c13025ef74970 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 21 Mar 2025 13:40:24 +0100
Subject: [PATCH 111/186] Big changes in Numbers and Combinatorics

---
 README.md              | 57 +++++++++++++++++++++---------------------
 index.html             | 55 ++++++++++++++++++++--------------------
 parse.js               | 10 ++++----
 pdf/index_for_pdf.html |  4 +--
 4 files changed, 62 insertions(+), 64 deletions(-)

diff --git a/README.md b/README.md
index eb47db966..f7f64f1dd 100644
--- a/README.md
+++ b/README.md
@@ -500,10 +500,10 @@ Numbers
 <Fraction> = fractions.Fraction(0, 1)             # Or: Fraction(numerator=0, denominator=1)
 <Decimal>  = decimal.Decimal(<str/int>)           # Or: Decimal((sign, digits, exponent))
 ```
-* **`'int(<str>)'` and `'float(<str>)'` raise ValueError on malformed strings.**
-* **Decimal numbers are stored exactly, unlike most floats where `'1.1 + 2.2 != 3.3'`.**
+* **Decimal numbers are stored exactly, unlike most floats where: `'1.1 + 2.2 != 3.3'`.**
 * **Floats can be compared with: `'math.isclose(<float>, <float>)'`.**
 * **Precision of decimal operations is set with: `'decimal.getcontext().prec = <int>'`.**
+* **Bools can be used anywhere ints can, because bool is a subclass of int: `'True + 1 == 2'`.**
 
 ### Basic Functions
 ```python
@@ -526,18 +526,23 @@ from statistics import mean, median, variance     # Also: stdev, quantiles, grou
 
 ### Random
 ```python
-from random import random, randint, choice        # Also: shuffle, gauss, triangular, seed.
-<float> = random()                                # A float inside [0, 1).
-<int>   = randint(from_inc, to_inc)               # An int inside [from_inc, to_inc].
-<el>    = choice(<sequence>)                      # Keeps the sequence intact.
+from random import random, randint, uniform       # Also: gauss, choice, shuffle, seed.
 ```
 
-### Bin, Hex
 ```python
-<int> = ±0b<bin>                                  # Or: ±0x<hex>
-<int> = int('±<bin>', 2)                          # Or: int('±<hex>', 16)
-<int> = int('±0b<bin>', 0)                        # Or: int('±0x<hex>', 0)
-<str> = bin(<int>)                                # Returns '[-]0b<bin>'. Also hex().
+<float> = random()                                # Returns a float inside [0, 1).
+<num>   = randint/uniform(a, b)                   # Returns an int/float inside [a, b].
+<float> = gauss(mean, stdev)                      # Also triangular(low, high, mode).
+<el>    = choice(<sequence>)                      # Keeps it intact. Also sample(pop, k).
+shuffle(<list>)                                   # Shuffles the list in place.
+```
+
+### Hexadecimal Numbers
+```python
+<int> = ±0x<hex>                                  # Or: ±0b<bin>
+<int> = int('±<hex>', 16)                         # Or: int('±<bin>', 2)
+<int> = int('±0x<hex>', 0)                        # Or: int('±0b<bin>', 0)
+<str> = hex(<int>)                                # Returns '[-]0x<hex>'. Also bin().
 ```
 
 ### Bitwise Operators
@@ -563,30 +568,24 @@ import itertools as it
 ```
 
 ```python
->>> list(it.product('abc', 'abc'))                    #   a  b  c
-[('a', 'a'), ('a', 'b'), ('a', 'c'),                  # a x  x  x
- ('b', 'a'), ('b', 'b'), ('b', 'c'),                  # b x  x  x
- ('c', 'a'), ('c', 'b'), ('c', 'c')]                  # c x  x  x
-```
-
-```python
->>> list(it.combinations('abc', 2))                   #   a  b  c
-[('a', 'b'), ('a', 'c'),                              # a .  x  x
- ('b', 'c')]                                          # b .  .  x
+>>> list(it.product('abc', 'abc'))                #   a  b  c
+[('a', 'a'), ('a', 'b'), ('a', 'c'),              # a x  x  x
+ ('b', 'a'), ('b', 'b'), ('b', 'c'),              # b x  x  x
+ ('c', 'a'), ('c', 'b'), ('c', 'c')]              # c x  x  x
 ```
 
 ```python
->>> list(it.combinations_with_replacement('abc', 2))  #   a  b  c
-[('a', 'a'), ('a', 'b'), ('a', 'c'),                  # a x  x  x
- ('b', 'b'), ('b', 'c'),                              # b .  x  x
- ('c', 'c')]                                          # c .  .  x
+>>> list(it.permutations('abc', 2))               #   a  b  c
+[('a', 'b'), ('a', 'c'),                          # a .  x  x
+ ('b', 'a'), ('b', 'c'),                          # b x  .  x
+ ('c', 'a'), ('c', 'b')]                          # c x  x  .
 ```
 
 ```python
->>> list(it.permutations('abc', 2))                   #   a  b  c
-[('a', 'b'), ('a', 'c'),                              # a .  x  x
- ('b', 'a'), ('b', 'c'),                              # b x  .  x
- ('c', 'a'), ('c', 'b')]                              # c x  x  .
+>>> list(it.combinations('abc', 2))               #   a  b  c
+[('a', 'b'), ('a', 'c'),                          # a .  x  x
+ ('b', 'c'),                                      # b .  .  x
+]                                                 # c .  .  .
 ```
 
 
diff --git a/index.html b/index.html
index f280ede9e..9d17abdd1 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 16, 2025</aside>
+    <aside>March 21, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -463,10 +463,10 @@
 </code></pre></div>
 
 <ul>
-<li><strong><code class="python hljs"><span class="hljs-string">'int(&lt;str&gt;)'</span></code> and <code class="python hljs"><span class="hljs-string">'float(&lt;str&gt;)'</span></code> raise ValueError on malformed strings.</strong></li>
-<li><strong>Decimal numbers are stored 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>Decimal numbers are stored 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(&lt;float&gt;, &lt;float&gt;)'</span></code>.</strong></li>
 <li><strong>Precision of decimal operations is set with: <code class="python hljs"><span class="hljs-string">'decimal.getcontext().prec = &lt;int&gt;'</span></code>.</strong></li>
+<li><strong>Bools can be used anywhere ints can, because 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="basicfunctions">Basic Functions</h3><pre><code class="python language-python hljs">&lt;num&gt; = pow(&lt;num&gt;, &lt;num&gt;)                         <span class="hljs-comment"># Or: &lt;number&gt; ** &lt;number&gt;</span>
 &lt;num&gt; = abs(&lt;num&gt;)                                <span class="hljs-comment"># &lt;float&gt; = abs(&lt;complex&gt;)</span>
@@ -481,16 +481,19 @@
 <div><h3 id="statistics">Statistics</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> statistics <span class="hljs-keyword">import</span> mean, median, variance     <span class="hljs-comment"># Also: stdev, quantiles, groupby.</span>
 </code></pre></div>
 
-<div><h3 id="random">Random</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> random, randint, choice        <span class="hljs-comment"># Also: shuffle, gauss, triangular, seed.</span>
-&lt;float&gt; = random()                                <span class="hljs-comment"># A float inside [0, 1).</span>
-&lt;int&gt;   = randint(from_inc, to_inc)               <span class="hljs-comment"># An int inside [from_inc, to_inc].</span>
-&lt;el&gt;    = choice(&lt;sequence&gt;)                      <span class="hljs-comment"># Keeps the sequence intact.</span>
+<div><h3 id="random">Random</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> random, randint, uniform       <span class="hljs-comment"># Also: gauss, choice, shuffle, seed.</span>
 </code></pre></div>
 
-<div><h3 id="binhex">Bin, Hex</h3><pre><code class="python language-python hljs">&lt;int&gt; = ±<span class="hljs-number">0b</span>&lt;bin&gt;                                  <span class="hljs-comment"># Or: ±0x&lt;hex&gt;</span>
-&lt;int&gt; = int(<span class="hljs-string">'±&lt;bin&gt;'</span>, <span class="hljs-number">2</span>)                          <span class="hljs-comment"># Or: int('±&lt;hex&gt;', 16)</span>
-&lt;int&gt; = int(<span class="hljs-string">'±0b&lt;bin&gt;'</span>, <span class="hljs-number">0</span>)                        <span class="hljs-comment"># Or: int('±0x&lt;hex&gt;', 0)</span>
-&lt;str&gt; = bin(&lt;int&gt;)                                <span class="hljs-comment"># Returns '[-]0b&lt;bin&gt;'. Also hex().</span>
+<pre><code class="python language-python hljs">&lt;float&gt; = random()                                <span class="hljs-comment"># Returns a float inside [0, 1).</span>
+&lt;num&gt;   = randint/uniform(a, b)                   <span class="hljs-comment"># Returns an int/float inside [a, b].</span>
+&lt;float&gt; = gauss(mean, stdev)                      <span class="hljs-comment"># Also triangular(low, high, mode).</span>
+&lt;el&gt;    = choice(&lt;sequence&gt;)                      <span class="hljs-comment"># Keeps it intact. Also sample(pop, k).</span>
+shuffle(&lt;list&gt;)                                   <span class="hljs-comment"># Shuffles the list in place.</span>
+</code></pre>
+<div><h3 id="hexadecimalnumbers">Hexadecimal Numbers</h3><pre><code class="python language-python hljs">&lt;int&gt; = ±<span class="hljs-number">0x</span>&lt;hex&gt;                                  <span class="hljs-comment"># Or: ±0b&lt;bin&gt;</span>
+&lt;int&gt; = int(<span class="hljs-string">'±&lt;hex&gt;'</span>, <span class="hljs-number">16</span>)                         <span class="hljs-comment"># Or: int('±&lt;bin&gt;', 2)</span>
+&lt;int&gt; = int(<span class="hljs-string">'±0x&lt;hex&gt;'</span>, <span class="hljs-number">0</span>)                        <span class="hljs-comment"># Or: int('±0b&lt;bin&gt;', 0)</span>
+&lt;str&gt; = hex(&lt;int&gt;)                                <span class="hljs-comment"># Returns '[-]0x&lt;hex&gt;'. Also bin().</span>
 </code></pre></div>
 
 <div><h3 id="bitwiseoperators">Bitwise Operators</h3><pre><code class="python language-python hljs">&lt;int&gt; = &lt;int&gt; &amp; &lt;int&gt;                             <span class="hljs-comment"># And (0b1100 &amp; 0b1010 == 0b1000).</span>
@@ -507,24 +510,20 @@
 [(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>), (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>), (<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>), (<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>),
  (<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>)]
 </code></pre>
-<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>list(it.product(<span class="hljs-string">'abc'</span>, <span class="hljs-string">'abc'</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">&gt;&gt;&gt; </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>
+<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>list(it.product(<span class="hljs-string">'abc'</span>, <span class="hljs-string">'abc'</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">&gt;&gt;&gt; </span>list(it.combinations_with_replacement(<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">'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">'b'</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">'c'</span>)]                                          <span class="hljs-comment"># c .  .  x</span>
+<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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>
+<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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>Provides 'date', 'time', 'datetime' and 'timedelta' classes. All are immutable and hashable.</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> date, time, datetime, timedelta, timezone
@@ -2945,7 +2944,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 16, 2025</aside>
+    <aside>March 21, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index c83b9d4f6..a2d74d516 100755
--- a/parse.js
+++ b/parse.js
@@ -43,10 +43,10 @@ const TOC =
   '</code></pre>\n';
 
 const BIN_HEX =
-  '&lt;int&gt; = ±<span class="hljs-number">0b</span>&lt;bin&gt;                                  <span class="hljs-comment"># Or: ±0x&lt;hex&gt;</span>\n' +
-  '&lt;int&gt; = int(<span class="hljs-string">\'±&lt;bin&gt;\'</span>, <span class="hljs-number">2</span>)                          <span class="hljs-comment"># Or: int(\'±&lt;hex&gt;\', 16)</span>\n' +
-  '&lt;int&gt; = int(<span class="hljs-string">\'±0b&lt;bin&gt;\'</span>, <span class="hljs-number">0</span>)                        <span class="hljs-comment"># Or: int(\'±0x&lt;hex&gt;\', 0)</span>\n' +
-  '&lt;str&gt; = bin(&lt;int&gt;)                                <span class="hljs-comment"># Returns \'[-]0b&lt;bin&gt;\'. Also hex().</span>\n';
+  '&lt;int&gt; = ±<span class="hljs-number">0x</span>&lt;hex&gt;                                  <span class="hljs-comment"># Or: ±0b&lt;bin&gt;</span>\n' +
+  '&lt;int&gt; = int(<span class="hljs-string">\'±&lt;hex&gt;\'</span>, <span class="hljs-number">16</span>)                         <span class="hljs-comment"># Or: int(\'±&lt;bin&gt;\', 2)</span>\n' +
+  '&lt;int&gt; = int(<span class="hljs-string">\'±0x&lt;hex&gt;\'</span>, <span class="hljs-number">0</span>)                        <span class="hljs-comment"># Or: int(\'±0b&lt;bin&gt;\', 0)</span>\n' +
+  '&lt;str&gt; = hex(&lt;int&gt;)                                <span class="hljs-comment"># Returns \'[-]0x&lt;hex&gt;\'. Also bin().</span>\n';
 
 const CACHE =
   '<span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> cache\n' +
@@ -922,7 +922,7 @@ function fixClasses() {
 }
 
 function fixHighlights() {
-  $(`code:contains(<int> = ±0b<bin>)`).html(BIN_HEX);
+  $(`code:contains(<int> = ±0x<hex>)`).html(BIN_HEX);
   $(`code:contains( + fib(n)`).html(CACHE);
   $(`code:contains(>>> def add)`).html(SPLAT);
   $(`code:contains(@debug(print_result=True))`).html(PARAMETRIZED_DECORATOR);
diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html
index cb62ed1c3..a4a44cc12 100644
--- a/pdf/index_for_pdf.html
+++ b/pdf/index_for_pdf.html
@@ -13,7 +13,7 @@ <h3 id="a">A</h3>
 <strong>audio, <a href="#audio">40</a>-<a href="#synthesizer">41</a>, <a href="#sound">42</a></strong>  </p>
 <h3 id="b">B</h3>
 <p><strong>beautifulsoup library, <a href="#scrapespythonsurlandlogofromitswikipediapage">35</a></strong><br>
-<strong>binary representation, <a href="#ints">7</a>, <a href="#binhex">8</a></strong><br>
+<strong>binary representation, <a href="#ints">7</a>, <a href="#hexadecimalnumbers">8</a></strong><br>
 <strong>bitwise operators, <a href="#bitwiseoperators">8</a>, <a href="#operator">30</a></strong><br>
 <strong>bytes, <a href="#open">22</a>-<a href="#modes">23</a>, <a href="#pickle">25</a>, <a href="#bytes">28</a>-<a href="#memoryview">29</a></strong>  </p>
 <h3 id="c">C</h3>
@@ -60,7 +60,7 @@ <h3 id="g">G</h3>
 <strong>gui app, <a href="#guiapp">35</a></strong>  </p>
 <h3 id="h">H</h3>
 <p><strong>hashable, <a href="#dataclass">15</a>, <a href="#hashable">16</a></strong><br>
-<strong>hexadecimal representation, <a href="#ints">7</a>, <a href="#binhex">8</a>, <a href="#encode-1">28</a></strong>  </p>
+<strong>hexadecimal representation, <a href="#ints">7</a>, <a href="#hexadecimalnumbers">8</a>, <a href="#encode-1">28</a></strong>  </p>
 <h3 id="i">I</h3>
 <p><strong>image, <a href="#scrapespythonsurlandlogofromitswikipediapage">35</a>, <a href="#image">39</a>-<a href="#animation">40</a>, <a href="#surface">42</a>-<a href="#basicmariobrothersexample">43</a></strong><br>
 <strong>imports, <a href="#imports">12</a></strong><br>

From 4248656a18ca267f74eb59b82dacfe7da392b3d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 25 Mar 2025 11:03:52 +0100
Subject: [PATCH 112/186] Synthesizer

---
 README.md  | 32 ++++++++++++++++----------------
 index.html | 36 ++++++++++++++++++------------------
 2 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/README.md b/README.md
index f7f64f1dd..d6c9813ac 100644
--- a/README.md
+++ b/README.md
@@ -2943,8 +2943,7 @@ write_to_wav_file('test.wav', samples_f, p=params)
 # $ pip3 install simpleaudio
 from simpleaudio import play_buffer
 with wave.open('test.wav') as file:
-    p = file.getparams()
-    frames = file.readframes(-1)
+    frames, p = file.readframes(-1), file.getparams()
     play_buffer(frames, p.nchannels, p.sampwidth, p.framerate).wait_done()
 ```
 
@@ -2963,20 +2962,21 @@ Synthesizer
 #### Plays Popcorn by Gershon Kingsley:
 ```python
 # $ pip3 install simpleaudio
-import array, itertools as it, math, simpleaudio
-
-F  = 44100
-P1 = '71♩,69♪,,71♩,66♪,,62♩,66♪,,59♩,,,71♩,69♪,,71♩,66♪,,62♩,66♪,,59♩,,,'
-P2 = '71♩,73♪,,74♩,73♪,,74♪,,71♪,,73♩,71♪,,73♪,,69♪,,71♩,69♪,,71♪,,67♪,,71♩,,,'
-get_pause   = lambda seconds: it.repeat(0, int(seconds * F))
-sin_f       = lambda i, hz: math.sin(i * 2 * math.pi * hz / F)
-get_wave    = lambda hz, seconds: (sin_f(i, hz) for i in range(int(seconds * F)))
-get_hz      = lambda note: 440 * 2 ** ((int(note[:2]) - 69) / 12)
-get_sec     = lambda note: 1/4 if '♩' in note else 1/8
-get_samples = lambda note: get_wave(get_hz(note), get_sec(note)) if note else get_pause(1/8)
-samples_f   = it.chain.from_iterable(get_samples(n) for n in (P1+P2).split(','))
-samples_i   = array.array('h', (int(f * 30000) for f in samples_f))
-simpleaudio.play_buffer(samples_i, 1, 2, F).wait_done()
+import itertools as it, math, array, simpleaudio
+
+def play_notes(notes, bpm=132, f=44100):
+    get_pause   = lambda n_beats: it.repeat(0, int(n_beats * 60/bpm * f))
+    sin_f       = lambda i, hz: math.sin(i * 2 * math.pi * hz / f)
+    get_wave    = lambda hz, n_beats: (sin_f(i, hz) for i in range(int(n_beats * 60/bpm * f)))
+    get_hz      = lambda note: 440 * 2 ** ((int(note[:2]) - 69) / 12)
+    get_nbeats  = lambda note: 1/2 if '♩' in note else 1/4 if '♪' in note else 1
+    get_samples = lambda n: get_wave(get_hz(n), get_nbeats(n)) if n else get_pause(1/4)
+    samples_f   = it.chain.from_iterable(get_samples(n) for n in notes.split(','))
+    samples_i   = array.array('h', (int(fl * 5000) for fl in samples_f))
+    simpleaudio.play_buffer(samples_i, 1, 2, f).wait_done()
+
+play_notes('83♩,81♪,,83♪,,78♪,,74♪,,78♪,,71♪,,,,83♪,,81♪,,83♪,,78♪,,74♪,,78♪,,71♪,,,,'
+           '83♩,85♪,,86♪,,85♪,,86♪,,83♪,,85♩,83♪,,85♪,,81♪,,83♪,,81♪,,83♪,,79♪,,83♪,,,,')
 ```
 
 
diff --git a/index.html b/index.html
index 9d17abdd1..ef3106dd3 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 21, 2025</aside>
+    <aside>March 25, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2415,8 +2415,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <div><h4 id="playsthewavfile">Plays the WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install simpleaudio</span>
 <span class="hljs-keyword">from</span> simpleaudio <span class="hljs-keyword">import</span> play_buffer
 <span class="hljs-keyword">with</span> wave.open(<span class="hljs-string">'test.wav'</span>) <span class="hljs-keyword">as</span> file:
-    p = file.getparams()
-    frames = file.readframes(<span class="hljs-number">-1</span>)
+    frames, p = file.readframes(<span class="hljs-number">-1</span>), file.getparams()
     play_buffer(frames, p.nchannels, p.sampwidth, p.framerate).wait_done()
 </code></pre></div>
 
@@ -2428,20 +2427,21 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </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 simpleaudio</span>
-<span class="hljs-keyword">import</span> array, itertools <span class="hljs-keyword">as</span> it, math, simpleaudio
-
-F  = <span class="hljs-number">44100</span>
-P1 = <span class="hljs-string">'71♩,69♪,,71♩,66♪,,62♩,66♪,,59♩,,,71♩,69♪,,71♩,66♪,,62♩,66♪,,59♩,,,'</span>
-P2 = <span class="hljs-string">'71♩,73♪,,74♩,73♪,,74♪,,71♪,,73♩,71♪,,73♪,,69♪,,71♩,69♪,,71♪,,67♪,,71♩,,,'</span>
-get_pause   = <span class="hljs-keyword">lambda</span> seconds: it.repeat(<span class="hljs-number">0</span>, int(seconds * F))
-sin_f       = <span class="hljs-keyword">lambda</span> i, hz: math.sin(i * <span class="hljs-number">2</span> * math.pi * hz / F)
-get_wave    = <span class="hljs-keyword">lambda</span> hz, seconds: (sin_f(i, hz) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(int(seconds * F)))
-get_hz      = <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_sec     = <span class="hljs-keyword">lambda</span> note: <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>/<span class="hljs-number">8</span>
-get_samples = <span class="hljs-keyword">lambda</span> note: get_wave(get_hz(note), get_sec(note)) <span class="hljs-keyword">if</span> note <span class="hljs-keyword">else</span> get_pause(<span class="hljs-number">1</span>/<span class="hljs-number">8</span>)
-samples_f   = it.chain.from_iterable(get_samples(n) <span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> (P1+P2).split(<span class="hljs-string">','</span>))
-samples_i   = array.array(<span class="hljs-string">'h'</span>, (int(f * <span class="hljs-number">30000</span>) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> samples_f))
-simpleaudio.play_buffer(samples_i, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, F).wait_done()
+<span class="hljs-keyword">import</span> itertools <span class="hljs-keyword">as</span> it, math, array, simpleaudio
+
+<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>, f=<span class="hljs-number">44100</span>)</span>:</span>
+    get_pause   = <span class="hljs-keyword">lambda</span> n_beats: it.repeat(<span class="hljs-number">0</span>, int(n_beats * <span class="hljs-number">60</span>/bpm * f))
+    sin_f       = <span class="hljs-keyword">lambda</span> i, hz: math.sin(i * <span class="hljs-number">2</span> * math.pi * hz / f)
+    get_wave    = <span class="hljs-keyword">lambda</span> hz, n_beats: (sin_f(i, hz) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(int(n_beats * <span class="hljs-number">60</span>/bpm * f)))
+    get_hz      = <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_nbeats  = <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_samples = <span class="hljs-keyword">lambda</span> n: get_wave(get_hz(n), get_nbeats(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.from_iterable(get_samples(n) <span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> notes.split(<span class="hljs-string">','</span>))
+    samples_i   = array.array(<span class="hljs-string">'h'</span>, (int(fl * <span class="hljs-number">5000</span>) <span class="hljs-keyword">for</span> fl <span class="hljs-keyword">in</span> samples_f))
+    simpleaudio.play_buffer(samples_i, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, f).wait_done()
+
+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>
 
 
@@ -2944,7 +2944,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 21, 2025</aside>
+    <aside>March 25, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From ec710626a9b61693a44e333518fee2703c46f8b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 25 Mar 2025 11:06:22 +0100
Subject: [PATCH 113/186] Pygame

---
 README.md  | 2 +-
 index.html | 2 +-
 parse.js   | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index d6c9813ac..ea4105cc5 100644
--- a/README.md
+++ b/README.md
@@ -3124,7 +3124,7 @@ def draw(screen, images, mario, tiles):
     screen.fill((85, 168, 255))
     mario.facing_left = mario.spd.x < 0 if mario.spd.x else mario.facing_left
     is_airborne = D.s not in get_boundaries(mario.rect, tiles)
-    image_index = 4 if is_airborne else (next(mario.frame_cycle) if mario.spd.x else 6)
+    image_index = 4 if is_airborne else next(mario.frame_cycle) if mario.spd.x else 6
     screen.blit(images[image_index + (mario.facing_left * 9)], mario.rect)
     for t in tiles:
         is_border = t.x in [0, (W-1)*16] or t.y in [0, (H-1)*16]
diff --git a/index.html b/index.html
index ef3106dd3..04a972ccf 100644
--- a/index.html
+++ b/index.html
@@ -2568,7 +2568,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     screen.fill((<span class="hljs-number">85</span>, <span class="hljs-number">168</span>, <span class="hljs-number">255</span>))
     mario.facing_left = mario.spd.x &lt; <span class="hljs-number">0</span> <span class="hljs-keyword">if</span> mario.spd.x <span class="hljs-keyword">else</span> mario.facing_left
     is_airborne = D.s <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> get_boundaries(mario.rect, tiles)
-    image_index = <span class="hljs-number">4</span> <span class="hljs-keyword">if</span> is_airborne <span class="hljs-keyword">else</span> (next(mario.frame_cycle) <span class="hljs-keyword">if</span> mario.spd.x <span class="hljs-keyword">else</span> <span class="hljs-number">6</span>)
+    image_index = <span class="hljs-number">4</span> <span class="hljs-keyword">if</span> is_airborne <span class="hljs-keyword">else</span> next(mario.frame_cycle) <span class="hljs-keyword">if</span> mario.spd.x <span class="hljs-keyword">else</span> <span class="hljs-number">6</span>
     screen.blit(images[image_index + (mario.facing_left * <span class="hljs-number">9</span>)], mario.rect)
     <span class="hljs-keyword">for</span> t <span class="hljs-keyword">in</span> tiles:
         is_border = t.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> t.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>]
diff --git a/parse.js b/parse.js
index a2d74d516..aebd7e9f3 100755
--- a/parse.js
+++ b/parse.js
@@ -302,7 +302,7 @@ const MARIO =
   '    screen.fill((<span class="hljs-number">85</span>, <span class="hljs-number">168</span>, <span class="hljs-number">255</span>))\n' +
   '    mario.facing_left = mario.spd.x &lt; <span class="hljs-number">0</span> <span class="hljs-keyword">if</span> mario.spd.x <span class="hljs-keyword">else</span> mario.facing_left\n' +
   '    is_airborne = D.s <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> get_boundaries(mario.rect, tiles)\n' +
-  '    image_index = <span class="hljs-number">4</span> <span class="hljs-keyword">if</span> is_airborne <span class="hljs-keyword">else</span> (next(mario.frame_cycle) <span class="hljs-keyword">if</span> mario.spd.x <span class="hljs-keyword">else</span> <span class="hljs-number">6</span>)\n' +
+  '    image_index = <span class="hljs-number">4</span> <span class="hljs-keyword">if</span> is_airborne <span class="hljs-keyword">else</span> next(mario.frame_cycle) <span class="hljs-keyword">if</span> mario.spd.x <span class="hljs-keyword">else</span> <span class="hljs-number">6</span>\n' +
   '    screen.blit(images[image_index + (mario.facing_left * <span class="hljs-number">9</span>)], mario.rect)\n' +
   '    <span class="hljs-keyword">for</span> t <span class="hljs-keyword">in</span> tiles:\n' +
   '        is_border = t.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> t.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>]\n' +

From 2c32601e15d41200d4961264e57197873e74742c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 27 Mar 2025 18:52:03 +0100
Subject: [PATCH 114/186] Splat operator

---
 README.md  |  8 ++++----
 index.html | 12 ++++++------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index ea4105cc5..07a6db398 100644
--- a/README.md
+++ b/README.md
@@ -728,10 +728,10 @@ func(1, 2, z=3)
 
 ### Other Uses
 ```python
-<list>  = [*<collection> [, ...]]  # Or: list(<collection>) [+ ...]
-<tuple> = (*<collection>, [...])   # Or: tuple(<collection>) [+ ...]
-<set>   = {*<collection> [, ...]}  # Or: set(<collection>) [| ...]
-<dict>  = {**<dict> [, ...]}       # Or: <dict> | ...
+<list>  = [*<collection> [, ...]]  # Or: list(<coll>) [+ ...]
+<tuple> = (*<collection>, [...])   # Or: tuple(<coll>) [+ ...]
+<set>   = {*<collection> [, ...]}  # Or: set(<coll>) [| ...]
+<dict>  = {**<dict>, ...}          # Or: <dict> | ...
 ```
 
 ```python
diff --git a/index.html b/index.html
index 04a972ccf..1a645fbbc 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 25, 2025</aside>
+    <aside>March 27, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -639,10 +639,10 @@
 ┗━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┛
 </code></pre></div>
 
-<div><h3 id="otheruses">Other Uses</h3><pre><code class="python language-python hljs">&lt;list&gt;  = [*&lt;collection&gt; [, ...]]  <span class="hljs-comment"># Or: list(&lt;collection&gt;) [+ ...]</span>
-&lt;tuple&gt; = (*&lt;collection&gt;, [...])   <span class="hljs-comment"># Or: tuple(&lt;collection&gt;) [+ ...]</span>
-&lt;set&gt;   = {*&lt;collection&gt; [, ...]}  <span class="hljs-comment"># Or: set(&lt;collection&gt;) [| ...]</span>
-&lt;dict&gt;  = {**&lt;dict&gt; [, ...]}       <span class="hljs-comment"># Or: &lt;dict&gt; | ...</span>
+<div><h3 id="otheruses">Other Uses</h3><pre><code class="python language-python hljs">&lt;list&gt;  = [*&lt;collection&gt; [, ...]]  <span class="hljs-comment"># Or: list(&lt;coll&gt;) [+ ...]</span>
+&lt;tuple&gt; = (*&lt;collection&gt;, [...])   <span class="hljs-comment"># Or: tuple(&lt;coll&gt;) [+ ...]</span>
+&lt;set&gt;   = {*&lt;collection&gt; [, ...]}  <span class="hljs-comment"># Or: set(&lt;coll&gt;) [| ...]</span>
+&lt;dict&gt;  = {**&lt;dict&gt;, ...}          <span class="hljs-comment"># Or: &lt;dict&gt; | ...</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs">head, *body, tail = &lt;collection&gt;   <span class="hljs-comment"># Head or tail can be omitted.</span>
@@ -2944,7 +2944,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 25, 2025</aside>
+    <aside>March 27, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 9785ab97cf1f043ce8630378df68a4d5bee0fdec Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 27 Mar 2025 18:54:59 +0100
Subject: [PATCH 115/186] Splat operator

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 07a6db398..5389f3274 100644
--- a/README.md
+++ b/README.md
@@ -731,7 +731,7 @@ func(1, 2, z=3)
 <list>  = [*<collection> [, ...]]  # Or: list(<coll>) [+ ...]
 <tuple> = (*<collection>, [...])   # Or: tuple(<coll>) [+ ...]
 <set>   = {*<collection> [, ...]}  # Or: set(<coll>) [| ...]
-<dict>  = {**<dict>, ...}          # Or: <dict> | ...
+<dict>  = {**<dict> [, ...]}       # Or: <dict> | ...
 ```
 
 ```python
diff --git a/index.html b/index.html
index 1a645fbbc..301730715 100644
--- a/index.html
+++ b/index.html
@@ -642,7 +642,7 @@
 <div><h3 id="otheruses">Other Uses</h3><pre><code class="python language-python hljs">&lt;list&gt;  = [*&lt;collection&gt; [, ...]]  <span class="hljs-comment"># Or: list(&lt;coll&gt;) [+ ...]</span>
 &lt;tuple&gt; = (*&lt;collection&gt;, [...])   <span class="hljs-comment"># Or: tuple(&lt;coll&gt;) [+ ...]</span>
 &lt;set&gt;   = {*&lt;collection&gt; [, ...]}  <span class="hljs-comment"># Or: set(&lt;coll&gt;) [| ...]</span>
-&lt;dict&gt;  = {**&lt;dict&gt;, ...}          <span class="hljs-comment"># Or: &lt;dict&gt; | ...</span>
+&lt;dict&gt;  = {**&lt;dict&gt; [, ...]}       <span class="hljs-comment"># Or: &lt;dict&gt; | ...</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs">head, *body, tail = &lt;collection&gt;   <span class="hljs-comment"># Head or tail can be omitted.</span>

From b87a82b76a7237c1b36458ae801bc335f8c0eaf1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 29 Mar 2025 11:47:47 +0100
Subject: [PATCH 116/186] Format

---
 README.md  | 4 ++--
 index.html | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 5389f3274..1cba26268 100644
--- a/README.md
+++ b/README.md
@@ -486,8 +486,8 @@ Format
 ### Ints
 ```python
 {90:c}                                   # 'Z'. Unicode character with value 90.
-{90:b}                                   # '1011010'. Number 90 in binary.
-{90:X}                                   # '5A'. Number 90 in uppercase hexadecimal.
+{90:b}                                   # '1011010'. Binary representation of the int.
+{90:X}                                   # '5A'. Hexadecimal with upper-case letters.
 ```
 
 
diff --git a/index.html b/index.html
index 301730715..db30be24b 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 27, 2025</aside>
+    <aside>March 29, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -451,8 +451,8 @@
 <li><strong>This 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>:c}                                   <span class="hljs-comment"># 'Z'. Unicode character with value 90.</span>
-{<span class="hljs-number">90</span>:b}                                   <span class="hljs-comment"># '1011010'. Number 90 in binary.</span>
-{<span class="hljs-number">90</span>:X}                                   <span class="hljs-comment"># '5A'. Number 90 in uppercase hexadecimal.</span>
+{<span class="hljs-number">90</span>:b}                                   <span class="hljs-comment"># '1011010'. Binary representation of the int.</span>
+{<span class="hljs-number">90</span>:X}                                   <span class="hljs-comment"># '5A'. Hexadecimal with upper-case letters.</span>
 </code></pre></div>
 
 <div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs">&lt;int&gt;      = int(&lt;float/str/bool&gt;)                <span class="hljs-comment"># Or: math.trunc(&lt;float&gt;)</span>
@@ -2944,7 +2944,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 27, 2025</aside>
+    <aside>March 29, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 8591e89bd9d3abc23241a0b81ebb67cfcf55de39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 29 Mar 2025 12:40:37 +0100
Subject: [PATCH 117/186] Splat table

---
 README.md  | 4 ++--
 index.html | 4 ++--
 parse.js   | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 1cba26268..7fed96112 100644
--- a/README.md
+++ b/README.md
@@ -719,8 +719,8 @@ func(1, 2, z=3)
 +--------------------+------------+--------------+----------------+------------------+
 |                    | f(1, 2, 3) | f(1, 2, z=3) | f(1, y=2, z=3) | f(x=1, y=2, z=3) |
 +--------------------+------------+--------------+----------------+------------------+
-| f(x, *args, **kw): |     yes    |     yes      |       yes      |       yes        |
-| f(*args, z, **kw): |            |     yes      |       yes      |       yes        |
+| f(x, *args, **kw): |     yes    |      yes     |       yes      |       yes        |
+| f(*args, z, **kw): |            |      yes     |       yes      |       yes        |
 | f(x, **kw):        |            |              |       yes      |       yes        |
 | f(*, x, **kw):     |            |              |                |       yes        |
 +--------------------+------------+--------------+----------------+------------------+
diff --git a/index.html b/index.html
index db30be24b..6fa12a241 100644
--- a/index.html
+++ b/index.html
@@ -632,8 +632,8 @@
 <div><h4 id="allowedcompositionsofargumentsinsidefunctiondefinitionandthewaystheycanbecalled">Allowed compositions of arguments inside function definition and the ways they can be called:</h4><pre><code class="text language-text">┏━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━┓
 ┃                    │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) ┃
 ┠────────────────────┼────────────┼──────────────┼────────────────┼──────────────────┨
-┃ <span class="hljs-title">f</span>(x, *args, **kw): │      ✓     │      ✓       │        ✓       │        ✓         ┃
-┃ <span class="hljs-title">f</span>(*args, z, **kw): │            │      ✓       │        ✓       │        ✓         ┃
+┃ <span class="hljs-title">f</span>(x, *args, **kw): │      ✓     │       ✓      │        ✓       │        ✓         ┃
+┃ <span class="hljs-title">f</span>(*args, z, **kw): │            │       ✓      │        ✓       │        ✓         ┃
 ┃ <span class="hljs-title">f</span>(x, **kw):        │            │              │        ✓       │        ✓         ┃
 ┃ <span class="hljs-title">f</span>(*, x, **kw):     │            │              │                │        ✓         ┃
 ┗━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┛
diff --git a/parse.js b/parse.js
index aebd7e9f3..f238de42d 100755
--- a/parse.js
+++ b/parse.js
@@ -430,8 +430,8 @@ const DIAGRAM_55_B =
   '┏━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━┓\n' +
   '┃                    │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) ┃\n' +
   '┠────────────────────┼────────────┼──────────────┼────────────────┼──────────────────┨\n' +
-  '┃ <span class="hljs-title">f</span>(x, *args, **kw): │      ✓     │      ✓       │        ✓       │        ✓         ┃\n' +
-  '┃ <span class="hljs-title">f</span>(*args, z, **kw): │            │      ✓       │        ✓       │        ✓         ┃\n' +
+  '┃ <span class="hljs-title">f</span>(x, *args, **kw): │      ✓     │       ✓      │        ✓       │        ✓         ┃\n' +
+  '┃ <span class="hljs-title">f</span>(*args, z, **kw): │            │       ✓      │        ✓       │        ✓         ┃\n' +
   '┃ <span class="hljs-title">f</span>(x, **kw):        │            │              │        ✓       │        ✓         ┃\n' +
   '┃ <span class="hljs-title">f</span>(*, x, **kw):     │            │              │                │        ✓         ┃\n' +
   '┗━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┛\n';

From 0640e70c35223e93c6092a7aec406c7e712f1996 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 30 Mar 2025 20:19:16 +0200
Subject: [PATCH 118/186] Datetime, Pandas

---
 README.md  | 4 ++--
 index.html | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 7fed96112..6cdf782d6 100644
--- a/README.md
+++ b/README.md
@@ -632,7 +632,7 @@ import zoneinfo, dateutil.tz
 ### Encode
 ```python
 <D/T/DT> = D/T/DT.fromisoformat(<str>)      # Object from ISO string. Raises ValueError.
-<DT>     = DT.strptime(<str>, '<format>')   # Datetime from str, according to format.
+<DT>     = DT.strptime(<str>, '<format>')   # Datetime from custom string. See Format.
 <D/DTn>  = D/DT.fromordinal(<int>)          # D/DT from days since the Gregorian NYE 1.
 <DTn>    = DT.fromtimestamp(<float>)        # Local naive DT from seconds since the Epoch.
 <DTa>    = DT.fromtimestamp(<float>, <tz>)  # Aware datetime from seconds since the Epoch.
@@ -3349,7 +3349,7 @@ c  6  7
 <DF>   = pd.read_csv/excel(<path/url/file>)    # Also `header/index_col/dtype/usecols/…=<obj>`.
 <list> = pd.read_html(<path/url/file>)         # Raises ImportError if webpage has zero tables.
 <S/DF> = pd.read_parquet/feather/hdf(<path…>)  # Function read_hdf() accepts `key=<s/df_name>`.
-<DF>   = pd.read_sql('<table/query>', <conn>)  # Pass SQLite3/Alchemy connection (see #SQLite).
+<DF>   = pd.read_sql('<table/query>', <conn>)  # Pass SQLite3/Alchemy connection. See #SQLite.
 ```
 
 ```python
diff --git a/index.html b/index.html
index 6fa12a241..a3ca5c8dc 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 29, 2025</aside>
+    <aside>March 30, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -562,7 +562,7 @@
 <li><strong>To get ZoneInfo() to work on Windows run <code class="python hljs"><span class="hljs-string">'&gt; pip3 install tzdata'</span></code>.</strong></li>
 </ul>
 <div><h3 id="encode">Encode</h3><pre><code class="python language-python apache hljs">&lt;D/T/DT&gt; = D/T/DT.fromisoformat(&lt;str&gt;)      <span class="hljs-comment"># Object from ISO string. Raises ValueError.</span>
-&lt;DT&gt;     = DT.strptime(&lt;str&gt;, <span class="hljs-string">'&lt;format&gt;'</span>)   <span class="hljs-comment"># Datetime from str, according to format.</span>
+&lt;DT&gt;     = DT.strptime(&lt;str&gt;, <span class="hljs-string">'&lt;format&gt;'</span>)   <span class="hljs-comment"># Datetime from custom string. See Format.</span>
 &lt;D/DTn&gt;  = D/DT.fromordinal(&lt;int&gt;)          <span class="hljs-comment"># D/DT from days since the Gregorian NYE 1.</span>
 &lt;DTn&gt;    = DT.fromtimestamp(&lt;float&gt;)        <span class="hljs-comment"># Local naive DT from seconds since the Epoch.</span>
 &lt;DTa&gt;    = DT.fromtimestamp(&lt;float&gt;, &lt;tz&gt;)  <span class="hljs-comment"># Aware datetime from seconds since the Epoch.</span>
@@ -2744,7 +2744,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;DF&gt;   = pd.read_csv/excel(&lt;path/url/file&gt;)    <span class="hljs-comment"># Also `header/index_col/dtype/usecols/…=&lt;obj&gt;`.</span>
 &lt;list&gt; = pd.read_html(&lt;path/url/file&gt;)         <span class="hljs-comment"># Raises ImportError if webpage has zero tables.</span>
 &lt;S/DF&gt; = pd.read_parquet/feather/hdf(&lt;path…&gt;)  <span class="hljs-comment"># Function read_hdf() accepts `key=&lt;s/df_name&gt;`.</span>
-&lt;DF&gt;   = pd.read_sql(<span class="hljs-string">'&lt;table/query&gt;'</span>, &lt;conn&gt;)  <span class="hljs-comment"># Pass SQLite3/Alchemy connection (see #SQLite).</span>
+&lt;DF&gt;   = pd.read_sql(<span class="hljs-string">'&lt;table/query&gt;'</span>, &lt;conn&gt;)  <span class="hljs-comment"># Pass SQLite3/Alchemy connection. See #SQLite.</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs">&lt;DF&gt;.to_json/csv/html/parquet/latex(&lt;path&gt;)    <span class="hljs-comment"># Returns a string/bytes if path is omitted.</span>
@@ -2944,7 +2944,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 29, 2025</aside>
+    <aside>March 30, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 6a70b6a899c338cf4e09eaff1e8fb26c6d38b1b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 1 Apr 2025 00:15:02 +0200
Subject: [PATCH 119/186] Datetime, Function

---
 README.md  | 10 +++++-----
 index.html | 14 +++++++-------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
index 6cdf782d6..3a8f41a99 100644
--- a/README.md
+++ b/README.md
@@ -374,7 +374,7 @@ import re
 * **Argument `'flags=re.IGNORECASE'` can be used with all functions.**
 * **Argument `'flags=re.MULTILINE'` makes `'^'` and `'$'` match the start/end of each line.**
 * **Argument `'flags=re.DOTALL'` makes `'.'` also accept the `'\n'`.**
-* **`'re.compile(<regex>)'` returns a Pattern object with methods sub(), findall(), …**
+* **`'re.compile(<regex>)'` returns a Pattern object with methods sub(), findall(), etc.**
 
 ### Match Object
 ```python
@@ -500,7 +500,7 @@ Numbers
 <Fraction> = fractions.Fraction(0, 1)             # Or: Fraction(numerator=0, denominator=1)
 <Decimal>  = decimal.Decimal(<str/int>)           # Or: Decimal((sign, digits, exponent))
 ```
-* **Decimal numbers are stored exactly, unlike most floats where: `'1.1 + 2.2 != 3.3'`.**
+* **Decimal numbers are stored exactly, unlike most floats where `'1.1 + 2.2 != 3.3'`.**
 * **Floats can be compared with: `'math.isclose(<float>, <float>)'`.**
 * **Precision of decimal operations is set with: `'decimal.getcontext().prec = <int>'`.**
 * **Bools can be used anywhere ints can, because bool is a subclass of int: `'True + 1 == 2'`.**
@@ -655,8 +655,8 @@ import zoneinfo, dateutil.tz
 >>> dt.strftime("%dth of %B '%y (%a), %I:%M %p %Z")
 "14th of August '25 (Thu), 11:39 PM UTC+02:00"
 ```
-* **`'%z'` accepts `'±HH[:]MM'` and returns `'±HHMM'` or empty string if datetime is naive.**
-* **`'%Z'` accepts `'UTC/GMT'` and local timezone's code and returns timezone's name, `'UTC[±HH:MM]'` if timezone is nameless, or an empty string if datetime is naive.**
+* **`'%z'` accepts `'±HH[:]MM'` and returns `'±HHMM'` or empty string if object is naive.**
+* **`'%Z'` accepts `'UTC/GMT'` and local timezone's code and returns timezone's name, `'UTC[±HH:MM]'` if timezone is nameless, or an empty string if object is naive.**
 
 ### Arithmetics
 ```python
@@ -679,7 +679,7 @@ def <func_name>(<default_args>): ...                     # E.g. `def func(x=0, y
 def <func_name>(<nondefault_args>, <default_args>): ...  # E.g. `def func(x, y=0): ...`.
 ```
 * **Function returns None if it doesn't encounter `'return <obj/exp>'` statement.**
-* **Before modifying a global variable from within the function run `'global <var_name>'`.**
+* **Run `'global <var_name>'` inside the function before assigning to global variable.**
 * **Default values are evaluated when function is first encountered in the scope. Any mutation of a mutable default value will persist between invocations!**
 
 ### Function Call
diff --git a/index.html b/index.html
index a3ca5c8dc..07c9c7270 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>March 30, 2025</aside>
+    <aside>April 1, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -356,7 +356,7 @@
 <li><strong>Argument <code class="python hljs"><span class="hljs-string">'flags=re.IGNORECASE'</span></code> can be used with all functions.</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>.</strong></li>
-<li><strong><code class="python hljs"><span class="hljs-string">'re.compile(&lt;regex&gt;)'</span></code> returns a Pattern object with methods sub(), findall(), …</strong></li>
+<li><strong><code class="python hljs"><span class="hljs-string">'re.compile(&lt;regex&gt;)'</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">&lt;str&gt;   = &lt;Match&gt;.group()                         <span class="hljs-comment"># Returns the whole match. Also group(0).</span>
 &lt;str&gt;   = &lt;Match&gt;.group(<span class="hljs-number">1</span>)                        <span class="hljs-comment"># Returns part inside the first brackets.</span>
@@ -463,7 +463,7 @@
 </code></pre></div>
 
 <ul>
-<li><strong>Decimal numbers are stored 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>Decimal numbers are stored 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(&lt;float&gt;, &lt;float&gt;)'</span></code>.</strong></li>
 <li><strong>Precision of decimal operations is set with: <code class="python hljs"><span class="hljs-string">'decimal.getcontext().prec = &lt;int&gt;'</span></code>.</strong></li>
 <li><strong>Bools can be used anywhere ints can, because bool is a subclass of int: <code class="python hljs"><span class="hljs-string">'True + 1 == 2'</span></code>.</strong></li>
@@ -585,8 +585,8 @@
 </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 datetime 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/GMT'</span></code> and 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 datetime 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">'±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/GMT'</span></code> and 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">&lt;bool&gt;   = &lt;D/T/DTn&gt; &gt; &lt;D/T/DTn&gt;            <span class="hljs-comment"># Ignores time jumps (fold attribute). Also ==.</span>
 &lt;bool&gt;   = &lt;DTa&gt;     &gt; &lt;DTa&gt;                <span class="hljs-comment"># Ignores time jumps if they share tzinfo object.</span>
@@ -605,7 +605,7 @@
 
 <ul>
 <li><strong>Function returns None if it doesn't encounter <code class="python hljs"><span class="hljs-string">'return &lt;obj/exp&gt;'</span></code> statement.</strong></li>
-<li><strong>Before modifying a global variable from within the function run <code class="python hljs"><span class="hljs-string">'global &lt;var_name&gt;'</span></code>.</strong></li>
+<li><strong>Run <code class="python hljs"><span class="hljs-string">'global &lt;var_name&gt;'</span></code> inside the function before assigning to global variable.</strong></li>
 <li><strong>Default values are evaluated when function is first encountered in the scope. Any mutation of a mutable default value will persist between invocations!</strong></li>
 </ul>
 <div><h3 id="functioncall">Function Call</h3><pre><code class="python language-python hljs">&lt;obj&gt; = &lt;function&gt;(&lt;positional_args&gt;)                    <span class="hljs-comment"># E.g. `func(0, 0)`.</span>
@@ -2944,7 +2944,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>March 30, 2025</aside>
+    <aside>April 1, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From b85abfe0b2b13c31ec1ab46dd007f93c3d272a7b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 17 Apr 2025 19:51:03 +0200
Subject: [PATCH 120/186] Console app, NumPy

---
 README.md  |  7 +++----
 index.html | 18 ++++++++----------
 parse.js   | 11 +++++------
 3 files changed, 16 insertions(+), 20 deletions(-)

diff --git a/README.md b/README.md
index 3a8f41a99..a43225bb0 100644
--- a/README.md
+++ b/README.md
@@ -2448,8 +2448,8 @@ def main(screen):
         ch = screen.getch()
         selected -= (ch == KEY_UP) and (selected > 0)
         selected += (ch == KEY_DOWN) and (selected < len(paths)-1)
-        first = min(first, selected)
-        first = max(first, selected - (height-1))
+        first -= (first > selected)
+        first += (first < selected-(height-1))
         if ch in [KEY_LEFT, KEY_RIGHT, KEY_ENTER, ord('\n'), ord('\r')]:
             new_dir = '..' if ch == KEY_LEFT else paths[selected]
             if os.path.isdir(new_dir):
@@ -2703,8 +2703,7 @@ import numpy as np
 <1/2d_arr> = <2d>[<2d/1d_bools>]                        # 1d_bools must have size of a column.
 ```
 * **`':'` returns a slice of all dimension's indices. Omitted dimensions default to `':'`.**
-* **Python converts `'obj[i, j]'` to `'obj[(i, j)]'`. This makes `'<2d>[row_i, col_i]'` and `'<2d>[row_indices]'` indistinguishable to NumPy if tuple of indices is passed!**
-* **Indexing with a slice and 1d object works the same as when using two slices (lines 4, 6, 7).**
+* **Python converts `'obj[i, j]'` to `'obj[(i, j)]'`. This makes `'<2d>[row_i, col_i]'` and `'<2d>[row_indices]'` indistinguishable to NumPy if tuple of two indices is passed!**
 * **`'ix_([1, 2], [3, 4])'` returns `'[[1], [2]]'` and `'[[3, 4]]'`. Due to broadcasting rules, this is the same as using `'[[1, 1], [2, 2]]'` and `'[[3, 4], [3, 4]]'`.**
 * **Any value that is broadcastable to the indexed shape can be assigned to the selection.**
 
diff --git a/index.html b/index.html
index 07c9c7270..fed245109 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>April 1, 2025</aside>
+    <aside>April 17, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -844,11 +844,10 @@
 <span class="hljs-keyword">raise</span> Exception(&lt;obj&gt;)
 </code></pre></div>
 
-<div><h4 id="expressionsthatcallthereprmethod">Expressions that call the repr() method:</h4><pre><code class="python language-python hljs">print/str/repr([&lt;obj&gt;])
-print/str/repr({&lt;obj&gt;: &lt;obj&gt;})
-<span class="hljs-string">f'<span class="hljs-subst">{&lt;obj&gt;!r}</span>'</span>
+<div><h4 id="expressionsthatcallthereprmethod">Expressions that call the repr() method:</h4><pre><code class="python language-python hljs">print/str/repr([&lt;obj&gt;, ...])
+print/str/repr({&lt;obj&gt;: &lt;obj&gt;, ...})
 Z = make_dataclass(<span class="hljs-string">'Z'</span>, [<span class="hljs-string">'a'</span>]); print/str/repr(Z(&lt;obj&gt;))
-<span class="hljs-meta">&gt;&gt;&gt; </span>&lt;obj&gt;
+<span class="hljs-string">f'<span class="hljs-subst">{&lt;obj&gt;!r}</span>'</span>
 </code></pre></div>
 
 <div><h3 id="inheritance">Inheritance</h3><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
@@ -2017,8 +2016,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
         ch = screen.getch()
         selected -= (ch == KEY_UP) <span class="hljs-keyword">and</span> (selected &gt; <span class="hljs-number">0</span>)
         selected += (ch == KEY_DOWN) <span class="hljs-keyword">and</span> (selected &lt; len(paths)-<span class="hljs-number">1</span>)
-        first = min(first, selected)
-        first = max(first, selected - (height-<span class="hljs-number">1</span>))
+        first -= (first &gt; selected)
+        first += (first &lt; 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, KEY_ENTER, ord(<span class="hljs-string">'\n'</span>), ord(<span class="hljs-string">'\r'</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):
@@ -2222,8 +2221,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <ul>
 <li><strong><code class="python hljs"><span class="hljs-string">':'</span></code> returns a slice of all dimension's indices. Omitted dimensions default to <code class="python hljs"><span class="hljs-string">':'</span></code>.</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">'&lt;2d&gt;[row_i, col_i]'</span></code> and <code class="python hljs"><span class="hljs-string">'&lt;2d&gt;[row_indices]'</span></code> indistinguishable to NumPy if tuple of indices is passed!</strong></li>
-<li><strong>Indexing with a slice and 1d object works the same as when using two slices (lines 4, 6, 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">'&lt;2d&gt;[row_i, col_i]'</span></code> and <code class="python hljs"><span class="hljs-string">'&lt;2d&gt;[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 using <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>
@@ -2944,7 +2942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>April 1, 2025</aside>
+    <aside>April 17, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index f238de42d..f07516785 100755
--- a/parse.js
+++ b/parse.js
@@ -80,11 +80,10 @@ const PARAMETRIZED_DECORATOR =
   '    <span class="hljs-keyword">return</span> x + y\n';
 
 const REPR_USE_CASES =
-  'print/str/repr([&lt;obj&gt;])\n' +
-  'print/str/repr({&lt;obj&gt;: &lt;obj&gt;})\n' +
-  '<span class="hljs-string">f\'<span class="hljs-subst">{&lt;obj&gt;!r}</span>\'</span>\n' +
+  'print/str/repr([&lt;obj&gt;, ...])\n' +
+  'print/str/repr({&lt;obj&gt;: &lt;obj&gt;, ...})\n' +
   'Z = make_dataclass(<span class="hljs-string">\'Z\'</span>, [<span class="hljs-string">\'a\'</span>]); print/str/repr(Z(&lt;obj&gt;))\n' +
-  '<span class="hljs-meta">&gt;&gt;&gt; </span>&lt;obj&gt;\n';
+  '<span class="hljs-string">f\'<span class="hljs-subst">{&lt;obj&gt;!r}</span>\'</span>\n';
 
 const CONSTRUCTOR_OVERLOADING =
   '<span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">name</span>&gt;:</span>\n' +
@@ -188,8 +187,8 @@ const CURSES =
   '        ch = screen.getch()\n' +
   '        selected -= (ch == KEY_UP) <span class="hljs-keyword">and</span> (selected &gt; <span class="hljs-number">0</span>)\n' +
   '        selected += (ch == KEY_DOWN) <span class="hljs-keyword">and</span> (selected &lt; len(paths)-<span class="hljs-number">1</span>)\n' +
-  '        first = min(first, selected)\n' +
-  '        first = max(first, selected - (height-<span class="hljs-number">1</span>))\n' +
+  '        first -= (first &gt; selected)\n' +
+  '        first += (first &lt; selected-(height-<span class="hljs-number">1</span>))\n' +
   '        <span class="hljs-keyword">if</span> ch <span class="hljs-keyword">in</span> [KEY_LEFT, KEY_RIGHT, KEY_ENTER, ord(<span class="hljs-string">\'\\n\'</span>), ord(<span class="hljs-string">\'\\r\'</span>)]:\n' +
   '            new_dir = <span class="hljs-string">\'..\'</span> <span class="hljs-keyword">if</span> ch == KEY_LEFT <span class="hljs-keyword">else</span> paths[selected]\n' +
   '            <span class="hljs-keyword">if</span> os.path.isdir(new_dir):\n' +

From 234cb5610b81f72fb5744ac8821f065ccfdfa0c9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 17 Apr 2025 19:55:32 +0200
Subject: [PATCH 121/186] Reverted repr() use cases

---
 index.html | 7 ++++---
 parse.js   | 7 ++++---
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/index.html b/index.html
index fed245109..89dbbe483 100644
--- a/index.html
+++ b/index.html
@@ -844,10 +844,11 @@
 <span class="hljs-keyword">raise</span> Exception(&lt;obj&gt;)
 </code></pre></div>
 
-<div><h4 id="expressionsthatcallthereprmethod">Expressions that call the repr() method:</h4><pre><code class="python language-python hljs">print/str/repr([&lt;obj&gt;, ...])
-print/str/repr({&lt;obj&gt;: &lt;obj&gt;, ...})
-Z = make_dataclass(<span class="hljs-string">'Z'</span>, [<span class="hljs-string">'a'</span>]); print/str/repr(Z(&lt;obj&gt;))
+<div><h4 id="expressionsthatcallthereprmethod">Expressions that call the repr() method:</h4><pre><code class="python language-python hljs">print/str/repr([&lt;obj&gt;])
+print/str/repr({&lt;obj&gt;: &lt;obj&gt;})
 <span class="hljs-string">f'<span class="hljs-subst">{&lt;obj&gt;!r}</span>'</span>
+Z = make_dataclass(<span class="hljs-string">'Z'</span>, [<span class="hljs-string">'a'</span>]); print/str/repr(Z(&lt;obj&gt;))
+<span class="hljs-meta">&gt;&gt;&gt; </span>&lt;obj&gt;
 </code></pre></div>
 
 <div><h3 id="inheritance">Inheritance</h3><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
diff --git a/parse.js b/parse.js
index f07516785..7e38b9348 100755
--- a/parse.js
+++ b/parse.js
@@ -80,10 +80,11 @@ const PARAMETRIZED_DECORATOR =
   '    <span class="hljs-keyword">return</span> x + y\n';
 
 const REPR_USE_CASES =
-  'print/str/repr([&lt;obj&gt;, ...])\n' +
-  'print/str/repr({&lt;obj&gt;: &lt;obj&gt;, ...})\n' +
+  'print/str/repr([&lt;obj&gt;])\n' +
+  'print/str/repr({&lt;obj&gt;: &lt;obj&gt;})\n' +
+  '<span class="hljs-string">f\'<span class="hljs-subst">{&lt;obj&gt;!r}</span>\'</span>\n' +
   'Z = make_dataclass(<span class="hljs-string">\'Z\'</span>, [<span class="hljs-string">\'a\'</span>]); print/str/repr(Z(&lt;obj&gt;))\n' +
-  '<span class="hljs-string">f\'<span class="hljs-subst">{&lt;obj&gt;!r}</span>\'</span>\n';
+  '<span class="hljs-meta">&gt;&gt;&gt; </span>&lt;obj&gt;\n';
 
 const CONSTRUCTOR_OVERLOADING =
   '<span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">name</span>&gt;:</span>\n' +

From 42f2e689796ce7de090f77bcd53a30288ae31df9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 22 Apr 2025 04:07:10 +0200
Subject: [PATCH 122/186] Numbers big changes, Combinatorics, Console app, GUI,
 Web

---
 README.md              | 115 ++++++++++++++++++++---------------------
 index.html             | 115 +++++++++++++++++++++--------------------
 parse.js               |  12 ++---
 pdf/index_for_pdf.html |   4 +-
 4 files changed, 123 insertions(+), 123 deletions(-)

diff --git a/README.md b/README.md
index a43225bb0..eac1b55a0 100644
--- a/README.md
+++ b/README.md
@@ -494,64 +494,69 @@ Format
 Numbers
 -------
 ```python
-<int>      = int(<float/str/bool>)                # Or: math.trunc(<float>)
-<float>    = float(<int/str/bool>)                # Or: <int/float>e±<int>
-<complex>  = complex(real=0, imag=0)              # Or: <int/float> ± <int/float>j
-<Fraction> = fractions.Fraction(0, 1)             # Or: Fraction(numerator=0, denominator=1)
-<Decimal>  = decimal.Decimal(<str/int>)           # Or: Decimal((sign, digits, exponent))
+<int>      = int(<float/str/bool>)           # Or: math.trunc(<float>)
+<float>    = float(<int/str/bool>)           # Or: <int/float>e±<int>
+<complex>  = complex(real=0, imag=0)         # Or: <int/float> ± <int/float>j
+<Fraction> = fractions.Fraction(0, 1)        # Or: Fraction(numerator=0, denominator=1)
+<Decimal>  = decimal.Decimal(<str/int>)      # Or: Decimal((sign, digits, exponent))
 ```
+* **`'int(<str>)'` and `'float(<str>)'` raise ValueError on malformed strings.**
 * **Decimal numbers are stored exactly, unlike most floats where `'1.1 + 2.2 != 3.3'`.**
 * **Floats can be compared with: `'math.isclose(<float>, <float>)'`.**
 * **Precision of decimal operations is set with: `'decimal.getcontext().prec = <int>'`.**
 * **Bools can be used anywhere ints can, because bool is a subclass of int: `'True + 1 == 2'`.**
 
-### Basic Functions
+### Built-in Functions
 ```python
-<num> = pow(<num>, <num>)                         # Or: <number> ** <number>
-<num> = abs(<num>)                                # <float> = abs(<complex>)
-<num> = round(<num> [, ±ndigits])                 # `round(126, -1) == 130`
+<num> = pow(<num>, <num>)                    # Or: <number> ** <number>
+<num> = abs(<num>)                           # <float> = abs(<complex>)
+<num> = round(<num> [, ±ndigits])            # Also math.floor/ceil(<number>).
+<num> = min(<collection>)                    # Also max(<num>, <num> [, ...]).
+<num> = sum(<collection>)                    # Also math.prod(<collection>).
 ```
 
 ### Math
 ```python
-from math import e, pi, inf, nan, isinf, isnan    # `<el> == nan` is always False.
-from math import sin, cos, tan, asin, acos, atan  # Also: degrees, radians.
-from math import log, log10, log2                 # Log can accept base as second arg.
+from math import e, pi, inf, nan, isnan      # `inf*0` and `nan+1` return nan.
+from math import sqrt, factorial             # `sqrt(-1)` raises ValueError.
+from math import sin, cos, tan               # Also: asin, degrees, radians.
+from math import log, log10, log2            # Log accepts base as second arg.
 ```
 
 ### Statistics
 ```python
-from statistics import mean, median, variance     # Also: stdev, quantiles, groupby.
+from statistics import mean, median, mode    # Mode returns the most common value.
+from statistics import variance, stdev       # Also: pvariance, pstdev, quantiles.
 ```
 
 ### Random
 ```python
-from random import random, randint, uniform       # Also: gauss, choice, shuffle, seed.
+from random import random, randint, uniform  # Also: gauss, choice, shuffle, seed.
 ```
 
 ```python
-<float> = random()                                # Returns a float inside [0, 1).
-<num>   = randint/uniform(a, b)                   # Returns an int/float inside [a, b].
-<float> = gauss(mean, stdev)                      # Also triangular(low, high, mode).
-<el>    = choice(<sequence>)                      # Keeps it intact. Also sample(pop, k).
-shuffle(<list>)                                   # Shuffles the list in place.
+<float> = random()                           # Returns a float inside [0, 1).
+<num>   = randint/uniform(a, b)              # Returns an int/float inside [a, b].
+<float> = gauss(mean, stdev)                 # Also triangular(low, high, mode).
+<el>    = choice(<sequence>)                 # Keeps it intact. Also sample(pop, k).
+shuffle(<list>)                              # Shuffles the list in place.
 ```
 
 ### Hexadecimal Numbers
 ```python
-<int> = ±0x<hex>                                  # Or: ±0b<bin>
-<int> = int('±<hex>', 16)                         # Or: int('±<bin>', 2)
-<int> = int('±0x<hex>', 0)                        # Or: int('±0b<bin>', 0)
-<str> = hex(<int>)                                # Returns '[-]0x<hex>'. Also bin().
+<int> = ±0x<hex>                             # Or: ±0b<bin>
+<int> = int('±<hex>', 16)                    # Or: int('±<bin>', 2)
+<int> = int('±0x<hex>', 0)                   # Or: int('±0b<bin>', 0)
+<str> = hex(<int>)                           # Returns '[-]0x<hex>'. Also bin().
 ```
 
 ### Bitwise Operators
 ```python
-<int> = <int> & <int>                             # And (0b1100 & 0b1010 == 0b1000).
-<int> = <int> | <int>                             # Or  (0b1100 | 0b1010 == 0b1110).
-<int> = <int> ^ <int>                             # Xor (0b1100 ^ 0b1010 == 0b0110).
-<int> = <int> << n_bits                           # Left shift. Use >> for right.
-<int> = ~<int>                                    # Not. Also -<int> - 1.
+<int> = <int> & <int>                        # And (0b1100 & 0b1010 == 0b1000).
+<int> = <int> | <int>                        # Or  (0b1100 | 0b1010 == 0b1110).
+<int> = <int> ^ <int>                        # Xor (0b1100 ^ 0b1010 == 0b0110).
+<int> = <int> << n_bits                      # Left shift. Use >> for right.
+<int> = ~<int>                               # Not. Also -<int> - 1.
 ```
 
 
@@ -562,30 +567,24 @@ import itertools as it
 ```
 
 ```python
->>> list(it.product([0, 1], repeat=3))
-[(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1),
- (1, 0, 0), (1, 0, 1), (1, 1, 0), (1, 1, 1)]
+>>> list(it.product('abc', repeat=2))        #   a  b  c
+[('a', 'a'), ('a', 'b'), ('a', 'c'),         # a x  x  x
+ ('b', 'a'), ('b', 'b'), ('b', 'c'),         # b x  x  x
+ ('c', 'a'), ('c', 'b'), ('c', 'c')]         # c x  x  x
 ```
 
 ```python
->>> list(it.product('abc', 'abc'))                #   a  b  c
-[('a', 'a'), ('a', 'b'), ('a', 'c'),              # a x  x  x
- ('b', 'a'), ('b', 'b'), ('b', 'c'),              # b x  x  x
- ('c', 'a'), ('c', 'b'), ('c', 'c')]              # c x  x  x
+>>> list(it.permutations('abc', 2))          #   a  b  c
+[('a', 'b'), ('a', 'c'),                     # a .  x  x
+ ('b', 'a'), ('b', 'c'),                     # b x  .  x
+ ('c', 'a'), ('c', 'b')]                     # c x  x  .
 ```
 
 ```python
->>> list(it.permutations('abc', 2))               #   a  b  c
-[('a', 'b'), ('a', 'c'),                          # a .  x  x
- ('b', 'a'), ('b', 'c'),                          # b x  .  x
- ('c', 'a'), ('c', 'b')]                          # c x  x  .
-```
-
-```python
->>> list(it.combinations('abc', 2))               #   a  b  c
-[('a', 'b'), ('a', 'c'),                          # a .  x  x
- ('b', 'c'),                                      # b .  .  x
-]                                                 # c .  .  .
+>>> list(it.combinations('abc', 2))          #   a  b  c
+[('a', 'b'), ('a', 'c'),                     # a .  x  x
+ ('b', 'c'),                                 # b .  .  x
+]                                            # c .  .  .
 ```
 
 
@@ -1183,7 +1182,7 @@ class Counter:
 
 ### Callable
 * **All functions and classes have a call() method, hence are callable.**
-* **Use `'callable(<obj>)'` or `'isinstance(<obj>, collections.abc.Callable)'` to check if object is callable.**
+* **Use `'callable(<obj>)'` or `'isinstance(<obj>, collections.abc.Callable)'` to check if object is callable. Calling an uncallable object raises `'TypeError'`.**
 * **When this cheatsheet uses `'<function>'` as an argument, it means `'<callable>'`.**
 ```python
 class Counter:
@@ -2435,7 +2434,7 @@ Console App
 ```python
 # $ pip3 install windows-curses
 import curses, os
-from curses import A_REVERSE, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER
+from curses import A_REVERSE, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT
 
 def main(screen):
     ch, first, selected, paths = 0, 0, 0, os.listdir()
@@ -2450,7 +2449,7 @@ def main(screen):
         selected += (ch == KEY_DOWN) and (selected < len(paths)-1)
         first -= (first > selected)
         first += (first < selected-(height-1))
-        if ch in [KEY_LEFT, KEY_RIGHT, KEY_ENTER, ord('\n'), ord('\r')]:
+        if ch in [KEY_LEFT, KEY_RIGHT, ord('\n')]:
             new_dir = '..' if ch == KEY_LEFT else paths[selected]
             if os.path.isdir(new_dir):
                 os.chdir(new_dir)
@@ -2469,9 +2468,9 @@ GUI App
 # $ pip3 install PySimpleGUI
 import PySimpleGUI as sg
 
-text_box = sg.Input(default_text='100', enable_events=True, key='-QUANTITY-')
-dropdown = sg.InputCombo(['g', 'kg', 't'], 'kg', readonly=True, enable_events=True, k='-UNIT-')
-label    = sg.Text('100 kg is 220.462 lbs.', key='-OUTPUT-')
+text_box = sg.Input(default_text='100', enable_events=True, key='QUANTITY')
+dropdown = sg.InputCombo(['g', 'kg', 't'], 'kg', readonly=True, enable_events=True, k='UNIT')
+label    = sg.Text('100 kg is 220.462 lbs.', key='OUTPUT')
 button   = sg.Button('Close')
 window   = sg.Window('Weight Converter', [[text_box, dropdown], [label], [button]])
 
@@ -2480,13 +2479,13 @@ while True:
     if event in [sg.WIN_CLOSED, 'Close']:
         break
     try:
-        quantity = float(values['-QUANTITY-'])
+        quantity = float(values['QUANTITY'])
     except ValueError:
         continue
-    unit = values['-UNIT-']
+    unit = values['UNIT']
     factors = {'g': 0.001, 'kg': 1, 't': 1000}
     lbs = quantity * factors[unit] / 0.45359237
-    window['-OUTPUT-'].update(value=f'{quantity} {unit} is {lbs:g} lbs.')
+    window['OUTPUT'].update(value=f'{quantity} {unit} is {lbs:g} lbs.')
 window.close()
 ```
 
@@ -2552,14 +2551,14 @@ app.run(host=None, port=None, debug=None)  # Or: $ flask --app FILE run [--ARG[=
 * **Install a WSGI server like [Waitress](https://flask.palletsprojects.com/en/latest/deploying/waitress/) and a HTTP server such as [Nginx](https://flask.palletsprojects.com/en/latest/deploying/nginx/) for better security.**
 * **Debug mode restarts the app whenever script changes and displays errors in the browser.**
 
-### Static Request
+### Serving Files
 ```python
 @app.route('/img/<path:filename>')
 def serve_file(filename):
     return fl.send_from_directory('DIRNAME', filename)
 ```
 
-### Dynamic Request
+### Serving HTML
 ```python
 @app.route('/<sport>')
 def serve_html(sport):
@@ -2570,7 +2569,7 @@ def serve_html(sport):
 * **`'fl.request.args[<str>]'` returns parameter from query string (URL part right of '?').**
 * **`'fl.session[<str>] = <obj>'` stores session data. It requires secret key to be set at the startup with `'app.secret_key = <str>'`.**
 
-### REST Request
+### Serving JSON
 ```python
 @app.post('/<sport>/odds')
 def serve_json(sport):
diff --git a/index.html b/index.html
index 89dbbe483..7e806730b 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>April 17, 2025</aside>
+    <aside>April 22, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -455,75 +455,76 @@
 {<span class="hljs-number">90</span>:X}                                   <span class="hljs-comment"># '5A'. Hexadecimal with upper-case letters.</span>
 </code></pre></div>
 
-<div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs">&lt;int&gt;      = int(&lt;float/str/bool&gt;)                <span class="hljs-comment"># Or: math.trunc(&lt;float&gt;)</span>
-&lt;float&gt;    = float(&lt;int/str/bool&gt;)                <span class="hljs-comment"># Or: &lt;int/float&gt;e±&lt;int&gt;</span>
-&lt;complex&gt;  = complex(real=<span class="hljs-number">0</span>, imag=<span class="hljs-number">0</span>)              <span class="hljs-comment"># Or: &lt;int/float&gt; ± &lt;int/float&gt;j</span>
-&lt;Fraction&gt; = fractions.Fraction(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>)             <span class="hljs-comment"># Or: Fraction(numerator=0, denominator=1)</span>
-&lt;Decimal&gt;  = decimal.Decimal(&lt;str/int&gt;)           <span class="hljs-comment"># Or: Decimal((sign, digits, exponent))</span>
+<div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs">&lt;int&gt;      = int(&lt;float/str/bool&gt;)           <span class="hljs-comment"># Or: math.trunc(&lt;float&gt;)</span>
+&lt;float&gt;    = float(&lt;int/str/bool&gt;)           <span class="hljs-comment"># Or: &lt;int/float&gt;e±&lt;int&gt;</span>
+&lt;complex&gt;  = complex(real=<span class="hljs-number">0</span>, imag=<span class="hljs-number">0</span>)         <span class="hljs-comment"># Or: &lt;int/float&gt; ± &lt;int/float&gt;j</span>
+&lt;Fraction&gt; = fractions.Fraction(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>)        <span class="hljs-comment"># Or: Fraction(numerator=0, denominator=1)</span>
+&lt;Decimal&gt;  = decimal.Decimal(&lt;str/int&gt;)      <span class="hljs-comment"># Or: Decimal((sign, digits, exponent))</span>
 </code></pre></div>
 
 <ul>
+<li><strong><code class="python hljs"><span class="hljs-string">'int(&lt;str&gt;)'</span></code> and <code class="python hljs"><span class="hljs-string">'float(&lt;str&gt;)'</span></code> raise ValueError on malformed strings.</strong></li>
 <li><strong>Decimal numbers are stored 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(&lt;float&gt;, &lt;float&gt;)'</span></code>.</strong></li>
 <li><strong>Precision of decimal operations is set with: <code class="python hljs"><span class="hljs-string">'decimal.getcontext().prec = &lt;int&gt;'</span></code>.</strong></li>
 <li><strong>Bools can be used anywhere ints can, because 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="basicfunctions">Basic Functions</h3><pre><code class="python language-python hljs">&lt;num&gt; = pow(&lt;num&gt;, &lt;num&gt;)                         <span class="hljs-comment"># Or: &lt;number&gt; ** &lt;number&gt;</span>
-&lt;num&gt; = abs(&lt;num&gt;)                                <span class="hljs-comment"># &lt;float&gt; = abs(&lt;complex&gt;)</span>
-&lt;num&gt; = round(&lt;num&gt; [, ±ndigits])                 <span class="hljs-comment"># `round(126, -1) == 130`</span>
+<div><h3 id="builtinfunctions">Built-in Functions</h3><pre><code class="python language-python hljs">&lt;num&gt; = pow(&lt;num&gt;, &lt;num&gt;)                    <span class="hljs-comment"># Or: &lt;number&gt; ** &lt;number&gt;</span>
+&lt;num&gt; = abs(&lt;num&gt;)                           <span class="hljs-comment"># &lt;float&gt; = abs(&lt;complex&gt;)</span>
+&lt;num&gt; = round(&lt;num&gt; [, ±ndigits])            <span class="hljs-comment"># Also math.floor/ceil(&lt;number&gt;).</span>
+&lt;num&gt; = min(&lt;collection&gt;)                    <span class="hljs-comment"># Also max(&lt;num&gt;, &lt;num&gt; [, ...]).</span>
+&lt;num&gt; = sum(&lt;collection&gt;)                    <span class="hljs-comment"># Also math.prod(&lt;collection&gt;).</span>
 </code></pre></div>
 
-<div><h3 id="math">Math</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> e, pi, inf, nan, isinf, isnan    <span class="hljs-comment"># `&lt;el&gt; == nan` is always False.</span>
-<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> sin, cos, tan, asin, acos, atan  <span class="hljs-comment"># Also: degrees, radians.</span>
-<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> log, log10, log2                 <span class="hljs-comment"># Log can accept base as second arg.</span>
+<div><h3 id="math">Math</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> e, pi, inf, nan, isnan      <span class="hljs-comment"># `inf*0` and `nan+1` return nan.</span>
+<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> sqrt, factorial             <span class="hljs-comment"># `sqrt(-1)` raises ValueError.</span>
+<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> sin, cos, tan               <span class="hljs-comment"># Also: asin, degrees, radians.</span>
+<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> log, log10, log2            <span class="hljs-comment"># Log accepts base as second arg.</span>
 </code></pre></div>
 
-<div><h3 id="statistics">Statistics</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> statistics <span class="hljs-keyword">import</span> mean, median, variance     <span class="hljs-comment"># Also: stdev, quantiles, groupby.</span>
+<div><h3 id="statistics">Statistics</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> statistics <span class="hljs-keyword">import</span> mean, median, mode    <span class="hljs-comment"># Mode returns the most common value.</span>
+<span class="hljs-keyword">from</span> statistics <span class="hljs-keyword">import</span> variance, stdev       <span class="hljs-comment"># Also: pvariance, pstdev, quantiles.</span>
 </code></pre></div>
 
-<div><h3 id="random">Random</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> random, randint, uniform       <span class="hljs-comment"># Also: gauss, choice, shuffle, seed.</span>
+<div><h3 id="random">Random</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> random, randint, uniform  <span class="hljs-comment"># Also: gauss, choice, shuffle, seed.</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs">&lt;float&gt; = random()                                <span class="hljs-comment"># Returns a float inside [0, 1).</span>
-&lt;num&gt;   = randint/uniform(a, b)                   <span class="hljs-comment"># Returns an int/float inside [a, b].</span>
-&lt;float&gt; = gauss(mean, stdev)                      <span class="hljs-comment"># Also triangular(low, high, mode).</span>
-&lt;el&gt;    = choice(&lt;sequence&gt;)                      <span class="hljs-comment"># Keeps it intact. Also sample(pop, k).</span>
-shuffle(&lt;list&gt;)                                   <span class="hljs-comment"># Shuffles the list in place.</span>
+<pre><code class="python language-python hljs">&lt;float&gt; = random()                           <span class="hljs-comment"># Returns a float inside [0, 1).</span>
+&lt;num&gt;   = randint/uniform(a, b)              <span class="hljs-comment"># Returns an int/float inside [a, b].</span>
+&lt;float&gt; = gauss(mean, stdev)                 <span class="hljs-comment"># Also triangular(low, high, mode).</span>
+&lt;el&gt;    = choice(&lt;sequence&gt;)                 <span class="hljs-comment"># Keeps it intact. Also sample(pop, k).</span>
+shuffle(&lt;list&gt;)                              <span class="hljs-comment"># Shuffles the list in place.</span>
 </code></pre>
-<div><h3 id="hexadecimalnumbers">Hexadecimal Numbers</h3><pre><code class="python language-python hljs">&lt;int&gt; = ±<span class="hljs-number">0x</span>&lt;hex&gt;                                  <span class="hljs-comment"># Or: ±0b&lt;bin&gt;</span>
-&lt;int&gt; = int(<span class="hljs-string">'±&lt;hex&gt;'</span>, <span class="hljs-number">16</span>)                         <span class="hljs-comment"># Or: int('±&lt;bin&gt;', 2)</span>
-&lt;int&gt; = int(<span class="hljs-string">'±0x&lt;hex&gt;'</span>, <span class="hljs-number">0</span>)                        <span class="hljs-comment"># Or: int('±0b&lt;bin&gt;', 0)</span>
-&lt;str&gt; = hex(&lt;int&gt;)                                <span class="hljs-comment"># Returns '[-]0x&lt;hex&gt;'. Also bin().</span>
+<div><h3 id="hexadecimalnumbers">Hexadecimal Numbers</h3><pre><code class="python language-python hljs">&lt;int&gt; = ±<span class="hljs-number">0x</span>&lt;hex&gt;                             <span class="hljs-comment"># Or: ±0b&lt;bin&gt;</span>
+&lt;int&gt; = int(<span class="hljs-string">'±&lt;hex&gt;'</span>, <span class="hljs-number">16</span>)                    <span class="hljs-comment"># Or: int('±&lt;bin&gt;', 2)</span>
+&lt;int&gt; = int(<span class="hljs-string">'±0x&lt;hex&gt;'</span>, <span class="hljs-number">0</span>)                   <span class="hljs-comment"># Or: int('±0b&lt;bin&gt;', 0)</span>
+&lt;str&gt; = hex(&lt;int&gt;)                           <span class="hljs-comment"># Returns '[-]0x&lt;hex&gt;'. Also bin().</span>
 </code></pre></div>
 
-<div><h3 id="bitwiseoperators">Bitwise Operators</h3><pre><code class="python language-python hljs">&lt;int&gt; = &lt;int&gt; &amp; &lt;int&gt;                             <span class="hljs-comment"># And (0b1100 &amp; 0b1010 == 0b1000).</span>
-&lt;int&gt; = &lt;int&gt; | &lt;int&gt;                             <span class="hljs-comment"># Or  (0b1100 | 0b1010 == 0b1110).</span>
-&lt;int&gt; = &lt;int&gt; ^ &lt;int&gt;                             <span class="hljs-comment"># Xor (0b1100 ^ 0b1010 == 0b0110).</span>
-&lt;int&gt; = &lt;int&gt; &lt;&lt; n_bits                           <span class="hljs-comment"># Left shift. Use &gt;&gt; for right.</span>
-&lt;int&gt; = ~&lt;int&gt;                                    <span class="hljs-comment"># Not. Also -&lt;int&gt; - 1.</span>
+<div><h3 id="bitwiseoperators">Bitwise Operators</h3><pre><code class="python language-python hljs">&lt;int&gt; = &lt;int&gt; &amp; &lt;int&gt;                        <span class="hljs-comment"># And (0b1100 &amp; 0b1010 == 0b1000).</span>
+&lt;int&gt; = &lt;int&gt; | &lt;int&gt;                        <span class="hljs-comment"># Or  (0b1100 | 0b1010 == 0b1110).</span>
+&lt;int&gt; = &lt;int&gt; ^ &lt;int&gt;                        <span class="hljs-comment"># Xor (0b1100 ^ 0b1010 == 0b0110).</span>
+&lt;int&gt; = &lt;int&gt; &lt;&lt; n_bits                      <span class="hljs-comment"># Left shift. Use &gt;&gt; for right.</span>
+&lt;int&gt; = ~&lt;int&gt;                               <span class="hljs-comment"># Not. Also -&lt;int&gt; - 1.</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">&gt;&gt;&gt; </span>list(it.product([<span class="hljs-number">0</span>, <span class="hljs-number">1</span>], repeat=<span class="hljs-number">3</span>))
-[(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>), (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>), (<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>), (<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>),
- (<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>)]
+<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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">&gt;&gt;&gt; </span>list(it.product(<span class="hljs-string">'abc'</span>, <span class="hljs-string">'abc'</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>
+<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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">&gt;&gt;&gt; </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>
+<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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>Provides 'date', 'time', 'datetime' and 'timedelta' classes. All are immutable and hashable.</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> date, time, datetime, timedelta, timezone
@@ -1012,7 +1013,7 @@
 <li><strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong></li>
 </ul><div><h3 id="callable">Callable</h3><ul>
 <li><strong>All functions and classes have a call() method, hence are callable.</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'callable(&lt;obj&gt;)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(&lt;obj&gt;, collections.abc.Callable)'</span></code> to check if object is callable.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'callable(&lt;obj&gt;)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(&lt;obj&gt;, collections.abc.Callable)'</span></code> to check if object is callable. Calling an uncallable object raises <code class="python hljs"><span class="hljs-string">'TypeError'</span></code>.</strong></li>
 <li><strong>When this cheatsheet uses <code class="python hljs"><span class="hljs-string">'&lt;function&gt;'</span></code> as an argument, it means <code class="python hljs"><span class="hljs-string">'&lt;callable&gt;'</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>
@@ -2004,7 +2005,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <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, KEY_ENTER
+<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()
@@ -2019,7 +2020,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
         selected += (ch == KEY_DOWN) <span class="hljs-keyword">and</span> (selected &lt; len(paths)-<span class="hljs-number">1</span>)
         first -= (first &gt; selected)
         first += (first &lt; 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, KEY_ENTER, ord(<span class="hljs-string">'\n'</span>), ord(<span class="hljs-string">'\r'</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)
@@ -2033,9 +2034,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <div><h2 id="guiapp"><a href="#guiapp" name="guiapp">#</a>GUI App</h2><div><h4 id="aweightconverterguiapplication">A weight converter GUI application:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install PySimpleGUI</span>
 <span class="hljs-keyword">import</span> PySimpleGUI <span class="hljs-keyword">as</span> sg
 
-text_box = 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>)
-dropdown = sg.InputCombo([<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>)
-label    = sg.Text(<span class="hljs-string">'100 kg is 220.462 lbs.'</span>, key=<span class="hljs-string">'-OUTPUT-'</span>)
+text_box = 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>)
+dropdown = sg.InputCombo([<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>)
+label    = sg.Text(<span class="hljs-string">'100 kg is 220.462 lbs.'</span>, key=<span class="hljs-string">'OUTPUT'</span>)
 button   = sg.Button(<span class="hljs-string">'Close'</span>)
 window   = sg.Window(<span class="hljs-string">'Weight Converter'</span>, [[text_box, dropdown], [label], [button]])
 
@@ -2044,13 +2045,13 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     <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>])
+        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>]
+    unit = values[<span class="hljs-string">'UNIT'</span>]
     factors = {<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>}
     lbs = quantity * factors[unit] / <span class="hljs-number">0.45359237</span>
-    window[<span class="hljs-string">'-OUTPUT-'</span>].update(value=<span class="hljs-string">f'<span class="hljs-subst">{quantity}</span> <span class="hljs-subst">{unit}</span> is <span class="hljs-subst">{lbs:g}</span> lbs.'</span>)
+    window[<span class="hljs-string">'OUTPUT'</span>].update(value=<span class="hljs-string">f'<span class="hljs-subst">{quantity}</span> <span class="hljs-subst">{unit}</span> is <span class="hljs-subst">{lbs:g}</span> lbs.'</span>)
 window.close()
 </code></pre></div></div>
 
@@ -2105,12 +2106,12 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>Install a WSGI 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> for 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="staticrequest">Static Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/img/&lt;path:filename&gt;')</span>
+<div><h3 id="servingfiles">Serving Files</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/img/&lt;path:filename&gt;')</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="dynamicrequest">Dynamic Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/&lt;sport&gt;')</span>
+<div><h3 id="servinghtml">Serving HTML</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/&lt;sport&gt;')</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">'&lt;h1&gt;{{title}}&lt;/h1&gt;'</span>, title=sport)
 </code></pre></div>
@@ -2121,7 +2122,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong><code class="python hljs"><span class="hljs-string">'fl.request.args[&lt;str&gt;]'</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[&lt;str&gt;] = &lt;obj&gt;'</span></code> stores session data. It requires secret key to be set at the startup with <code class="python hljs"><span class="hljs-string">'app.secret_key = &lt;str&gt;'</span></code>.</strong></li>
 </ul>
-<div><h3 id="restrequest">REST Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.post('/&lt;sport&gt;/odds')</span>
+<div><h3 id="servingjson">Serving JSON</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.post('/&lt;sport&gt;/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>]}
@@ -2943,7 +2944,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>April 17, 2025</aside>
+    <aside>April 22, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 7e38b9348..c1e0bd165 100755
--- a/parse.js
+++ b/parse.js
@@ -43,10 +43,10 @@ const TOC =
   '</code></pre>\n';
 
 const BIN_HEX =
-  '&lt;int&gt; = ±<span class="hljs-number">0x</span>&lt;hex&gt;                                  <span class="hljs-comment"># Or: ±0b&lt;bin&gt;</span>\n' +
-  '&lt;int&gt; = int(<span class="hljs-string">\'±&lt;hex&gt;\'</span>, <span class="hljs-number">16</span>)                         <span class="hljs-comment"># Or: int(\'±&lt;bin&gt;\', 2)</span>\n' +
-  '&lt;int&gt; = int(<span class="hljs-string">\'±0x&lt;hex&gt;\'</span>, <span class="hljs-number">0</span>)                        <span class="hljs-comment"># Or: int(\'±0b&lt;bin&gt;\', 0)</span>\n' +
-  '&lt;str&gt; = hex(&lt;int&gt;)                                <span class="hljs-comment"># Returns \'[-]0x&lt;hex&gt;\'. Also bin().</span>\n';
+  '&lt;int&gt; = ±<span class="hljs-number">0x</span>&lt;hex&gt;                             <span class="hljs-comment"># Or: ±0b&lt;bin&gt;</span>\n' +
+  '&lt;int&gt; = int(<span class="hljs-string">\'±&lt;hex&gt;\'</span>, <span class="hljs-number">16</span>)                    <span class="hljs-comment"># Or: int(\'±&lt;bin&gt;\', 2)</span>\n' +
+  '&lt;int&gt; = int(<span class="hljs-string">\'±0x&lt;hex&gt;\'</span>, <span class="hljs-number">0</span>)                   <span class="hljs-comment"># Or: int(\'±0b&lt;bin&gt;\', 0)</span>\n' +
+  '&lt;str&gt; = hex(&lt;int&gt;)                           <span class="hljs-comment"># Returns \'[-]0x&lt;hex&gt;\'. Also bin().</span>\n';
 
 const CACHE =
   '<span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> cache\n' +
@@ -175,7 +175,7 @@ const COROUTINES =
 const CURSES =
   '<span class="hljs-comment"># $ pip3 install windows-curses</span>\n' +
   '<span class="hljs-keyword">import</span> curses, os\n' +
-  '<span class="hljs-keyword">from</span> curses <span class="hljs-keyword">import</span> A_REVERSE, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT, KEY_ENTER\n' +
+  '<span class="hljs-keyword">from</span> curses <span class="hljs-keyword">import</span> A_REVERSE, KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT\n' +
   '\n' +
   '<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">(screen)</span>:</span>\n' +
   '    ch, first, selected, paths = <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, os.listdir()\n' +
@@ -190,7 +190,7 @@ const CURSES =
   '        selected += (ch == KEY_DOWN) <span class="hljs-keyword">and</span> (selected &lt; len(paths)-<span class="hljs-number">1</span>)\n' +
   '        first -= (first &gt; selected)\n' +
   '        first += (first &lt; selected-(height-<span class="hljs-number">1</span>))\n' +
-  '        <span class="hljs-keyword">if</span> ch <span class="hljs-keyword">in</span> [KEY_LEFT, KEY_RIGHT, KEY_ENTER, ord(<span class="hljs-string">\'\\n\'</span>), ord(<span class="hljs-string">\'\\r\'</span>)]:\n' +
+  '        <span class="hljs-keyword">if</span> ch <span class="hljs-keyword">in</span> [KEY_LEFT, KEY_RIGHT, ord(<span class="hljs-string">\'\\n\'</span>)]:\n' +
   '            new_dir = <span class="hljs-string">\'..\'</span> <span class="hljs-keyword">if</span> ch == KEY_LEFT <span class="hljs-keyword">else</span> paths[selected]\n' +
   '            <span class="hljs-keyword">if</span> os.path.isdir(new_dir):\n' +
   '                os.chdir(new_dir)\n' +
diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html
index a4a44cc12..9cb299e6b 100644
--- a/pdf/index_for_pdf.html
+++ b/pdf/index_for_pdf.html
@@ -73,7 +73,7 @@ <h3 id="i">I</h3>
 <strong>iterator, <a href="#enumerate">3</a>-<a href="#generator">4</a>, <a href="#comprehensions">11</a>, <a href="#iterator-1">17</a></strong><br>
 <strong>itertools module, <a href="#itertools">3</a>, <a href="#combinatorics">8</a></strong>  </p>
 <h3 id="j">J</h3>
-<p><strong>json, <a href="#json">25</a>, <a href="#restrequest">36</a>, <a href="#fileformats">46</a></strong>  </p>
+<p><strong>json, <a href="#json">25</a>, <a href="#servingjson">36</a>, <a href="#fileformats">46</a></strong>  </p>
 <h3 id="l">L</h3>
 <p><strong>lambda, <a href="#lambda">11</a></strong><br>
 <strong>lists, <a href="#list">1</a>-<a href="#list">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">10</a>-<a href="#comprehensions">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
@@ -135,7 +135,7 @@ <h3 id="s">S</h3>
 <strong>sys module, <a href="#cache">13</a>, <a href="#exit">21</a>-<a href="#commandlinearguments">22</a></strong> </p>
 <h3 id="t">T</h3>
 <p><strong>table, <a href="#csv">26</a>, <a href="#example-1">27</a>, <a href="#table">34</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#dataframe">45</a>-<a href="#dataframeaggregatetransformmap">46</a></strong><br>
-<strong>template, <a href="#format">6</a>, <a href="#dynamicrequest">36</a></strong><br>
+<strong>template, <a href="#format">6</a>, <a href="#servinghtml">36</a></strong><br>
 <strong>threading module, <a href="#threading">32</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong><br>
 <strong>time module, <a href="#progressbar">34</a>, <a href="#profiling">36</a></strong><br>
 <strong>tuples, <a href="#tuple">3</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">10</a>-<a href="#comprehensions">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a></strong><br>

From 218be718501eb840805e5575e02e74e7bde16654 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 22 Apr 2025 17:47:05 +0200
Subject: [PATCH 123/186] Numbers

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index eac1b55a0..540dbb419 100644
--- a/README.md
+++ b/README.md
@@ -517,7 +517,7 @@ Numbers
 
 ### Math
 ```python
-from math import e, pi, inf, nan, isnan      # `inf*0` and `nan+1` return nan.
+from math import pi, inf, nan, isnan         # `inf*0` and `nan+1` return nan.
 from math import sqrt, factorial             # `sqrt(-1)` raises ValueError.
 from math import sin, cos, tan               # Also: asin, degrees, radians.
 from math import log, log10, log2            # Log accepts base as second arg.
@@ -583,7 +583,7 @@ import itertools as it
 ```python
 >>> list(it.combinations('abc', 2))          #   a  b  c
 [('a', 'b'), ('a', 'c'),                     # a .  x  x
- ('b', 'c'),                                 # b .  .  x
+ ('b', 'c')                                  # b .  .  x
 ]                                            # c .  .  .
 ```
 
diff --git a/index.html b/index.html
index 7e806730b..623614088 100644
--- a/index.html
+++ b/index.html
@@ -476,7 +476,7 @@
 &lt;num&gt; = sum(&lt;collection&gt;)                    <span class="hljs-comment"># Also math.prod(&lt;collection&gt;).</span>
 </code></pre></div>
 
-<div><h3 id="math">Math</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> e, pi, inf, nan, isnan      <span class="hljs-comment"># `inf*0` and `nan+1` return nan.</span>
+<div><h3 id="math">Math</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> pi, inf, nan, isnan         <span class="hljs-comment"># `inf*0` and `nan+1` return nan.</span>
 <span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> sqrt, factorial             <span class="hljs-comment"># `sqrt(-1)` raises ValueError.</span>
 <span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> sin, cos, tan               <span class="hljs-comment"># Also: asin, degrees, radians.</span>
 <span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> log, log10, log2            <span class="hljs-comment"># Log accepts base as second arg.</span>
@@ -523,7 +523,7 @@
 </code></pre>
 <pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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-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>Provides 'date', 'time', 'datetime' and 'timedelta' classes. All are immutable and hashable.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install python-dateutil</span>

From e88b89f1221013ef98c227fb85adc1bd1ca1ec61 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 27 Apr 2025 18:25:50 +0200
Subject: [PATCH 124/186] Image, Pygame, Pandas

---
 README.md  | 18 +++++++++---------
 index.html | 22 +++++++++++-----------
 2 files changed, 20 insertions(+), 20 deletions(-)

diff --git a/README.md b/README.md
index 540dbb419..260cb34b7 100644
--- a/README.md
+++ b/README.md
@@ -2818,7 +2818,7 @@ img.show()
 ```python
 from PIL import ImageDraw
 <Draw> = ImageDraw.Draw(<Image>)                # Object for adding 2D graphics to the image.
-<Draw>.point((x, y))                            # Draws a point. Truncates floats into ints.
+<Draw>.point((x, y))                            # Draws a point. Also `fill=<int/tuple/str>`.
 <Draw>.line((x1, y1, x2, y2 [, ...]))           # For anti-aliasing use <Image>.resize((w, h)).
 <Draw>.arc((x1, y1, x2, y2), deg1, deg2)        # Draws in clockwise dir. Also pieslice().
 <Draw>.rectangle((x1, y1, x2, y2))              # Also rounded_rectangle(), regular_polygon().
@@ -2829,7 +2829,7 @@ from PIL import ImageDraw
 * **Use `'fill=<color>'` to set the primary color.**
 * **Use `'width=<int>'` to set the width of lines or contours.**
 * **Use `'outline=<color>'` to set the color of the contours.**
-* **Color can be an int, tuple, `'#rrggbb[aa]'` string or a color name.**
+* **Color can be an int, tuple, `'#rrggbb[aa]'` or a color name.**
 
 
 Animation
@@ -2989,10 +2989,10 @@ pg.init()
 screen = pg.display.set_mode((500, 500))
 rect = pg.Rect(240, 240, 20, 20)
 while not pg.event.get(pg.QUIT):
-    deltas = {pg.K_UP: (0, -20), pg.K_RIGHT: (20, 0), pg.K_DOWN: (0, 20), pg.K_LEFT: (-20, 0)}
+    deltas = {pg.K_UP: (0, -1), pg.K_RIGHT: (1, 0), pg.K_DOWN: (0, 1), pg.K_LEFT: (-1, 0)}
     for event in pg.event.get(pg.KEYDOWN):
-        dx, dy = deltas.get(event.key, (0, 0))
-        rect = rect.move((dx, dy))
+        x, y = deltas.get(event.key, (0, 0))
+        rect = rect.move((x*20, y*20))
     screen.fill(pg.Color('black'))
     pg.draw.rect(screen, pg.Color('white'), rect)
     pg.display.flip()
@@ -3003,8 +3003,8 @@ pg.quit()
 **Object for storing rectangular coordinates.**
 ```python
 <Rect> = pg.Rect(x, y, width, height)           # Creates Rect object. Truncates passed floats.
-<int>  = <Rect>.x/y/centerx/centery/…           # Top, right, bottom, left. Allows assignments.
-<tup.> = <Rect>.topleft/center/…                # Topright, bottomright, bottomleft. Same.
+<int>  = <Rect>.x/y/centerx/centery/…           # `top/right/bottom/left`. Allows assignments.
+<tup.> = <Rect>.topleft/center/…                # `topright/bottomright/bottomleft`. Same.
 <Rect> = <Rect>.move((delta_x, delta_y))        # Use move_ip() to move in-place.
 ```
 
@@ -3026,7 +3026,7 @@ pg.quit()
 ```
 
 ```python
-<Surf>.fill(color)                              # Tuple, Color('#rrggbb[aa]') or Color(<name>).
+<Surf>.fill(color)                              # Pass tuple or pg.Color('<name/hex_code>').
 <Surf>.set_at((x, y), color)                    # Updates pixel. Also <Surf>.get_at((x, y)).
 <Surf>.blit(<Surf>, (x, y))                     # Draws passed surface at specified location.
 ```
@@ -3185,7 +3185,7 @@ Name: a, dtype: int64
 ```python
 <S>.plot.line/area/bar/pie/hist()              # Generates a plot. `plt.show()` displays it.
 ```
-* **Also `'<S>.quantile(<float/coll>)'` and `'pd.cut(<S>, bins=<int/coll>)'`.**
+* **Use `'print(<S>.to_string())'` to print a Series that has more than 60 items.**
 * **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`.**
 * **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
 * **Series will silently overflow if we run `'pd.Series([100], dtype="int8") + 100'`!**
diff --git a/index.html b/index.html
index 623614088..dcd57219a 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>April 22, 2025</aside>
+    <aside>April 27, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2312,7 +2312,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <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
 &lt;Draw&gt; = ImageDraw.Draw(&lt;Image&gt;)                <span class="hljs-comment"># Object for adding 2D graphics to the image.</span>
-&lt;Draw&gt;.point((x, y))                            <span class="hljs-comment"># Draws a point. Truncates floats into ints.</span>
+&lt;Draw&gt;.point((x, y))                            <span class="hljs-comment"># Draws a point. Also `fill=&lt;int/tuple/str&gt;`.</span>
 &lt;Draw&gt;.line((x1, y1, x2, y2 [, ...]))           <span class="hljs-comment"># For anti-aliasing use &lt;Image&gt;.resize((w, h)).</span>
 &lt;Draw&gt;.arc((x1, y1, x2, y2), deg1, deg2)        <span class="hljs-comment"># Draws in clockwise dir. Also pieslice().</span>
 &lt;Draw&gt;.rectangle((x1, y1, x2, y2))              <span class="hljs-comment"># Also rounded_rectangle(), regular_polygon().</span>
@@ -2325,7 +2325,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'fill=&lt;color&gt;'</span></code> to set the primary color.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'width=&lt;int&gt;'</span></code> to set the width of lines or contours.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'outline=&lt;color&gt;'</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> string or a color name.</strong></li>
+<li><strong>Color can be an int, tuple, <code class="python hljs"><span class="hljs-string">'#rrggbb[aa]'</span></code> or a 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
@@ -2452,10 +2452,10 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 screen = 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):
-    deltas = {pg.K_UP: (<span class="hljs-number">0</span>, <span class="hljs-number">-20</span>), pg.K_RIGHT: (<span class="hljs-number">20</span>, <span class="hljs-number">0</span>), pg.K_DOWN: (<span class="hljs-number">0</span>, <span class="hljs-number">20</span>), pg.K_LEFT: (<span class="hljs-number">-20</span>, <span class="hljs-number">0</span>)}
+    deltas = {pg.K_UP: (<span class="hljs-number">0</span>, <span class="hljs-number">-1</span>), pg.K_RIGHT: (<span class="hljs-number">1</span>, <span class="hljs-number">0</span>), pg.K_DOWN: (<span class="hljs-number">0</span>, <span class="hljs-number">1</span>), pg.K_LEFT: (<span class="hljs-number">-1</span>, <span class="hljs-number">0</span>)}
     <span class="hljs-keyword">for</span> event <span class="hljs-keyword">in</span> pg.event.get(pg.KEYDOWN):
-        dx, dy = deltas.get(event.key, (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>))
-        rect = rect.move((dx, dy))
+        x, y = deltas.get(event.key, (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>))
+        rect = rect.move((x*<span class="hljs-number">20</span>, y*<span class="hljs-number">20</span>))
     screen.fill(pg.Color(<span class="hljs-string">'black'</span>))
     pg.draw.rect(screen, pg.Color(<span class="hljs-string">'white'</span>), rect)
     pg.display.flip()
@@ -2464,8 +2464,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 <div><h3 id="rect">Rect</h3><p><strong>Object for storing rectangular coordinates.</strong></p><pre><code class="python language-python hljs">&lt;Rect&gt; = pg.Rect(x, y, width, height)           <span class="hljs-comment"># Creates Rect object. Truncates passed floats.</span>
-&lt;int&gt;  = &lt;Rect&gt;.x/y/centerx/centery/…           <span class="hljs-comment"># Top, right, bottom, left. Allows assignments.</span>
-&lt;tup.&gt; = &lt;Rect&gt;.topleft/center/…                <span class="hljs-comment"># Topright, bottomright, bottomleft. Same.</span>
+&lt;int&gt;  = &lt;Rect&gt;.x/y/centerx/centery/…           <span class="hljs-comment"># `top/right/bottom/left`. Allows assignments.</span>
+&lt;tup.&gt; = &lt;Rect&gt;.topleft/center/…                <span class="hljs-comment"># `topright/bottomright/bottomleft`. Same.</span>
 &lt;Rect&gt; = &lt;Rect&gt;.move((delta_x, delta_y))        <span class="hljs-comment"># Use move_ip() to move in-place.</span>
 </code></pre></div>
 
@@ -2483,7 +2483,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 
-<pre><code class="python language-python hljs">&lt;Surf&gt;.fill(color)                              <span class="hljs-comment"># Tuple, Color('#rrggbb[aa]') or Color(&lt;name&gt;).</span>
+<pre><code class="python language-python hljs">&lt;Surf&gt;.fill(color)                              <span class="hljs-comment"># Pass tuple or pg.Color('&lt;name/hex_code&gt;').</span>
 &lt;Surf&gt;.set_at((x, y), color)                    <span class="hljs-comment"># Updates pixel. Also &lt;Surf&gt;.get_at((x, y)).</span>
 &lt;Surf&gt;.blit(&lt;Surf&gt;, (x, y))                     <span class="hljs-comment"># Draws passed surface at specified location.</span>
 </code></pre>
@@ -2613,7 +2613,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. `plt.show()` displays it.</span>
 </code></pre>
 <ul>
-<li><strong>Also <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.quantile(&lt;float/coll&gt;)'</span></code> and <code class="python hljs"><span class="hljs-string">'pd.cut(&lt;S&gt;, bins=&lt;int/coll&gt;)'</span></code>.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'print(&lt;S&gt;.to_string())'</span></code> to print a Series that has more than 60 items.</strong></li>
 <li><strong>Indexing objects can't be tuples 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>.</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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
 <li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
@@ -2944,7 +2944,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>April 22, 2025</aside>
+    <aside>April 27, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From f516ffe1e52d50323d0f99e6060a5eaf1be751ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 27 Apr 2025 18:45:26 +0200
Subject: [PATCH 125/186] Pygame

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 260cb34b7..6155e96e1 100644
--- a/README.md
+++ b/README.md
@@ -3026,7 +3026,7 @@ pg.quit()
 ```
 
 ```python
-<Surf>.fill(color)                              # Pass tuple or pg.Color('<name/hex_code>').
+<Surf>.fill(color)                              # Pass tuple or pg.Color('<name/rgb_code>').
 <Surf>.set_at((x, y), color)                    # Updates pixel. Also <Surf>.get_at((x, y)).
 <Surf>.blit(<Surf>, (x, y))                     # Draws passed surface at specified location.
 ```
diff --git a/index.html b/index.html
index dcd57219a..f922aeb3c 100644
--- a/index.html
+++ b/index.html
@@ -2483,7 +2483,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 
-<pre><code class="python language-python hljs">&lt;Surf&gt;.fill(color)                              <span class="hljs-comment"># Pass tuple or pg.Color('&lt;name/hex_code&gt;').</span>
+<pre><code class="python language-python hljs">&lt;Surf&gt;.fill(color)                              <span class="hljs-comment"># Pass tuple or pg.Color('&lt;name/rgb_code&gt;').</span>
 &lt;Surf&gt;.set_at((x, y), color)                    <span class="hljs-comment"># Updates pixel. Also &lt;Surf&gt;.get_at((x, y)).</span>
 &lt;Surf&gt;.blit(&lt;Surf&gt;, (x, y))                     <span class="hljs-comment"># Draws passed surface at specified location.</span>
 </code></pre>

From 226d77a1acb9dffb330a02b6ce09aadccfb9cf53 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 27 Apr 2025 19:06:06 +0200
Subject: [PATCH 126/186] Pygame

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 6155e96e1..b79562d9d 100644
--- a/README.md
+++ b/README.md
@@ -3026,7 +3026,7 @@ pg.quit()
 ```
 
 ```python
-<Surf>.fill(color)                              # Pass tuple or pg.Color('<name/rgb_code>').
+<Surf>.fill(color)                              # Pass tuple of ints or pg.Color('<name/hex>').
 <Surf>.set_at((x, y), color)                    # Updates pixel. Also <Surf>.get_at((x, y)).
 <Surf>.blit(<Surf>, (x, y))                     # Draws passed surface at specified location.
 ```
diff --git a/index.html b/index.html
index f922aeb3c..f64096469 100644
--- a/index.html
+++ b/index.html
@@ -2483,7 +2483,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 
-<pre><code class="python language-python hljs">&lt;Surf&gt;.fill(color)                              <span class="hljs-comment"># Pass tuple or pg.Color('&lt;name/rgb_code&gt;').</span>
+<pre><code class="python language-python hljs">&lt;Surf&gt;.fill(color)                              <span class="hljs-comment"># Pass tuple of ints or pg.Color('&lt;name/hex&gt;').</span>
 &lt;Surf&gt;.set_at((x, y), color)                    <span class="hljs-comment"># Updates pixel. Also &lt;Surf&gt;.get_at((x, y)).</span>
 &lt;Surf&gt;.blit(&lt;Surf&gt;, (x, y))                     <span class="hljs-comment"># Draws passed surface at specified location.</span>
 </code></pre>

From d252dfebe9584234839d925421caed9ce7844192 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 27 Apr 2025 19:56:45 +0200
Subject: [PATCH 127/186] Tuple, Enumerate, Iterator

---
 README.md  | 19 +++++++++----------
 index.html | 20 +++++++++-----------
 2 files changed, 18 insertions(+), 21 deletions(-)

diff --git a/README.md b/README.md
index b79562d9d..d8339672c 100644
--- a/README.md
+++ b/README.md
@@ -165,14 +165,11 @@ Tuple
 ```python
 >>> from collections import namedtuple
 >>> Point = namedtuple('Point', 'x y')
->>> p = Point(1, y=2); p
+>>> p = Point(1, y=2)
+>>> print(p)
 Point(x=1, y=2)
->>> p[0]
-1
->>> p.x
-1
->>> getattr(p, 'y')
-2
+>>> p[0], p.x
+(1, 1)
 ```
 
 
@@ -180,9 +177,9 @@ Range
 -----
 **Immutable and hashable sequence of integers.**
 ```python
-<range> = range(stop)                      # range(to_exclusive)
-<range> = range(start, stop)               # range(from_inclusive, to_exclusive)
-<range> = range(start, stop, ±step)        # range(from_inclusive, to_exclusive, ±step_size)
+<range> = range(stop)                      # I.e. range(to_exclusive).
+<range> = range(start, stop)               # I.e. range(from_inclusive, to_exclusive).
+<range> = range(start, stop, ±step)        # I.e. range(from_inclusive, to_exclusive, ±step).
 ```
 
 ```python
@@ -201,6 +198,8 @@ for i, el in enumerate(<coll>, start=0):   # Returns next element and its index
 
 Iterator
 --------
+**Potentially endless stream of elements.**
+
 ```python
 <iter> = iter(<collection>)                # `iter(<iter>)` returns unmodified iterator.
 <iter> = iter(<function>, to_exclusive)    # A sequence of return values until 'to_exclusive'.
diff --git a/index.html b/index.html
index f64096469..891bd5328 100644
--- a/index.html
+++ b/index.html
@@ -206,20 +206,17 @@
 
 <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">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> namedtuple
 <span class="hljs-meta">&gt;&gt;&gt; </span>Point = namedtuple(<span class="hljs-string">'Point'</span>, <span class="hljs-string">'x y'</span>)
-<span class="hljs-meta">&gt;&gt;&gt; </span>p = Point(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>); p
+<span class="hljs-meta">&gt;&gt;&gt; </span>p = Point(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>)
+<span class="hljs-meta">&gt;&gt;&gt; </span>print(p)
 Point(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>)
-<span class="hljs-meta">&gt;&gt;&gt; </span>p[<span class="hljs-number">0</span>]
-<span class="hljs-number">1</span>
-<span class="hljs-meta">&gt;&gt;&gt; </span>p.x
-<span class="hljs-number">1</span>
-<span class="hljs-meta">&gt;&gt;&gt; </span>getattr(p, <span class="hljs-string">'y'</span>)
-<span class="hljs-number">2</span>
+<span class="hljs-meta">&gt;&gt;&gt; </span>p[<span class="hljs-number">0</span>], p.x
+(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>)
 </code></pre></div>
 
 
-<div><h2 id="range"><a href="#range" name="range">#</a>Range</h2><p><strong>Immutable and hashable sequence of integers.</strong></p><pre><code class="python language-python hljs">&lt;range&gt; = range(stop)                      <span class="hljs-comment"># range(to_exclusive)</span>
-&lt;range&gt; = range(start, stop)               <span class="hljs-comment"># range(from_inclusive, to_exclusive)</span>
-&lt;range&gt; = range(start, stop, ±step)        <span class="hljs-comment"># range(from_inclusive, to_exclusive, ±step_size)</span>
+<div><h2 id="range"><a href="#range" name="range">#</a>Range</h2><p><strong>Immutable and hashable sequence of integers.</strong></p><pre><code class="python language-python hljs">&lt;range&gt; = range(stop)                      <span class="hljs-comment"># I.e. range(to_exclusive).</span>
+&lt;range&gt; = range(start, stop)               <span class="hljs-comment"># I.e. range(from_inclusive, to_exclusive).</span>
+&lt;range&gt; = range(start, stop, ±step)        <span class="hljs-comment"># I.e. range(from_inclusive, to_exclusive, ±step).</span>
 </code></pre></div>
 
 
@@ -230,12 +227,13 @@
     ...
 </code></pre></div>
 
-<div><h2 id="iterator"><a href="#iterator" name="iterator">#</a>Iterator</h2><pre><code class="python language-python hljs">&lt;iter&gt; = iter(&lt;collection&gt;)                <span class="hljs-comment"># `iter(&lt;iter&gt;)` returns unmodified iterator.</span>
+<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">&lt;iter&gt; = iter(&lt;collection&gt;)                <span class="hljs-comment"># `iter(&lt;iter&gt;)` returns unmodified iterator.</span>
 &lt;iter&gt; = iter(&lt;function&gt;, to_exclusive)    <span class="hljs-comment"># A sequence of return values until 'to_exclusive'.</span>
 &lt;el&gt;   = next(&lt;iter&gt; [, default])          <span class="hljs-comment"># Raises StopIteration or returns 'default' on end.</span>
 &lt;list&gt; = list(&lt;iter&gt;)                      <span class="hljs-comment"># Returns a list of iterator's remaining elements.</span>
 </code></pre></div>
 
+
 <div><h3 id="itertools">Itertools</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> itertools <span class="hljs-keyword">as</span> it
 </code></pre></div>
 

From cd34692e33ff203a7e565063db8ad56e99cbe4b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 30 Apr 2025 03:31:49 +0200
Subject: [PATCH 128/186] Datetime, Duck types, Pandas

---
 README.md  | 19 ++++++++++---------
 index.html | 25 ++++++++++++-------------
 2 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/README.md b/README.md
index d8339672c..a193b501d 100644
--- a/README.md
+++ b/README.md
@@ -603,7 +603,7 @@ import zoneinfo, dateutil.tz
 <DT> = datetime(year, month, day, hour=0)   # Also: `minute=0, second=0, microsecond=0, …`.
 <TD> = timedelta(weeks=0, days=0, hours=0)  # Also: `minutes=0, seconds=0, microseconds=0`.
 ```
-* **Aware times and datetimes have defined timezone, while naive don't. If object is naive, it is presumed to be in the system's timezone!**
+* **Times and datetimes that have defined timezone are called aware and ones that don't, naive. If object is naive, it is presumed to be in the system's timezone!**
 * **`'fold=1'` means the second pass in case of time jumping back for one hour.**
 * **Timedelta normalizes arguments to ±days, seconds (< 86 400) and microseconds (< 1M). Its str() method returns `'[±D, ]H:MM:SS[.…]'` and total_seconds() a float of all seconds.**
 * **Use `'<D/DT>.weekday()'` to get the day of the week as an int, with Monday being 0.**
@@ -1155,7 +1155,8 @@ class MySortable:
 ### Iterator
 * **Any object that has methods next() and iter() is an iterator.**
 * **Next() should return next item or raise StopIteration exception.**
-* **Iter() should return 'self', i.e. unmodified object on which it was called.**
+* **Iter() should return an iterator of remaining items, i.e. 'self'.**
+* **Only objects that have iter() method can be used in for loops.**
 ```python
 class Counter:
     def __init__(self):
@@ -1181,7 +1182,7 @@ class Counter:
 
 ### Callable
 * **All functions and classes have a call() method, hence are callable.**
-* **Use `'callable(<obj>)'` or `'isinstance(<obj>, collections.abc.Callable)'` to check if object is callable. Calling an uncallable object raises `'TypeError'`.**
+* **Use `'callable(<obj>)'` or `'isinstance(<obj>, collections.abc.Callable)'` to check if object is callable. Calling an uncallable object raises TypeError.**
 * **When this cheatsheet uses `'<function>'` as an argument, it means `'<callable>'`.**
 ```python
 class Counter:
@@ -1727,8 +1728,8 @@ os.remove(<path>)                   # Deletes the file.
 os.rmdir(<path>)                    # Deletes the empty directory.
 shutil.rmtree(<path>)               # Deletes the directory.
 ```
-* **Paths can be either strings, Paths, or DirEntry objects.**
-* **Functions report OS related errors by raising either OSError or one of its [subclasses](#exceptions-1).**
+* **Paths can be either strings, Path objects, or DirEntry objects.**
+* **Functions report OS related errors by raising OSError or one of its [subclasses](#exceptions-1).**
 
 ### Shell Commands
 ```python
@@ -2257,7 +2258,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
 <Thread>.join()                                # Waits for the thread to finish executing.
 ```
 * **Use `'kwargs=<dict>'` to pass keyword arguments to the function.**
-* **Use `'daemon=True'`, or the program will not be able to exit while the thread is alive.**
+* **Use `'daemon=True'`, or program won't be able to exit while the thread is alive.**
 
 ### Lock
 ```python
@@ -3185,9 +3186,10 @@ Name: a, dtype: int64
 <S>.plot.line/area/bar/pie/hist()              # Generates a plot. `plt.show()` displays it.
 ```
 * **Use `'print(<S>.to_string())'` to print a Series that has more than 60 items.**
-* **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`.**
+* **Use `'<S>.index'` to get collection of keys and `'<S>.index = <coll>'` to update them.**
+* **Only pass a list or Series to loc/iloc because `'obj[x, y]'` is converted to `'obj[(x, y)]'` and `'<S>.loc[key_1, key_2]'` is how you retrieve a value from a multi-indexed Series.**
 * **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
-* **Series will silently overflow if we run `'pd.Series([100], dtype="int8") + 100'`!**
+* **Series will silently overflow if you run `'pd.Series([100], dtype="int8") + 100'`!**
 
 #### Series — Aggregate, Transform, Map:
 ```python
@@ -3214,7 +3216,6 @@ Name: a, dtype: int64
 |              |    y  2.0   |   y   2.0   |      y  2.0   |
 +--------------+-------------+-------------+---------------+
 ```
-* **Last result has a multi-index. Use `'<S>[key_1, key_2]'` to get its values.**
 
 ### DataFrame
 **Table with labeled rows and columns.**
diff --git a/index.html b/index.html
index 891bd5328..adae251cd 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>April 27, 2025</aside>
+    <aside>April 30, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -536,7 +536,7 @@
 &lt;TD&gt; = 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"># Also: `minutes=0, seconds=0, microseconds=0`.</span>
 </code></pre>
 <ul>
-<li><strong>Aware times and datetimes have defined timezone, while naive don't. If object is naive, it is presumed to be in the system's timezone!</strong></li>
+<li><strong>Times and datetimes that have defined timezone are called aware and ones that don't, naive. If 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 for one hour.</strong></li>
 <li><strong>Timedelta normalizes arguments to ±days, seconds (&lt; 86 400) and microseconds (&lt; 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 all seconds.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'&lt;D/DT&gt;.weekday()'</span></code> to get the day of the week as an int, with Monday being 0.</strong></li>
@@ -988,7 +988,8 @@
 <div><h3 id="iterator-1">Iterator</h3><ul>
 <li><strong>Any object that has methods next() and iter() is an iterator.</strong></li>
 <li><strong>Next() should return next item or raise StopIteration exception.</strong></li>
-<li><strong>Iter() should return 'self', i.e. unmodified object on which it was called.</strong></li>
+<li><strong>Iter() should return an iterator of remaining items, i.e. 'self'.</strong></li>
+<li><strong>Only objects that have iter() method can be used in for loops.</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>
@@ -1011,7 +1012,7 @@
 <li><strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong></li>
 </ul><div><h3 id="callable">Callable</h3><ul>
 <li><strong>All functions and classes have a call() method, hence are callable.</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'callable(&lt;obj&gt;)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(&lt;obj&gt;, collections.abc.Callable)'</span></code> to check if object is callable. Calling an uncallable object raises <code class="python hljs"><span class="hljs-string">'TypeError'</span></code>.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'callable(&lt;obj&gt;)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(&lt;obj&gt;, collections.abc.Callable)'</span></code> to check if object is callable. Calling an uncallable object raises TypeError.</strong></li>
 <li><strong>When this cheatsheet uses <code class="python hljs"><span class="hljs-string">'&lt;function&gt;'</span></code> as an argument, it means <code class="python hljs"><span class="hljs-string">'&lt;callable&gt;'</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>
@@ -1460,8 +1461,8 @@
 shutil.rmtree(&lt;path&gt;)               <span class="hljs-comment"># Deletes the directory.</span>
 </code></pre>
 <ul>
-<li><strong>Paths can be either strings, Paths, or DirEntry objects.</strong></li>
-<li><strong>Functions report OS related errors by raising either OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong></li>
+<li><strong>Paths can be either strings, Path objects, or DirEntry objects.</strong></li>
+<li><strong>Functions report OS related errors by raising OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong></li>
 </ul>
 <div><h3 id="shellcommands">Shell Commands</h3><pre><code class="python language-python hljs">&lt;pipe&gt; = os.popen(<span class="hljs-string">'&lt;commands&gt;'</span>)     <span class="hljs-comment"># Executes commands in sh/cmd. Returns combined stdout.</span>
 &lt;str&gt;  = &lt;pipe&gt;.read(size=<span class="hljs-number">-1</span>)       <span class="hljs-comment"># Reads 'size' chars or until EOF. Also readline/s().</span>
@@ -1865,7 +1866,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <ul>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'kwargs=&lt;dict&gt;'</span></code> to pass keyword arguments to the function.</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'daemon=True'</span></code>, or the program will not be able to exit while the thread is alive.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'daemon=True'</span></code>, or program won't be able to exit while the thread is alive.</strong></li>
 </ul>
 <div><h3 id="lock">Lock</h3><pre><code class="python language-python hljs">&lt;lock&gt; = Lock/RLock()                          <span class="hljs-comment"># RLock can only be released by acquirer.</span>
 &lt;lock&gt;.acquire()                               <span class="hljs-comment"># Waits for the lock to be available.</span>
@@ -2612,9 +2613,10 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <ul>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'print(&lt;S&gt;.to_string())'</span></code> to print a Series that has more than 60 items.</strong></li>
-<li><strong>Indexing objects can't be tuples 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>.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.index'</span></code> to get collection of keys and <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.index = &lt;coll&gt;'</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">'&lt;S&gt;.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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
-<li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
+<li><strong>Series will silently overflow if you run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
 </ul>
 <div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.sum/max/mean/std/idxmax/count()     <span class="hljs-comment"># Or: &lt;S&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;S&gt;  = &lt;S&gt;.rank/diff/cumsum/ffill/interpol…()  <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>
@@ -2637,9 +2639,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 ┗━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛
 </code></pre>
 
-<ul>
-<li><strong>Last result has a multi-index. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;[key_1, key_2]'</span></code> to get its values.</strong></li>
-</ul>
 <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">&gt;&gt;&gt; </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>
@@ -2942,7 +2941,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>April 27, 2025</aside>
+    <aside>April 30, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 0c986f0183c4556a6e4914cc3f9aaaaef4e6e610 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 30 Apr 2025 04:08:33 +0200
Subject: [PATCH 129/186] Pandas

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index a193b501d..68364c2de 100644
--- a/README.md
+++ b/README.md
@@ -3189,7 +3189,7 @@ Name: a, dtype: int64
 * **Use `'<S>.index'` to get collection of keys and `'<S>.index = <coll>'` to update them.**
 * **Only pass a list or Series to loc/iloc because `'obj[x, y]'` is converted to `'obj[(x, y)]'` and `'<S>.loc[key_1, key_2]'` is how you retrieve a value from a multi-indexed Series.**
 * **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
-* **Series will silently overflow if you run `'pd.Series([100], dtype="int8") + 100'`!**
+* **Series will silently overflow if we run `'pd.Series([100], dtype="int8") + 100'`!**
 
 #### Series — Aggregate, Transform, Map:
 ```python
diff --git a/index.html b/index.html
index adae251cd..f09fa1ddd 100644
--- a/index.html
+++ b/index.html
@@ -2616,7 +2616,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.index'</span></code> to get collection of keys and <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.index = &lt;coll&gt;'</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">'&lt;S&gt;.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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
-<li><strong>Series will silently overflow if you run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
+<li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
 </ul>
 <div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.sum/max/mean/std/idxmax/count()     <span class="hljs-comment"># Or: &lt;S&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;S&gt;  = &lt;S&gt;.rank/diff/cumsum/ffill/interpol…()  <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>

From 619490503e58881533a1e3e00c30566e26a49316 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 30 Apr 2025 04:43:55 +0200
Subject: [PATCH 130/186] Pandas

---
 README.md  | 1 -
 index.html | 1 -
 2 files changed, 2 deletions(-)

diff --git a/README.md b/README.md
index 68364c2de..c8358e4f7 100644
--- a/README.md
+++ b/README.md
@@ -3189,7 +3189,6 @@ Name: a, dtype: int64
 * **Use `'<S>.index'` to get collection of keys and `'<S>.index = <coll>'` to update them.**
 * **Only pass a list or Series to loc/iloc because `'obj[x, y]'` is converted to `'obj[(x, y)]'` and `'<S>.loc[key_1, key_2]'` is how you retrieve a value from a multi-indexed Series.**
 * **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
-* **Series will silently overflow if we run `'pd.Series([100], dtype="int8") + 100'`!**
 
 #### Series — Aggregate, Transform, Map:
 ```python
diff --git a/index.html b/index.html
index f09fa1ddd..7c52e276a 100644
--- a/index.html
+++ b/index.html
@@ -2616,7 +2616,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.index'</span></code> to get collection of keys and <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.index = &lt;coll&gt;'</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">'&lt;S&gt;.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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted Series.</strong></li>
-<li><strong>Series will silently overflow if we run <code class="python hljs"><span class="hljs-string">'pd.Series([100], dtype="int8") + 100'</span></code>!</strong></li>
 </ul>
 <div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs">&lt;el&gt; = &lt;S&gt;.sum/max/mean/std/idxmax/count()     <span class="hljs-comment"># Or: &lt;S&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;S&gt;  = &lt;S&gt;.rank/diff/cumsum/ffill/interpol…()  <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>

From dba864aef1fe019224ef99e839b7382ef7d57a87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 30 Apr 2025 04:51:49 +0200
Subject: [PATCH 131/186] Duck types

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index c8358e4f7..8a41909fb 100644
--- a/README.md
+++ b/README.md
@@ -1156,7 +1156,7 @@ class MySortable:
 * **Any object that has methods next() and iter() is an iterator.**
 * **Next() should return next item or raise StopIteration exception.**
 * **Iter() should return an iterator of remaining items, i.e. 'self'.**
-* **Only objects that have iter() method can be used in for loops.**
+* **Any object that has iter() method can be used in a for loop.**
 ```python
 class Counter:
     def __init__(self):
diff --git a/index.html b/index.html
index 7c52e276a..df7e54300 100644
--- a/index.html
+++ b/index.html
@@ -989,7 +989,7 @@
 <li><strong>Any object that has methods next() and iter() is an iterator.</strong></li>
 <li><strong>Next() should return next item or raise StopIteration exception.</strong></li>
 <li><strong>Iter() should return an iterator of remaining items, i.e. 'self'.</strong></li>
-<li><strong>Only objects that have iter() method can be used in for loops.</strong></li>
+<li><strong>Any object that has iter() 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>

From 1c920d17c6b48b4a291e9379978836593ab24f69 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 1 May 2025 18:28:05 +0200
Subject: [PATCH 132/186] Splat operator

---
 README.md  | 25 +++++++++++++------------
 index.html | 29 ++++++++++++++---------------
 parse.js   | 17 ++++++++---------
 3 files changed, 35 insertions(+), 36 deletions(-)

diff --git a/README.md b/README.md
index 8a41909fb..683dfdf27 100644
--- a/README.md
+++ b/README.md
@@ -705,23 +705,24 @@ func(1, 2, z=3)
 ### Inside Function Definition
 **Splat combines zero or more positional arguments into a tuple, while splatty-splat combines zero or more keyword arguments into a dictionary.**
 ```python
->>> def add(*a):
-...     return sum(a)
-...
+def add(*a):
+    return sum(a)
+```
+
+```python
 >>> add(1, 2, 3)
 6
 ```
 
-#### Allowed compositions of arguments inside function definition and the ways they can be called:
+#### Allowed compositions of arguments and the ways they can be called:
 ```text
-+--------------------+------------+--------------+----------------+------------------+
-|                    | f(1, 2, 3) | f(1, 2, z=3) | f(1, y=2, z=3) | f(x=1, y=2, z=3) |
-+--------------------+------------+--------------+----------------+------------------+
-| f(x, *args, **kw): |     yes    |      yes     |       yes      |       yes        |
-| f(*args, z, **kw): |            |      yes     |       yes      |       yes        |
-| f(x, **kw):        |            |              |       yes      |       yes        |
-| f(*, x, **kw):     |            |              |                |       yes        |
-+--------------------+------------+--------------+----------------+------------------+
++---------------------------+--------------+--------------+----------------+
+|                           |  func(1, 2)  | func(1, y=2) | func(x=1, y=2) |
++---------------------------+--------------+--------------+----------------+
+| func(x, *args, **kwargs): |     yes      |     yes      |      yes       |
+| func(*args, y, **kwargs): |              |     yes      |      yes       |
+| func(*, x, **kwargs):     |              |              |      yes       |
++---------------------------+--------------+--------------+----------------+
 ```
 
 ### Other Uses
diff --git a/index.html b/index.html
index df7e54300..1b924d0be 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>April 30, 2025</aside>
+    <aside>May 1, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -620,22 +620,21 @@
 <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="insidefunctiondefinition">Inside Function Definition</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-meta">&gt;&gt;&gt; </span><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add</span><span class="hljs-params">(*a)</span>:</span>
-<span class="hljs-meta">... </span>    <span class="hljs-keyword">return</span> sum(a)
-<span class="hljs-meta">... </span>
-<span class="hljs-meta">&gt;&gt;&gt; </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>
+<div><h3 id="insidefunctiondefinition">Inside Function Definition</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">(*a)</span>:</span>
+    <span class="hljs-keyword">return</span> sum(a)
 </code></pre></div>
 
 
-<div><h4 id="allowedcompositionsofargumentsinsidefunctiondefinitionandthewaystheycanbecalled">Allowed compositions of arguments inside function definition and the ways they can be called:</h4><pre><code class="text language-text">┏━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━┓
-┃                    │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) ┃
-┠────────────────────┼────────────┼──────────────┼────────────────┼──────────────────┨
-┃ <span class="hljs-title">f</span>(x, *args, **kw): │      ✓     │       ✓      │        ✓       │        ✓         ┃
-┃ <span class="hljs-title">f</span>(*args, z, **kw): │            │       ✓      │        ✓       │        ✓         ┃
-┃ <span class="hljs-title">f</span>(x, **kw):        │            │              │        ✓       │        ✓         ┃
-┃ <span class="hljs-title">f</span>(*, x, **kw):     │            │              │                │        ✓         ┃
-┗━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┛
+<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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>
+<div><h4 id="allowedcompositionsofargumentsandthewaystheycanbecalled">Allowed compositions of arguments and the ways they can be called:</h4><pre><code class="text language-text">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┓
+┃                           │  func(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)  │ func(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>) │ func(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>) ┃
+┠───────────────────────────┼──────────────┼──────────────┼────────────────┨
+┃ <span class="hljs-title">func</span>(x, *args, **kwargs): │      ✓       │      ✓       │       ✓        ┃
+┃ <span class="hljs-title">func</span>(*args, y, **kwargs): │              │      ✓       │       ✓        ┃
+┃ <span class="hljs-title">func</span>(*, x, **kwargs):     │              │              │       ✓        ┃
+┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┛
 </code></pre></div>
 
 <div><h3 id="otheruses">Other Uses</h3><pre><code class="python language-python hljs">&lt;list&gt;  = [*&lt;collection&gt; [, ...]]  <span class="hljs-comment"># Or: list(&lt;coll&gt;) [+ ...]</span>
@@ -2940,7 +2939,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>April 30, 2025</aside>
+    <aside>May 1, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index c1e0bd165..c06fa0dc3 100755
--- a/parse.js
+++ b/parse.js
@@ -424,17 +424,16 @@ const DIAGRAM_5_A =
   "+--------------+----------------+----------------+----------------+----------------+\n";
 
 const DIAGRAM_55_A =
-  "+--------------------+------------+--------------+----------------+------------------+\n";
+  "+---------------------------+--------------+--------------+----------------+\n";
 
 const DIAGRAM_55_B =
-  '┏━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━┓\n' +
-  '┃                    │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) │ f(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>, z=<span class="hljs-number">3</span>) ┃\n' +
-  '┠────────────────────┼────────────┼──────────────┼────────────────┼──────────────────┨\n' +
-  '┃ <span class="hljs-title">f</span>(x, *args, **kw): │      ✓     │       ✓      │        ✓       │        ✓         ┃\n' +
-  '┃ <span class="hljs-title">f</span>(*args, z, **kw): │            │       ✓      │        ✓       │        ✓         ┃\n' +
-  '┃ <span class="hljs-title">f</span>(x, **kw):        │            │              │        ✓       │        ✓         ┃\n' +
-  '┃ <span class="hljs-title">f</span>(*, x, **kw):     │            │              │                │        ✓         ┃\n' +
-  '┗━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┛\n';
+  '┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━┓\n' +
+  '┃                           │  func(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)  │ func(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>) │ func(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>) ┃\n' +
+  '┠───────────────────────────┼──────────────┼──────────────┼────────────────┨\n' +
+  '┃ <span class="hljs-title">func</span>(x, *args, **kwargs): │      ✓       │      ✓       │       ✓        ┃\n' +
+  '┃ <span class="hljs-title">func</span>(*args, y, **kwargs): │              │      ✓       │       ✓        ┃\n' +
+  '┃ <span class="hljs-title">func</span>(*, x, **kwargs):     │              │              │       ✓        ┃\n' +
+  '┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━┛\n';
 
 const DIAGRAM_6_A =
   '+------------+------------+------------+------------+--------------+\n' +

From 20f779903e8fa3b408fcda6fa8ec10ad82872078 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 2 May 2025 00:04:58 +0200
Subject: [PATCH 133/186] Pandas

---
 README.md  | 3 ++-
 index.html | 3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 683dfdf27..9149f30d3 100644
--- a/README.md
+++ b/README.md
@@ -3184,7 +3184,8 @@ Name: a, dtype: int64
 ```
 
 ```python
-<S>.plot.line/area/bar/pie/hist()              # Generates a plot. `plt.show()` displays it.
+<S>.plot.line/area/bar/pie/hist()              # Generates a plot. Accepts `title=<str>`.
+plt.show()                                     # Displays the plot. Also plt.savefig(<path>).
 ```
 * **Use `'print(<S>.to_string())'` to print a Series that has more than 60 items.**
 * **Use `'<S>.index'` to get collection of keys and `'<S>.index = <coll>'` to update them.**
diff --git a/index.html b/index.html
index 1b924d0be..3e580c915 100644
--- a/index.html
+++ b/index.html
@@ -2608,7 +2608,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;S&gt;  = &lt;S&gt;.dt.year/month/day/hour              <span class="hljs-comment"># Use pd.to_datetime(&lt;S&gt;) to get S of datetimes.</span>
 &lt;S&gt;  = &lt;S&gt;.dt.to_period(<span class="hljs-string">'y/m/d/h'</span>)             <span class="hljs-comment"># Quantizes datetimes into Period objects.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. `plt.show()` displays it.</span>
+<pre><code class="python language-python hljs">&lt;S&gt;.plot.line/area/bar/pie/hist()              <span class="hljs-comment"># Generates a plot. Accepts `title=&lt;str&gt;`.</span>
+plt.show()                                     <span class="hljs-comment"># Displays the plot. Also plt.savefig(&lt;path&gt;).</span>
 </code></pre>
 <ul>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'print(&lt;S&gt;.to_string())'</span></code> to print a Series that has more than 60 items.</strong></li>

From 2d08cb5eee24704c5d3679ad18050a850c42a531 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 2 May 2025 19:06:21 +0200
Subject: [PATCH 134/186] Open, Paths

---
 README.md  | 4 ++--
 index.html | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 9149f30d3..39fde71f3 100644
--- a/README.md
+++ b/README.md
@@ -1600,7 +1600,7 @@ Open
 ```
 
 ```python
-<file>.write(<str/bytes>)           # Writes a string or bytes object.
+<file>.write(<str/bytes>)           # Writes a string or bytes object to the file.
 <file>.writelines(<collection>)     # Writes a coll. of strings or bytes objects.
 <file>.flush()                      # Flushes write buffer. Runs every 4096/8192 B.
 <file>.close()                      # Closes the file after flushing write buffer.
@@ -1707,7 +1707,7 @@ import os, shutil, subprocess
 ```
 
 ```python
-os.chdir(<path>)                    # Changes the current working directory.
+os.chdir(<path>)                    # Changes the current working directory (CWD).
 os.mkdir(<path>, mode=0o777)        # Creates a directory. Permissions are in octal.
 os.makedirs(<path>, mode=0o777)     # Creates all path's dirs. Also `exist_ok=False`.
 ```
diff --git a/index.html b/index.html
index 3e580c915..475643d13 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 1, 2025</aside>
+    <aside>May 2, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1371,7 +1371,7 @@
 &lt;list&gt;      = &lt;file&gt;.readlines()    <span class="hljs-comment"># Returns a list of remaining lines.</span>
 &lt;str/bytes&gt; = next(&lt;file&gt;)          <span class="hljs-comment"># Returns a line using buffer. Do not mix.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;file&gt;.write(&lt;str/bytes&gt;)           <span class="hljs-comment"># Writes a string or bytes object.</span>
+<pre><code class="python language-python hljs">&lt;file&gt;.write(&lt;str/bytes&gt;)           <span class="hljs-comment"># Writes a string or bytes object to the file.</span>
 &lt;file&gt;.writelines(&lt;collection&gt;)     <span class="hljs-comment"># Writes a coll. of strings or bytes objects.</span>
 &lt;file&gt;.flush()                      <span class="hljs-comment"># Flushes write buffer. Runs every 4096/8192 B.</span>
 &lt;file&gt;.close()                      <span class="hljs-comment"># Closes the file after flushing write buffer.</span>
@@ -1443,7 +1443,7 @@
 <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, subprocess
 </code></pre></div>
 
-<pre><code class="python language-python hljs">os.chdir(&lt;path&gt;)                    <span class="hljs-comment"># Changes the current working directory.</span>
+<pre><code class="python language-python hljs">os.chdir(&lt;path&gt;)                    <span class="hljs-comment"># Changes the current working directory (CWD).</span>
 os.mkdir(&lt;path&gt;, mode=<span class="hljs-number">0o777</span>)        <span class="hljs-comment"># Creates a directory. Permissions are in octal.</span>
 os.makedirs(&lt;path&gt;, mode=<span class="hljs-number">0o777</span>)     <span class="hljs-comment"># Creates all path's dirs. Also `exist_ok=False`.</span>
 </code></pre>
@@ -2940,7 +2940,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 1, 2025</aside>
+    <aside>May 2, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 5328b93413030376c3d786198c3e66065086c82c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 3 May 2025 13:36:45 +0200
Subject: [PATCH 135/186] List, Paths

---
 README.md  | 4 ++--
 index.html | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 39fde71f3..ce97b3f95 100644
--- a/README.md
+++ b/README.md
@@ -29,7 +29,7 @@ if __name__ == '__main__':      # Skips next line if file was imported.
 List
 ----
 ```python
-<list> = [<el_1>, <el_2>, ...]  # Creates new list. Also list(<collection>).
+<list> = [<el_1>, <el_2>, ...]  # Creates a list object. Also list(<collection>).
 ```
 
 ```python
@@ -1664,7 +1664,7 @@ from pathlib import Path
 <iter> = os.scandir(path='.')       # Returns DirEntry objects located at the path.
 <str>  = <DirEntry>.path            # Returns the whole path as a string.
 <str>  = <DirEntry>.name            # Returns final component as a string.
-<file> = open(<DirEntry>)           # Opens the file and returns a file object.
+<file> = open(<DirEntry>)           # Opens the file and returns its file object.
 ```
 
 ### Path Object
diff --git a/index.html b/index.html
index 475643d13..0cd45a56a 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 2, 2025</aside>
+    <aside>May 3, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -111,7 +111,7 @@
     main()                      <span class="hljs-comment"># Runs `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">&lt;list&gt; = [&lt;el_1&gt;, &lt;el_2&gt;, ...]  <span class="hljs-comment"># Creates new list. Also list(&lt;collection&gt;).</span>
+<div><h2 id="list"><a href="#list" name="list">#</a>List</h2><pre><code class="python language-python hljs">&lt;list&gt; = [&lt;el_1&gt;, &lt;el_2&gt;, ...]  <span class="hljs-comment"># Creates a list object. Also list(&lt;collection&gt;).</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs">&lt;el&gt;   = &lt;list&gt;[index]          <span class="hljs-comment"># First index is 0. Last -1. Allows assignments.</span>
@@ -1414,7 +1414,7 @@
 <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">&lt;iter&gt; = os.scandir(path=<span class="hljs-string">'.'</span>)       <span class="hljs-comment"># Returns DirEntry objects located at the path.</span>
 &lt;str&gt;  = &lt;DirEntry&gt;.path            <span class="hljs-comment"># Returns the whole path as a string.</span>
 &lt;str&gt;  = &lt;DirEntry&gt;.name            <span class="hljs-comment"># Returns final component as a string.</span>
-&lt;file&gt; = open(&lt;DirEntry&gt;)           <span class="hljs-comment"># Opens the file and returns a file object.</span>
+&lt;file&gt; = open(&lt;DirEntry&gt;)           <span class="hljs-comment"># Opens the file and returns its file object.</span>
 </code></pre></div>
 
 
@@ -2940,7 +2940,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 2, 2025</aside>
+    <aside>May 3, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 05f360c493a4ad5f89bec39187a36e6bcab7c527 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 3 May 2025 17:36:39 +0200
Subject: [PATCH 136/186] Open

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index ce97b3f95..5f2e5ce8f 100644
--- a/README.md
+++ b/README.md
@@ -1600,7 +1600,7 @@ Open
 ```
 
 ```python
-<file>.write(<str/bytes>)           # Writes a string or bytes object to the file.
+<file>.write(<str/bytes>)           # Writes a string or bytes object.
 <file>.writelines(<collection>)     # Writes a coll. of strings or bytes objects.
 <file>.flush()                      # Flushes write buffer. Runs every 4096/8192 B.
 <file>.close()                      # Closes the file after flushing write buffer.
diff --git a/index.html b/index.html
index 0cd45a56a..869e1e8f7 100644
--- a/index.html
+++ b/index.html
@@ -1371,7 +1371,7 @@
 &lt;list&gt;      = &lt;file&gt;.readlines()    <span class="hljs-comment"># Returns a list of remaining lines.</span>
 &lt;str/bytes&gt; = next(&lt;file&gt;)          <span class="hljs-comment"># Returns a line using buffer. Do not mix.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;file&gt;.write(&lt;str/bytes&gt;)           <span class="hljs-comment"># Writes a string or bytes object to the file.</span>
+<pre><code class="python language-python hljs">&lt;file&gt;.write(&lt;str/bytes&gt;)           <span class="hljs-comment"># Writes a string or bytes object.</span>
 &lt;file&gt;.writelines(&lt;collection&gt;)     <span class="hljs-comment"># Writes a coll. of strings or bytes objects.</span>
 &lt;file&gt;.flush()                      <span class="hljs-comment"># Flushes write buffer. Runs every 4096/8192 B.</span>
 &lt;file&gt;.close()                      <span class="hljs-comment"># Closes the file after flushing write buffer.</span>

From e85825b8732797b816807e0451d09d49a6d99342 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 7 May 2025 03:10:27 +0200
Subject: [PATCH 137/186] Struct, Threading

---
 README.md  |  8 ++++----
 index.html | 22 +++++++++++-----------
 2 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/README.md b/README.md
index 5f2e5ce8f..ea1af9dc0 100644
--- a/README.md
+++ b/README.md
@@ -1997,8 +1997,8 @@ Struct
 ```python
 from struct import pack, unpack
 
-<bytes> = pack('<format>', <el_1> [, ...])  # Packs objects according to format string.
-<tuple> = unpack('<format>', <bytes>)       # Use iter_unpack() to get iterator of tuples.
+<bytes> = pack('<format>', <num_1> [, ...])  # Packs numbers according to format string.
+<tuple> = unpack('<format>', <bytes>)        # Use iter_unpack() to get iterator of tuples.
 ```
 
 ```python
@@ -2259,7 +2259,7 @@ from concurrent.futures import ThreadPoolExecutor, as_completed
 <Thread>.join()                                # Waits for the thread to finish executing.
 ```
 * **Use `'kwargs=<dict>'` to pass keyword arguments to the function.**
-* **Use `'daemon=True'`, or program won't be able to exit while the thread is alive.**
+* **Use `'daemon=True'`, or the program won't be able to exit while the thread is alive.**
 
 ### Lock
 ```python
@@ -2295,7 +2295,7 @@ with <lock>:                                   # Enters the block by calling acq
 <Exec> = ThreadPoolExecutor(max_workers=None)  # Or: `with ThreadPoolExecutor() as <name>: ...`
 <iter> = <Exec>.map(<func>, <args_1>, ...)     # Multithreaded and non-lazy map(). Keeps order.
 <Futr> = <Exec>.submit(<func>, <arg_1>, ...)   # Creates a thread and returns its Future obj.
-<Exec>.shutdown()                              # Blocks until all threads finish executing.
+<Exec>.shutdown()                              # Waits for all submitted threads to finish.
 ```
 
 ```python
diff --git a/index.html b/index.html
index 869e1e8f7..753683693 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 3, 2025</aside>
+    <aside>May 7, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1430,8 +1430,8 @@
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Path&gt; = &lt;Path&gt;.parent              <span class="hljs-comment"># Returns Path without the final component.</span>
 &lt;str&gt;  = &lt;Path&gt;.name                <span class="hljs-comment"># Returns final component as a string.</span>
-&lt;str&gt;  = &lt;Path&gt;.stem                <span class="hljs-comment"># Returns final component w/o last extension.</span>
-&lt;str&gt;  = &lt;Path&gt;.suffix              <span class="hljs-comment"># Returns last extension prepended with a dot.</span>
+&lt;str&gt;  = &lt;Path&gt;.suffix              <span class="hljs-comment"># Returns name's last extension (e.g. '.py').</span>
+&lt;str&gt;  = &lt;Path&gt;.stem                <span class="hljs-comment"># Returns name without its last extension.</span>
 &lt;tup.&gt; = &lt;Path&gt;.parts               <span class="hljs-comment"># Returns all path's components as strings.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;iter&gt; = &lt;Path&gt;.iterdir()           <span class="hljs-comment"># Returns directory contents as Path objects.</span>
@@ -1591,8 +1591,8 @@
     &lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)                  <span class="hljs-comment"># depending on whether any exception occurred.</span>
 </code></pre></div>
 
-<div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)        <span class="hljs-comment"># Replaces '?'s in query with values.</span>
-&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces ':&lt;key&gt;'s with values.</span>
+<div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)        <span class="hljs-comment"># Replaces every '?' with an item.</span>
+&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces every ':&lt;key&gt;' with a value.</span>
 &lt;conn&gt;.executemany(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;coll_of_coll&gt;)  <span class="hljs-comment"># Runs execute() multiple times.</span>
 </code></pre></div>
 
@@ -1612,7 +1612,7 @@
 <span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> create_engine, text
 &lt;engine&gt; = create_engine(<span class="hljs-string">'&lt;url&gt;'</span>)              <span class="hljs-comment"># Url: 'dialect://user:password@host/dbname'.</span>
 &lt;conn&gt;   = &lt;engine&gt;.connect()                  <span class="hljs-comment"># Creates a connection. Also &lt;conn&gt;.close().</span>
-&lt;cursor&gt; = &lt;conn&gt;.execute(text(<span class="hljs-string">'&lt;query&gt;'</span>), …)  <span class="hljs-comment"># `&lt;dict&gt;`. Replaces ':&lt;key&gt;'s with values.</span>
+&lt;cursor&gt; = &lt;conn&gt;.execute(text(<span class="hljs-string">'&lt;query&gt;'</span>), …)  <span class="hljs-comment"># `&lt;dict&gt;`. Replaces every ':&lt;key&gt;' with value.</span>
 <span class="hljs-keyword">with</span> &lt;conn&gt;.begin(): ...                       <span class="hljs-comment"># Exits the block with commit or rollback.</span>
 </code></pre></div>
 
@@ -1660,8 +1660,8 @@
 <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
 
-&lt;bytes&gt; = pack(<span class="hljs-string">'&lt;format&gt;'</span>, &lt;el_1&gt; [, ...])  <span class="hljs-comment"># Packs objects according to format string.</span>
-&lt;tuple&gt; = unpack(<span class="hljs-string">'&lt;format&gt;'</span>, &lt;bytes&gt;)       <span class="hljs-comment"># Use iter_unpack() to get iterator of tuples.</span>
+&lt;bytes&gt; = pack(<span class="hljs-string">'&lt;format&gt;'</span>, &lt;num_1&gt; [, ...])  <span class="hljs-comment"># Packs numbers according to format string.</span>
+&lt;tuple&gt; = unpack(<span class="hljs-string">'&lt;format&gt;'</span>, &lt;bytes&gt;)        <span class="hljs-comment"># Use iter_unpack() to get iterator of tuples.</span>
 </code></pre></div>
 
 
@@ -1865,7 +1865,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <ul>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'kwargs=&lt;dict&gt;'</span></code> to pass keyword arguments to the function.</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'daemon=True'</span></code>, or program won't be able to exit while the thread is alive.</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 the thread is alive.</strong></li>
 </ul>
 <div><h3 id="lock">Lock</h3><pre><code class="python language-python hljs">&lt;lock&gt; = Lock/RLock()                          <span class="hljs-comment"># RLock can only be released by acquirer.</span>
 &lt;lock&gt;.acquire()                               <span class="hljs-comment"># Waits for the lock to be available.</span>
@@ -1891,7 +1891,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <div><h3 id="threadpoolexecutor">Thread Pool Executor</h3><pre><code class="python language-python hljs">&lt;Exec&gt; = ThreadPoolExecutor(max_workers=<span class="hljs-keyword">None</span>)  <span class="hljs-comment"># Or: `with ThreadPoolExecutor() as &lt;name&gt;: ...`</span>
 &lt;iter&gt; = &lt;Exec&gt;.map(&lt;func&gt;, &lt;args_1&gt;, ...)     <span class="hljs-comment"># Multithreaded and non-lazy map(). Keeps order.</span>
 &lt;Futr&gt; = &lt;Exec&gt;.submit(&lt;func&gt;, &lt;arg_1&gt;, ...)   <span class="hljs-comment"># Creates a thread and returns its Future obj.</span>
-&lt;Exec&gt;.shutdown()                              <span class="hljs-comment"># Blocks until all threads finish executing.</span>
+&lt;Exec&gt;.shutdown()                              <span class="hljs-comment"># Waits for all submitted threads to finish.</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs">&lt;bool&gt; = &lt;Future&gt;.done()                       <span class="hljs-comment"># Checks if the thread has finished executing.</span>
@@ -2940,7 +2940,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 3, 2025</aside>
+    <aside>May 7, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 097a688ec12d237ff0474eaaa440ac41733696cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 8 May 2025 06:07:14 +0200
Subject: [PATCH 138/186] Paths

---
 README.md  |  4 ++--
 index.html | 14 +++++++-------
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/README.md b/README.md
index ea1af9dc0..88cacc85b 100644
--- a/README.md
+++ b/README.md
@@ -1684,8 +1684,8 @@ from pathlib import Path
 ```python
 <Path> = <Path>.parent              # Returns Path without the final component.
 <str>  = <Path>.name                # Returns final component as a string.
-<str>  = <Path>.stem                # Returns final component w/o last extension.
-<str>  = <Path>.suffix              # Returns last extension prepended with a dot.
+<str>  = <Path>.suffix              # Returns name's last extension, e.g. '.py'.
+<str>  = <Path>.stem                # Returns name without last extension.
 <tup.> = <Path>.parts               # Returns all path's components as strings.
 ```
 
diff --git a/index.html b/index.html
index 753683693..f8540c548 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 7, 2025</aside>
+    <aside>May 8, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1430,8 +1430,8 @@
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Path&gt; = &lt;Path&gt;.parent              <span class="hljs-comment"># Returns Path without the final component.</span>
 &lt;str&gt;  = &lt;Path&gt;.name                <span class="hljs-comment"># Returns final component as a string.</span>
-&lt;str&gt;  = &lt;Path&gt;.suffix              <span class="hljs-comment"># Returns name's last extension (e.g. '.py').</span>
-&lt;str&gt;  = &lt;Path&gt;.stem                <span class="hljs-comment"># Returns name without its last extension.</span>
+&lt;str&gt;  = &lt;Path&gt;.suffix              <span class="hljs-comment"># Returns name's last extension, e.g. '.py'.</span>
+&lt;str&gt;  = &lt;Path&gt;.stem                <span class="hljs-comment"># Returns name without last extension.</span>
 &lt;tup.&gt; = &lt;Path&gt;.parts               <span class="hljs-comment"># Returns all path's components as strings.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;iter&gt; = &lt;Path&gt;.iterdir()           <span class="hljs-comment"># Returns directory contents as Path objects.</span>
@@ -1591,8 +1591,8 @@
     &lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)                  <span class="hljs-comment"># depending on whether any exception occurred.</span>
 </code></pre></div>
 
-<div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)        <span class="hljs-comment"># Replaces every '?' with an item.</span>
-&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces every ':&lt;key&gt;' with a value.</span>
+<div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)        <span class="hljs-comment"># Replaces '?'s in query with values.</span>
+&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces ':&lt;key&gt;'s with values.</span>
 &lt;conn&gt;.executemany(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;coll_of_coll&gt;)  <span class="hljs-comment"># Runs execute() multiple times.</span>
 </code></pre></div>
 
@@ -1612,7 +1612,7 @@
 <span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> create_engine, text
 &lt;engine&gt; = create_engine(<span class="hljs-string">'&lt;url&gt;'</span>)              <span class="hljs-comment"># Url: 'dialect://user:password@host/dbname'.</span>
 &lt;conn&gt;   = &lt;engine&gt;.connect()                  <span class="hljs-comment"># Creates a connection. Also &lt;conn&gt;.close().</span>
-&lt;cursor&gt; = &lt;conn&gt;.execute(text(<span class="hljs-string">'&lt;query&gt;'</span>), …)  <span class="hljs-comment"># `&lt;dict&gt;`. Replaces every ':&lt;key&gt;' with value.</span>
+&lt;cursor&gt; = &lt;conn&gt;.execute(text(<span class="hljs-string">'&lt;query&gt;'</span>), …)  <span class="hljs-comment"># `&lt;dict&gt;`. Replaces ':&lt;key&gt;'s with values.</span>
 <span class="hljs-keyword">with</span> &lt;conn&gt;.begin(): ...                       <span class="hljs-comment"># Exits the block with commit or rollback.</span>
 </code></pre></div>
 
@@ -2940,7 +2940,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 7, 2025</aside>
+    <aside>May 8, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 9d967f5980525ca736888ea60aa08309c9b3ca51 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 9 May 2025 02:33:44 +0200
Subject: [PATCH 139/186] SQLite, Pygame

---
 README.md  |  8 ++++----
 index.html | 12 ++++++------
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index 88cacc85b..8fe2c5668 100644
--- a/README.md
+++ b/README.md
@@ -1907,8 +1907,8 @@ with <conn>:                                   # Exits the block with commit() o
 
 ### Placeholders
 ```python
-<conn>.execute('<query>', <list/tuple>)        # Replaces '?'s in query with values.
-<conn>.execute('<query>', <dict/namedtuple>)   # Replaces ':<key>'s with values.
+<conn>.execute('<query>', <list/tuple>)        # Replaces every question mark with an item.
+<conn>.execute('<query>', <dict/namedtuple>)   # Replaces every :<key> with value.
 <conn>.executemany('<query>', <coll_of_coll>)  # Runs execute() multiple times.
 ```
 * **Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).**
@@ -1931,7 +1931,7 @@ with <conn>:                                   # Exits the block with commit() o
 from sqlalchemy import create_engine, text
 <engine> = create_engine('<url>')              # Url: 'dialect://user:password@host/dbname'.
 <conn>   = <engine>.connect()                  # Creates a connection. Also <conn>.close().
-<cursor> = <conn>.execute(text('<query>'), …)  # `<dict>`. Replaces ':<key>'s with values.
+<cursor> = <conn>.execute(text('<query>'), …)  # `<dict>`. Replaces every :<key> with value.
 with <conn>.begin(): ...                       # Exits the block with commit or rollback.
 ```
 
@@ -3048,7 +3048,7 @@ rect(<Surf>, color, <Rect>, width=0)            # Also polygon(<Surf>, color, po
 
 ```python
 <Font> = pg.font.Font(<path/file>, size)        # Loads TTF file. Pass None for default font.
-<Surf> = <Font>.render(text, antialias, color)  # Background color can be specified at the end.
+<Surf> = <Font>.render(text, antialias, color)  # Accepts background color as fourth argument.
 ```
 
 ### Sound
diff --git a/index.html b/index.html
index f8540c548..23b6a23a4 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 8, 2025</aside>
+    <aside>May 9, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1591,8 +1591,8 @@
     &lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)                  <span class="hljs-comment"># depending on whether any exception occurred.</span>
 </code></pre></div>
 
-<div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)        <span class="hljs-comment"># Replaces '?'s in query with values.</span>
-&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces ':&lt;key&gt;'s with values.</span>
+<div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)        <span class="hljs-comment"># Replaces every question mark with an item.</span>
+&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces every :&lt;key&gt; with value.</span>
 &lt;conn&gt;.executemany(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;coll_of_coll&gt;)  <span class="hljs-comment"># Runs execute() multiple times.</span>
 </code></pre></div>
 
@@ -1612,7 +1612,7 @@
 <span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> create_engine, text
 &lt;engine&gt; = create_engine(<span class="hljs-string">'&lt;url&gt;'</span>)              <span class="hljs-comment"># Url: 'dialect://user:password@host/dbname'.</span>
 &lt;conn&gt;   = &lt;engine&gt;.connect()                  <span class="hljs-comment"># Creates a connection. Also &lt;conn&gt;.close().</span>
-&lt;cursor&gt; = &lt;conn&gt;.execute(text(<span class="hljs-string">'&lt;query&gt;'</span>), …)  <span class="hljs-comment"># `&lt;dict&gt;`. Replaces ':&lt;key&gt;'s with values.</span>
+&lt;cursor&gt; = &lt;conn&gt;.execute(text(<span class="hljs-string">'&lt;query&gt;'</span>), …)  <span class="hljs-comment"># `&lt;dict&gt;`. Replaces every :&lt;key&gt; with value.</span>
 <span class="hljs-keyword">with</span> &lt;conn&gt;.begin(): ...                       <span class="hljs-comment"># Exits the block with commit or rollback.</span>
 </code></pre></div>
 
@@ -2496,7 +2496,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 rect(&lt;Surf&gt;, color, &lt;Rect&gt;, width=<span class="hljs-number">0</span>)            <span class="hljs-comment"># Also polygon(&lt;Surf&gt;, color, points, width=0).</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Font&gt; = pg.font.Font(&lt;path/file&gt;, size)        <span class="hljs-comment"># Loads TTF file. Pass None for default font.</span>
-&lt;Surf&gt; = &lt;Font&gt;.render(text, antialias, color)  <span class="hljs-comment"># Background color can be specified at the end.</span>
+&lt;Surf&gt; = &lt;Font&gt;.render(text, antialias, color)  <span class="hljs-comment"># Accepts background color as fourth argument.</span>
 </code></pre>
 <div><h3 id="sound">Sound</h3><pre><code class="python language-python hljs">&lt;Sound&gt; = pg.mixer.Sound(&lt;path/file/bytes&gt;)     <span class="hljs-comment"># WAV file or bytes/array of signed shorts.</span>
 &lt;Sound&gt;.play/stop()                             <span class="hljs-comment"># Also set_volume(&lt;float&gt;) and fadeout(msec).</span>
@@ -2940,7 +2940,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 8, 2025</aside>
+    <aside>May 9, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From df765fb31509e92704575141e087c4b42ea6449a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 9 May 2025 02:43:00 +0200
Subject: [PATCH 140/186] Pandas

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 8fe2c5668..a5e57cbd4 100644
--- a/README.md
+++ b/README.md
@@ -3352,7 +3352,7 @@ c  6  7
 ```
 
 ```python
-<DF>.to_json/csv/html/parquet/latex(<path>)    # Returns a string/bytes if path is omitted.
+<DF>.to_json/csv/html/latex/parquet(<path>)    # Returns a string/bytes if path is omitted.
 <DF>.to_pickle/excel/feather/hdf(<path>)       # Method to_hdf() requires `key=<s/df_name>`.
 <DF>.to_sql('<table_name>', <connection>)      # Also `if_exists='fail/replace/append'`.
 ```
@@ -3414,7 +3414,7 @@ import plotly.express as px, pandas as pd
 ```python
 <Fig> = px.line(<DF>, x=col_key, y=col_key)           # Or: px.line(x=<list>, y=<list>)
 <Fig>.update_layout(margin=dict(t=0, r=0, b=0, l=0))  # Also `paper_bgcolor='rgb(0, 0, 0)'`.
-<Fig>.write_html/json/image('<path>')                 # <Fig>.show() displays the plot.
+<Fig>.write_html/json/image('<path>')                 # `<Fig>.show()` displays the plot.
 ```
 
 ```python
diff --git a/index.html b/index.html
index 23b6a23a4..9be5ffe5b 100644
--- a/index.html
+++ b/index.html
@@ -2743,7 +2743,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;DF&gt;   = pd.read_sql(<span class="hljs-string">'&lt;table/query&gt;'</span>, &lt;conn&gt;)  <span class="hljs-comment"># Pass SQLite3/Alchemy connection. See #SQLite.</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs">&lt;DF&gt;.to_json/csv/html/parquet/latex(&lt;path&gt;)    <span class="hljs-comment"># Returns a string/bytes if path is omitted.</span>
+<pre><code class="python language-python hljs">&lt;DF&gt;.to_json/csv/html/latex/parquet(&lt;path&gt;)    <span class="hljs-comment"># Returns a string/bytes if path is omitted.</span>
 &lt;DF&gt;.to_pickle/excel/feather/hdf(&lt;path&gt;)       <span class="hljs-comment"># Method to_hdf() requires `key=&lt;s/df_name&gt;`.</span>
 &lt;DF&gt;.to_sql(<span class="hljs-string">'&lt;table_name&gt;'</span>, &lt;connection&gt;)      <span class="hljs-comment"># Also `if_exists='fail/replace/append'`.</span>
 </code></pre>
@@ -2790,7 +2790,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <pre><code class="python language-python hljs">&lt;Fig&gt; = px.line(&lt;DF&gt;, x=col_key, y=col_key)           <span class="hljs-comment"># Or: px.line(x=&lt;list&gt;, y=&lt;list&gt;)</span>
 &lt;Fig&gt;.update_layout(margin=dict(t=<span class="hljs-number">0</span>, r=<span class="hljs-number">0</span>, b=<span class="hljs-number">0</span>, l=<span class="hljs-number">0</span>))  <span class="hljs-comment"># Also `paper_bgcolor='rgb(0, 0, 0)'`.</span>
-&lt;Fig&gt;.write_html/json/image(<span class="hljs-string">'&lt;path&gt;'</span>)                 <span class="hljs-comment"># &lt;Fig&gt;.show() displays the plot.</span>
+&lt;Fig&gt;.write_html/json/image(<span class="hljs-string">'&lt;path&gt;'</span>)                 <span class="hljs-comment"># `&lt;Fig&gt;.show()` displays the plot.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Fig&gt; = px.area/bar/box(&lt;DF&gt;, x=col_key, y=col_key)   <span class="hljs-comment"># Also `color=col_key`.</span>
 &lt;Fig&gt; = px.scatter(&lt;DF&gt;, x=col_key, y=col_key)        <span class="hljs-comment"># Also `color/size/symbol=col_key`.</span>

From 078178902e3144aa3ba8353794f4e802f518d688 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 9 May 2025 21:13:57 +0200
Subject: [PATCH 141/186] Exceptions, Input

---
 README.md  | 4 ++--
 index.html | 4 ++--
 parse.js   | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index a5e57cbd4..c906e61e9 100644
--- a/README.md
+++ b/README.md
@@ -1461,7 +1461,7 @@ BaseException
       |    +-- ConnectionError    # Errors such as BrokenPipeError/ConnectionAbortedError.
       +-- RuntimeError            # Raised by errors that don't fall into other categories.
       |    +-- NotImplementedEr…  # Can be raised by abstract methods or by unfinished code.
-      |    +-- RecursionError     # Raised when the maximum recursion depth is exceeded.
+      |    +-- RecursionError     # Raised if max recursion depth is exceeded (3k by default).
       +-- StopIteration           # Raised when an empty iterator is passed to next().
       +-- TypeError               # When an argument of the wrong type is passed to function.
       +-- ValueError              # When argument has the right type but inappropriate value.
@@ -1528,7 +1528,7 @@ Input
 ```
 * **Reads a line from the user input or pipe if present (trailing newline gets stripped).**
 * **If argument is passed, it gets printed to the standard output before input is read.**
-* **EOFError is raised if user hits EOF (ctrl-d/ctrl-z⏎) or input stream gets exhausted.**
+* **EOFError is raised if user hits EOF (ctrl-d/ctrl-z⏎) or if input stream is exhausted.**
 
 
 Command Line Arguments
diff --git a/index.html b/index.html
index 9be5ffe5b..d2af9dd93 100644
--- a/index.html
+++ b/index.html
@@ -1257,7 +1257,7 @@
       │    └── ConnectionError    <span class="hljs-comment"># Errors such as BrokenPipeError/ConnectionAbortedError.</span>
       ├── RuntimeError            <span class="hljs-comment"># Raised by errors that don't fall into other categories.</span>
       │    ├── NotImplementedEr…  <span class="hljs-comment"># Can be raised by abstract methods or by unfinished code.</span>
-      │    └── RecursionError     <span class="hljs-comment"># Raised when the maximum recursion depth is exceeded.</span>
+      │    └── RecursionError     <span class="hljs-comment"># Raised if max recursion depth is exceeded (3k by default).</span>
       ├── StopIteration           <span class="hljs-comment"># Raised when an empty iterator is passed to next().</span>
       ├── TypeError               <span class="hljs-comment"># When an argument of the wrong type is passed to function.</span>
       └── ValueError              <span class="hljs-comment"># When argument has the right type but inappropriate value.</span>
@@ -1310,7 +1310,7 @@
 <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 input stream gets exhausted.</strong></li>
+<li><strong>EOFError is raised if user hits EOF (ctrl-d/ctrl-z⏎) or if input stream is exhausted.</strong></li>
 </ul>
 <div><h2 id="commandlinearguments"><a href="#commandlinearguments" name="commandlinearguments">#</a>Command Line 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>]
diff --git a/parse.js b/parse.js
index c06fa0dc3..3d186693b 100755
--- a/parse.js
+++ b/parse.js
@@ -476,7 +476,7 @@ const DIAGRAM_7_B =
   "      │    └── ConnectionError    <span class='hljs-comment'># Errors such as BrokenPipeError/ConnectionAbortedError.</span>\n" +
   "      ├── RuntimeError            <span class='hljs-comment'># Raised by errors that don't fall into other categories.</span>\n" +
   "      │    ├── NotImplementedEr…  <span class='hljs-comment'># Can be raised by abstract methods or by unfinished code.</span>\n" +
-  "      │    └── RecursionError     <span class='hljs-comment'># Raised when the maximum recursion depth is exceeded.</span>\n" +
+  "      │    └── RecursionError     <span class='hljs-comment'># Raised if max recursion depth is exceeded (3k by default).</span>\n" +
   "      ├── StopIteration           <span class='hljs-comment'># Raised when an empty iterator is passed to next().</span>\n" +
   "      ├── TypeError               <span class='hljs-comment'># When an argument of the wrong type is passed to function.</span>\n" +
   "      └── ValueError              <span class='hljs-comment'># When argument has the right type but inappropriate value.</span>\n";

From 036b94e66872049acdb2791a14192e5438bece6f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 13 May 2025 00:05:00 +0200
Subject: [PATCH 142/186] Inheritence to Subclass in Class, Paths, CSV

---
 README.md              | 32 +++++++++++++++++---------------
 index.html             | 35 ++++++++++++++++++++---------------
 pdf/index_for_pdf.html |  2 +-
 3 files changed, 38 insertions(+), 31 deletions(-)

diff --git a/README.md b/README.md
index c906e61e9..4f2da95db 100644
--- a/README.md
+++ b/README.md
@@ -995,29 +995,31 @@ Z = make_dataclass('Z', ['a']); print/str/repr(Z(<obj>))
 >>> <obj>
 ```
 
-### Inheritance
+### Subclass
+* **Inheritance is a mechanism that enables a class to extend another class (subclass to extend its parent), and by doing so inherit all its methods and attributes.**
+* **Subclass can then add its own methods and attributes or override inherited ones by reusing their names.**
+
 ```python
 class Person:
     def __init__(self, name):
         self.name = name
+    def __repr__(self):
+        return f'Person({self.name!r})'
+    def __lt__(self, other):
+        return self.name < other.name
 
 class Employee(Person):
     def __init__(self, name, staff_num):
         super().__init__(name)
         self.staff_num = staff_num
+    def __repr__(self):
+        return f'Employee({self.name!r}, {self.staff_num})'
 ```
 
-#### Multiple inheritance:
-```python
-class A: pass
-class B: pass
-class C(A, B): pass
-```
-
-**MRO determines the order in which parent classes are traversed when searching for a method or an attribute:**
 ```python
->>> C.mro()
-[<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>]
+>>> people = {Person('Ann'), Employee('Bob', 0)}
+>>> sorted(people)
+[Person('Ann'), Employee('Bob', 0)]
 ```
 
 ### Type Annotations
@@ -1685,8 +1687,8 @@ from pathlib import Path
 <Path> = <Path>.parent              # Returns Path without the final component.
 <str>  = <Path>.name                # Returns final component as a string.
 <str>  = <Path>.suffix              # Returns name's last extension, e.g. '.py'.
-<str>  = <Path>.stem                # Returns name without last extension.
-<tup.> = <Path>.parts               # Returns all path's components as strings.
+<str>  = <Path>.stem                # Returns name without the last extension.
+<tup.> = <Path>.parts               # Returns all components as strings.
 ```
 
 ```python
@@ -1820,10 +1822,10 @@ import csv
 <list>   = next(<reader>)           # Returns next row as a list of strings.
 <list>   = list(<reader>)           # Returns a list of remaining rows.
 ```
-* **File must be opened with a `'newline=""'` argument, or newlines embedded inside quoted fields will not be interpreted correctly!**
+* **File must be opened with a `'newline=""'` argument, or all '\r\n' sequences inside quoted fields will get converted to '\n'!**
 * **To print the spreadsheet to the console use [Tabulate](#table) library.**
 * **For XML and binary Excel files (xlsx, xlsm and xlsb) use [Pandas](#dataframe-plot-encode-decode) library.**
-* **Reader accepts any iterator of strings, not just files.**
+* **Reader accepts any collection of strings, not just files.**
 
 ### Write
 ```python
diff --git a/index.html b/index.html
index d2af9dd93..a26d19153 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 9, 2025</aside>
+    <aside>May 12, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -849,25 +849,30 @@
 <span class="hljs-meta">&gt;&gt;&gt; </span>&lt;obj&gt;
 </code></pre></div>
 
-<div><h3 id="inheritance">Inheritance</h3><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span>
+<div><h3 id="subclass">Subclass</h3><ul>
+<li><strong>Inheritance is a mechanism that enables a class to extend another class (subclass to extend its parent), and by doing so inherit all 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 &lt; 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>
 
-<div><h4 id="multipleinheritance">Multiple inheritance:</h4><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">A</span>:</span> <span class="hljs-keyword">pass</span>
-<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">B</span>:</span> <span class="hljs-keyword">pass</span>
-<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">C</span><span class="hljs-params">(A, B)</span>:</span> <span class="hljs-keyword">pass</span>
-</code></pre></div>
 
-<p><strong>MRO determines the order in which parent classes are traversed when searching for a method or an attribute:</strong></p>
-<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>C.mro()
-[&lt;<span class="hljs-class"><span class="hljs-title">class</span> '<span class="hljs-title">C</span>'&gt;, &lt;<span class="hljs-title">class</span> '<span class="hljs-title">A</span>'&gt;, &lt;<span class="hljs-title">class</span> '<span class="hljs-title">B</span>'&gt;, &lt;<span class="hljs-title">class</span> '<span class="hljs-title">object</span>'&gt;]
-</span></code></pre>
+<pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>people = {Person(<span class="hljs-string">'Ann'</span>), Employee(<span class="hljs-string">'Bob'</span>, <span class="hljs-number">0</span>)}
+<span class="hljs-meta">&gt;&gt;&gt; </span>sorted(people)
+[Person(<span class="hljs-string">'Ann'</span>), Employee(<span class="hljs-string">'Bob'</span>, <span class="hljs-number">0</span>)]
+</code></pre>
 <div><h3 id="typeannotations">Type Annotations</h3><ul>
 <li><strong>They add type hints to variables, arguments and functions (<code class="python hljs"><span class="hljs-string">'def f() -&gt; &lt;type&gt;:'</span></code>).</strong></li>
 <li><strong>Hints are used by type checkers like <a href="https://pypi.org/project/mypy/">mypy</a>, data validation libraries such as <a href="https://pypi.org/project/pydantic/">Pydantic</a> and lately also by <a href="https://pypi.org/project/Cython/">Cython</a> compiler. However, they are not enforced by CPython interpreter.</strong></li>
@@ -1431,8 +1436,8 @@
 <pre><code class="python language-python hljs">&lt;Path&gt; = &lt;Path&gt;.parent              <span class="hljs-comment"># Returns Path without the final component.</span>
 &lt;str&gt;  = &lt;Path&gt;.name                <span class="hljs-comment"># Returns final component as a string.</span>
 &lt;str&gt;  = &lt;Path&gt;.suffix              <span class="hljs-comment"># Returns name's last extension, e.g. '.py'.</span>
-&lt;str&gt;  = &lt;Path&gt;.stem                <span class="hljs-comment"># Returns name without last extension.</span>
-&lt;tup.&gt; = &lt;Path&gt;.parts               <span class="hljs-comment"># Returns all path's components as strings.</span>
+&lt;str&gt;  = &lt;Path&gt;.stem                <span class="hljs-comment"># Returns name without the last extension.</span>
+&lt;tup.&gt; = &lt;Path&gt;.parts               <span class="hljs-comment"># Returns all components as strings.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;iter&gt; = &lt;Path&gt;.iterdir()           <span class="hljs-comment"># Returns directory contents as Path objects.</span>
 &lt;iter&gt; = &lt;Path&gt;.glob(<span class="hljs-string">'&lt;pattern&gt;'</span>)   <span class="hljs-comment"># Returns Paths matching the wildcard pattern.</span>
@@ -1522,10 +1527,10 @@
 </code></pre></div>
 
 <ul>
-<li><strong>File must be opened with a <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, or newlines embedded inside quoted fields will not be interpreted correctly!</strong></li>
+<li><strong>File must be opened with a <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, or all '\r\n' sequences inside quoted fields will get converted to '\n'!</strong></li>
 <li><strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong></li>
 <li><strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#dataframeplotencodedecode">Pandas</a> library.</strong></li>
-<li><strong>Reader accepts any iterator of strings, not just files.</strong></li>
+<li><strong>Reader accepts any collection of strings, not just files.</strong></li>
 </ul>
 <div><h3 id="write">Write</h3><pre><code class="python language-python hljs">&lt;writer&gt; = csv.writer(&lt;file&gt;)       <span class="hljs-comment"># Also: `dialect='excel', delimiter=','`.</span>
 &lt;writer&gt;.writerow(&lt;collection&gt;)     <span class="hljs-comment"># Encodes objects using `str(&lt;el&gt;)`.</span>
@@ -2940,7 +2945,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 9, 2025</aside>
+    <aside>May 12, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html
index 9cb299e6b..4327865bf 100644
--- a/pdf/index_for_pdf.html
+++ b/pdf/index_for_pdf.html
@@ -131,7 +131,7 @@ <h3 id="s">S</h3>
 <strong>strings, <a href="#abstractbaseclasses">4</a>-<a href="#comparisonofpresentationtypes">7</a>, <a href="#class">14</a></strong><br>
 <strong>struct module, <a href="#struct">28</a>-<a href="#integertypesuseacapitalletterforunsignedtypeminimumandstandardsizesareinbrackets">29</a></strong><br>
 <strong>subprocess module, <a href="#sends11tothebasiccalculatorandcapturesitsoutput">25</a></strong><br>
-<strong>super function, <a href="#inheritance">14</a></strong><br>
+<strong>super function, <a href="#subclass">14</a></strong><br>
 <strong>sys module, <a href="#cache">13</a>, <a href="#exit">21</a>-<a href="#commandlinearguments">22</a></strong> </p>
 <h3 id="t">T</h3>
 <p><strong>table, <a href="#csv">26</a>, <a href="#example-1">27</a>, <a href="#table">34</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#dataframe">45</a>-<a href="#dataframeaggregatetransformmap">46</a></strong><br>

From e76785f55924823beb515625da9d9b4a98b243f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 13 May 2025 00:23:47 +0200
Subject: [PATCH 143/186] Paths

---
 README.md  | 2 +-
 index.html | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 4f2da95db..53bc4ebb6 100644
--- a/README.md
+++ b/README.md
@@ -1697,7 +1697,7 @@ from pathlib import Path
 ```
 
 ```python
-<str>  = str(<Path>)                # Returns path as a string.
+<str>  = str(<Path>)                # Returns path as str. Also <Path>.as_uri().
 <file> = open(<Path>)               # Also <Path>.read/write_text/bytes(<args>).
 ```
 
diff --git a/index.html b/index.html
index a26d19153..596c171e5 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 12, 2025</aside>
+    <aside>May 13, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1442,7 +1442,7 @@
 <pre><code class="python language-python hljs">&lt;iter&gt; = &lt;Path&gt;.iterdir()           <span class="hljs-comment"># Returns directory contents as Path objects.</span>
 &lt;iter&gt; = &lt;Path&gt;.glob(<span class="hljs-string">'&lt;pattern&gt;'</span>)   <span class="hljs-comment"># Returns Paths matching the wildcard pattern.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;str&gt;  = str(&lt;Path&gt;)                <span class="hljs-comment"># Returns path as a string.</span>
+<pre><code class="python language-python hljs">&lt;str&gt;  = str(&lt;Path&gt;)                <span class="hljs-comment"># Returns path as str. Also &lt;Path&gt;.as_uri().</span>
 &lt;file&gt; = open(&lt;Path&gt;)               <span class="hljs-comment"># Also &lt;Path&gt;.read/write_text/bytes(&lt;args&gt;).</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, subprocess
@@ -2945,7 +2945,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 12, 2025</aside>
+    <aside>May 13, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From c3e6a0b2aa63d22c58edfa79b045812289dd3195 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 16 May 2025 16:41:27 +0200
Subject: [PATCH 144/186] CSV

---
 README.md           |  6 +++---
 index.html          | 10 +++++-----
 pdf/remove_links.py |  2 +-
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/README.md b/README.md
index 53bc4ebb6..e911850d3 100644
--- a/README.md
+++ b/README.md
@@ -1822,7 +1822,7 @@ import csv
 <list>   = next(<reader>)           # Returns next row as a list of strings.
 <list>   = list(<reader>)           # Returns a list of remaining rows.
 ```
-* **File must be opened with a `'newline=""'` argument, or all '\r\n' sequences inside quoted fields will get converted to '\n'!**
+* **File must be opened with a `'newline=""'` argument, or every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'!**
 * **To print the spreadsheet to the console use [Tabulate](#table) library.**
 * **For XML and binary Excel files (xlsx, xlsm and xlsb) use [Pandas](#dataframe-plot-encode-decode) library.**
 * **Reader accepts any collection of strings, not just files.**
@@ -1838,10 +1838,10 @@ import csv
 
 ### Parameters
 * **`'dialect'` - Master parameter that sets the default values. String or a 'csv.Dialect' object.**
-* **`'delimiter'` - A one-character string used to separate fields.**
+* **`'delimiter'` - A one-character string that separates fields (comma, tab, semicolon, etc.).**
 * **`'lineterminator'` - How writer terminates rows. Reader looks for '\n', '\r' and '\r\n'.**
 * **`'quotechar'` - Character for quoting fields containing delimiters, quotechars, '\n' or '\r'.**
-* **`'escapechar'` - Character for escaping quotechars.**
+* **`'escapechar'` - Character for escaping quotechars (not needed if doublequote is True).**
 * **`'doublequote'` - Whether quotechars inside fields are/get doubled or escaped.**
 * **`'quoting'` - 0: As necessary, 1: All, 2: All but numbers which are read as floats, 3: None.**
 * **`'skipinitialspace'` - Is space character at the start of the field stripped by the reader.**
diff --git a/index.html b/index.html
index 596c171e5..ef7103325 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 13, 2025</aside>
+    <aside>May 16, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1527,7 +1527,7 @@
 </code></pre></div>
 
 <ul>
-<li><strong>File must be opened with a <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, or all '\r\n' sequences inside quoted fields will get converted to '\n'!</strong></li>
+<li><strong>File must be opened with a <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, or every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'!</strong></li>
 <li><strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong></li>
 <li><strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#dataframeplotencodedecode">Pandas</a> library.</strong></li>
 <li><strong>Reader accepts any collection of strings, not just files.</strong></li>
@@ -1543,10 +1543,10 @@
 </ul>
 <div><h3 id="parameters">Parameters</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 'csv.Dialect' object.</strong></li>
-<li><strong><code class="python hljs"><span class="hljs-string">'delimiter'</span></code> - A one-character string used to separate fields.</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> - 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.</strong></li>
+<li><strong><code class="python hljs"><span class="hljs-string">'escapechar'</span></code> - Character for escaping quotechars (not needed 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 or 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>
@@ -2945,7 +2945,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 13, 2025</aside>
+    <aside>May 16, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index 891cb6bcb..48c167d3b 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -21,7 +21,7 @@
     '<strong>Generators returned by the <a href="#generator">generator functions</a> and <a href="#comprehensions">generator expressions</a>.</strong>': '<strong>Generators returned by the generator functions (p. 4) and generator expressions (p. 11).</strong>',
     '<strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong>': '<strong>File objects returned by the open() function (p. 22), etc.</strong>',
     '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">Logging</a>.</strong>': '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see Logging (p. 31).</strong>',
-    '<strong>Functions report OS related errors by raising either OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong>': '<strong>Functions report OS related errors by raising OSError or one of its subclasses (p. 23).</strong>',
+    '<strong>Functions report OS related errors by raising OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong>': '<strong>Functions report OS related errors by raising OSError or one of its subclasses (p. 23).</strong>',
     '<strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong>': '<strong>To print the spreadsheet to the console use Tabulate library (p. 34).</strong>',
     '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#dataframeplotencodedecode">Pandas</a> library.</strong>': '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use Pandas library (p. 46).</strong>',
     '<strong>Bools will be stored and returned as ints and dates as <a href="#encode">ISO formatted strings</a>.</strong>': '<strong>Bools will be stored and returned as ints and dates as ISO formatted strings (p. 9).</strong>',

From 40c12e4419bbfb85c59c528e017ff18949caa243 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 16 May 2025 23:10:22 +0200
Subject: [PATCH 145/186] Struct

---
 README.md  | 8 ++++----
 index.html | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index e911850d3..756b62b37 100644
--- a/README.md
+++ b/README.md
@@ -1741,7 +1741,7 @@ shutil.rmtree(<path>)               # Deletes the directory.
 <int>  = <pipe>.close()             # Returns None if last command exited with returncode 0.
 ```
 
-#### Sends '1 + 1' to the basic calculator and captures its output:
+#### Sends "1 + 1" to the basic calculator and captures its output:
 ```python
 >>> subprocess.run('bc', input='1 + 1\n', capture_output=True, text=True)
 CompletedProcess(args='bc', returncode=0, stdout='2\n', stderr='')
@@ -1910,7 +1910,7 @@ with <conn>:                                   # Exits the block with commit() o
 ### Placeholders
 ```python
 <conn>.execute('<query>', <list/tuple>)        # Replaces every question mark with an item.
-<conn>.execute('<query>', <dict/namedtuple>)   # Replaces every :<key> with value.
+<conn>.execute('<query>', <dict/namedtuple>)   # Replaces every :<key> with a value.
 <conn>.executemany('<query>', <coll_of_coll>)  # Runs execute() multiple times.
 ```
 * **Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).**
@@ -1999,8 +1999,8 @@ Struct
 ```python
 from struct import pack, unpack
 
-<bytes> = pack('<format>', <num_1> [, ...])  # Packs numbers according to format string.
-<tuple> = unpack('<format>', <bytes>)        # Use iter_unpack() to get iterator of tuples.
+<bytes> = pack('<format>', <el_1> [, ...])  # Packs numbers according to format string.
+<tuple> = unpack('<format>', <bytes>)       # Use iter_unpack() to get iterator of tuples.
 ```
 
 ```python
diff --git a/index.html b/index.html
index ef7103325..02786fc9d 100644
--- a/index.html
+++ b/index.html
@@ -1473,7 +1473,7 @@
 &lt;int&gt;  = &lt;pipe&gt;.close()             <span class="hljs-comment"># Returns None if last command exited with returncode 0.</span>
 </code></pre></div>
 
-<div><h4 id="sends11tothebasiccalculatorandcapturesitsoutput">Sends '1 + 1' to the basic calculator and captures its output:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>subprocess.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>)
+<div><h4 id="sends11tothebasiccalculatorandcapturesitsoutput">Sends "1 + 1" to the basic calculator and captures its output:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>subprocess.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>
 
@@ -1597,7 +1597,7 @@
 </code></pre></div>
 
 <div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)        <span class="hljs-comment"># Replaces every question mark with an item.</span>
-&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces every :&lt;key&gt; with value.</span>
+&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces every :&lt;key&gt; with a value.</span>
 &lt;conn&gt;.executemany(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;coll_of_coll&gt;)  <span class="hljs-comment"># Runs execute() multiple times.</span>
 </code></pre></div>
 
@@ -1665,8 +1665,8 @@
 <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
 
-&lt;bytes&gt; = pack(<span class="hljs-string">'&lt;format&gt;'</span>, &lt;num_1&gt; [, ...])  <span class="hljs-comment"># Packs numbers according to format string.</span>
-&lt;tuple&gt; = unpack(<span class="hljs-string">'&lt;format&gt;'</span>, &lt;bytes&gt;)        <span class="hljs-comment"># Use iter_unpack() to get iterator of tuples.</span>
+&lt;bytes&gt; = pack(<span class="hljs-string">'&lt;format&gt;'</span>, &lt;el_1&gt; [, ...])  <span class="hljs-comment"># Packs numbers according to format string.</span>
+&lt;tuple&gt; = unpack(<span class="hljs-string">'&lt;format&gt;'</span>, &lt;bytes&gt;)       <span class="hljs-comment"># Use iter_unpack() to get iterator of tuples.</span>
 </code></pre></div>
 
 

From edb7680a98fd392682ace5945dffc166426663fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 21 May 2025 16:48:42 +0200
Subject: [PATCH 146/186] Numbers, Duck types, Bytes, Match statement

---
 README.md  | 37 +++++++++++++++++--------------------
 index.html | 41 +++++++++++++++++++----------------------
 2 files changed, 36 insertions(+), 42 deletions(-)

diff --git a/README.md b/README.md
index 756b62b37..82173e88f 100644
--- a/README.md
+++ b/README.md
@@ -320,7 +320,7 @@ String
 <list> = <str>.split()                       # Splits on one or more whitespace characters.
 <list> = <str>.split(sep=None, maxsplit=-1)  # Splits on 'sep' str at most 'maxsplit' times.
 <list> = <str>.splitlines(keepends=False)    # On [\n\r\f\v\x1c-\x1e\x85\u2028\u2029] and \r\n.
-<str>  = <str>.join(<coll_of_strings>)       # Joins elements using string as a separator.
+<str>  = <str>.join(<coll_of_strings>)       # Joins elements by using string as a separator.
 ```
 
 ```python
@@ -524,8 +524,7 @@ from math import log, log10, log2            # Log accepts base as second arg.
 
 ### Statistics
 ```python
-from statistics import mean, median, mode    # Mode returns the most common value.
-from statistics import variance, stdev       # Also: pvariance, pstdev, quantiles.
+from statistics import mean, median, mode    # Also: variance, stdev, quantiles.
 ```
 
 ### Random
@@ -606,7 +605,7 @@ import zoneinfo, dateutil.tz
 * **Times and datetimes that have defined timezone are called aware and ones that don't, naive. If object is naive, it is presumed to be in the system's timezone!**
 * **`'fold=1'` means the second pass in case of time jumping back for one hour.**
 * **Timedelta normalizes arguments to ±days, seconds (< 86 400) and microseconds (< 1M). Its str() method returns `'[±D, ]H:MM:SS[.…]'` and total_seconds() a float of all seconds.**
-* **Use `'<D/DT>.weekday()'` to get the day of the week as an int, with Monday being 0.**
+* **Use `'<D/DT>.weekday()'` to get the day of the week as an integer, with Monday being 0.**
 
 ### Now
 ```python
@@ -1076,7 +1075,7 @@ class Person:
 ```
 
 ### Slots
-**Mechanism that restricts objects to attributes listed in 'slots', reduces their memory footprint.**
+**Mechanism that restricts objects to attributes listed in 'slots'.**
 
 ```python
 class MyClassWithSlots:
@@ -1097,8 +1096,7 @@ Duck Types
 **A duck type is an implicit type that prescribes a set of special methods. Any object that has those methods defined is considered a member of that duck type.**
 
 ### Comparable
-* **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`.**
-* **That means all user-defined objects compare not equal by default.**
+* **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`. That means all user-defined objects compare not equal by default, because id() returns object's unique identification number (its memory address).**
 * **Only the left side object has eq() method called, unless it returns NotImplemented, in which case the right object is consulted. False is returned if both return NotImplemented.**
 * **Ne() automatically works on any object that has eq() defined.**
 
@@ -1113,9 +1111,8 @@ class MyComparable:
 ```
 
 ### Hashable
-* **Hashable object needs both hash() and eq() methods and its hash value should never change.**
-* **Hashable objects that compare equal must have the same hash value, meaning default hash() that returns `'id(self)'` will not do.**
-* **That is why Python automatically makes classes unhashable if you only implement eq().**
+* **Hashable object needs both hash() and eq() methods and its hash value must not change.**
+* **Hashable objects that compare equal must have the same hash value, meaning default hash() that returns `'id(self)'` will not do. That is why Python automatically makes classes unhashable if you only implement eq().**
 
 ```python
 class MyHashable:
@@ -1133,7 +1130,7 @@ class MyHashable:
 ```
 
 ### Sortable
-* **With 'total_ordering' decorator, you only need to provide eq() and one of lt(), gt(), le() or ge() special methods and the rest will be automatically generated.**
+* **With 'total_ordering' decorator, you only need to provide eq() and one of lt(), gt(), le() or ge() special methods (used by <, >, <=, >=) and the rest will be automatically generated.**
 * **Functions sorted() and min() only require lt() method, while max() only requires gt(). However, it is best to define them all so that confusion doesn't arise in other contexts.**
 * **When two lists, strings or dataclasses are compared, their values get compared in order 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 values being equal.**
 * **To sort collection of strings in proper alphabetical order pass `'key=locale.strxfrm'` to sorted() after running `'locale.setlocale(locale.LC_COLLATE, "en_US.UTF-8")'`.**
@@ -1205,7 +1202,7 @@ class Counter:
 ### Context Manager
 * **With statements only work on objects that have enter() and exit() special methods.**
 * **Enter() should lock the resources and optionally return an object.**
-* **Exit() should release the resources.**
+* **Exit() should release the resources (for example close a file).**
 * **Any exception that happens inside the with block is passed to the exit() method.**
 * **The exit() method can suppress the exception by returning a true value.**
 ```python
@@ -1530,7 +1527,7 @@ Input
 ```
 * **Reads a line from the user input or pipe if present (trailing newline gets stripped).**
 * **If argument is passed, it gets printed to the standard output before input is read.**
-* **EOFError is raised if user hits EOF (ctrl-d/ctrl-z⏎) or if input stream is exhausted.**
+* **EOFError is raised if user hits EOF (ctrl-d/ctrl-z⏎) or if stream is already exhausted.**
 
 
 Command Line Arguments
@@ -1955,14 +1952,14 @@ Bytes
 
 ```python
 <bytes> = b'<str>'                       # Only accepts ASCII characters and \x00-\xff.
-<int>   = <bytes>[index]                 # Returns an int in range from 0 to 255.
+<int>   = <bytes>[index]                 # Returns an integer in range from 0 to 255.
 <bytes> = <bytes>[<slice>]               # Returns bytes even if it has only one element.
-<bytes> = <bytes>.join(<coll_of_bytes>)  # Joins elements using bytes as a separator.
+<bytes> = <bytes>.join(<coll_of_bytes>)  # Joins elements by using bytes as a separator.
 ```
 
 ### Encode
 ```python
-<bytes> = bytes(<coll_of_ints>)          # Ints must be in range from 0 to 255.
+<bytes> = bytes(<coll_of_ints>)          # Integers must be in range from 0 to 255.
 <bytes> = bytes(<str>, 'utf-8')          # Encodes the string. Also <str>.encode().
 <bytes> = bytes.fromhex('<hex>')         # Hex pairs can be separated by whitespaces.
 <bytes> = <int>.to_bytes(n_bytes, …)     # `byteorder='big/little', signed=False`.
@@ -1970,7 +1967,7 @@ Bytes
 
 ### Decode
 ```python
-<list>  = list(<bytes>)                  # Returns ints in range from 0 to 255.
+<list>  = list(<bytes>)                  # Returns integers in range from 0 to 255.
 <str>   = str(<bytes>, 'utf-8')          # Returns a string. Also <bytes>.decode().
 <str>   = <bytes>.hex()                  # Returns hex pairs. Accepts `sep=<str>`.
 <int>   = int.from_bytes(<bytes>, …)     # `byteorder='big/little', signed=False`.
@@ -2059,7 +2056,7 @@ Memory View
 
 ```python
 <mview> = memoryview(<bytes/bytearray/array>)  # Immutable if bytes is passed, else mutable.
-<obj>   = <mview>[index]                       # Returns int or float. Bytes if format is 'c'.
+<obj>   = <mview>[index]                       # Returns int/float. Bytes if format is 'c'.
 <mview> = <mview>[<slice>]                     # Returns memoryview with rearranged elements.
 <mview> = <mview>.cast('<typecode>')           # Only works between B/b/c and other types.
 <mview>.release()                              # Releases memory buffer of the base object.
@@ -2126,7 +2123,7 @@ first_element    = op.methodcaller('pop', 0)(<list>)
 
 Match Statement
 ---------------
-**Executes the first block with matching pattern. Added in Python 3.10.**
+**Executes the first block with matching pattern.**
 
 ```python
 match <object/expression>:
@@ -2147,7 +2144,7 @@ match <object/expression>:
 <mapping_patt>  = {<value_pattern>: <patt>, ...}   # Matches dictionary with matching items.
 <class_pattern> = <type>(<attr_name>=<patt>, ...)  # Matches object with matching attributes.
 ```
-* **Sequence pattern can also be written as a tuple.**
+* **Sequence pattern can also be written as a tuple, i.e. `'(<patt_1>, [...])'`.**
 * **Use `'*<name>'` and `'**<name>'` in sequence/mapping patterns to bind remaining items.**
 * **Sequence pattern must match all items of the collection, while mapping pattern does not.**
 * **Patterns can be surrounded with brackets to override precedence (`'|'` > `'as'` > `','`).**
diff --git a/index.html b/index.html
index 02786fc9d..7818c96d0 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 16, 2025</aside>
+    <aside>May 21, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -312,7 +312,7 @@
 <pre><code class="python language-python hljs">&lt;list&gt; = &lt;str&gt;.split()                       <span class="hljs-comment"># Splits on one or more whitespace characters.</span>
 &lt;list&gt; = &lt;str&gt;.split(sep=<span class="hljs-keyword">None</span>, maxsplit=<span class="hljs-number">-1</span>)  <span class="hljs-comment"># Splits on 'sep' str at most 'maxsplit' times.</span>
 &lt;list&gt; = &lt;str&gt;.splitlines(keepends=<span class="hljs-keyword">False</span>)    <span class="hljs-comment"># On [\n\r\f\v\x1c-\x1e\x85\u2028\u2029] and \r\n.</span>
-&lt;str&gt;  = &lt;str&gt;.join(&lt;coll_of_strings&gt;)       <span class="hljs-comment"># Joins elements using string as a separator.</span>
+&lt;str&gt;  = &lt;str&gt;.join(&lt;coll_of_strings&gt;)       <span class="hljs-comment"># Joins elements by using string as a separator.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;bool&gt; = &lt;sub_str&gt; <span class="hljs-keyword">in</span> &lt;str&gt;                  <span class="hljs-comment"># Checks if string contains the substring.</span>
 &lt;bool&gt; = &lt;str&gt;.startswith(&lt;sub_str&gt;)         <span class="hljs-comment"># Pass tuple of strings for multiple options.</span>
@@ -480,8 +480,7 @@
 <span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> log, log10, log2            <span class="hljs-comment"># Log accepts base as second arg.</span>
 </code></pre></div>
 
-<div><h3 id="statistics">Statistics</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> statistics <span class="hljs-keyword">import</span> mean, median, mode    <span class="hljs-comment"># Mode returns the most common value.</span>
-<span class="hljs-keyword">from</span> statistics <span class="hljs-keyword">import</span> variance, stdev       <span class="hljs-comment"># Also: pvariance, pstdev, quantiles.</span>
+<div><h3 id="statistics">Statistics</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> statistics <span class="hljs-keyword">import</span> mean, median, mode    <span class="hljs-comment"># Also: variance, stdev, quantiles.</span>
 </code></pre></div>
 
 <div><h3 id="random">Random</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> random, randint, uniform  <span class="hljs-comment"># Also: gauss, choice, shuffle, seed.</span>
@@ -539,7 +538,7 @@
 <li><strong>Times and datetimes that have defined timezone are called aware and ones that don't, naive. If 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 for one hour.</strong></li>
 <li><strong>Timedelta normalizes arguments to ±days, seconds (&lt; 86 400) and microseconds (&lt; 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 all seconds.</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'&lt;D/DT&gt;.weekday()'</span></code> to get the day of the week as an int, with Monday being 0.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'&lt;D/DT&gt;.weekday()'</span></code> to get the day of the week as an integer, with Monday being 0.</strong></li>
 </ul>
 <div><h3 id="now">Now</h3><pre><code class="python language-python hljs">&lt;D/DTn&gt; = D/DT.today()                      <span class="hljs-comment"># Current local date or naive DT. Also DT.now().</span>
 &lt;DTa&gt;   = DT.now(&lt;tzinfo&gt;)                  <span class="hljs-comment"># Aware DT from current time in passed timezone.</span>
@@ -920,7 +919,7 @@
 <span class="hljs-meta">&gt;&gt;&gt; </span>person.name
 <span class="hljs-string">'Guido van Rossum'</span>
 </code></pre>
-<div><h3 id="slots">Slots</h3><p><strong>Mechanism that restricts objects to attributes listed in 'slots', reduces their memory footprint.</strong></p><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClassWithSlots</span>:</span>
+<div><h3 id="slots">Slots</h3><p><strong>Mechanism that restricts objects to attributes listed in 'slots'.</strong></p><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClassWithSlots</span>:</span>
     __slots__ = [<span class="hljs-string">'a'</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.a = <span class="hljs-number">1</span>
@@ -932,8 +931,7 @@
 </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 has those methods defined 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>.</strong></li>
-<li><strong>That means all user-defined objects compare not equal by default.</strong></li>
+<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 unique identification number (its memory address).</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. False is returned if both return NotImplemented.</strong></li>
 <li><strong>Ne() 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>
@@ -949,9 +947,8 @@
 
 
 <div><h3 id="hashable">Hashable</h3><ul>
-<li><strong>Hashable object needs both hash() and eq() methods and its hash value should 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.</strong></li>
-<li><strong>That is why Python automatically makes classes unhashable if you only implement eq().</strong></li>
+<li><strong>Hashable object needs both hash() and eq() methods and its hash value must not 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 eq().</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
@@ -968,7 +965,7 @@
 
 
 <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 and the rest will be automatically generated.</strong></li>
+<li><strong>With 'total_ordering' decorator, you only need to provide eq() and one of lt(), gt(), le() or ge() special methods (used by &lt;, &gt;, &lt;=, &gt;=) and the rest will be automatically generated.</strong></li>
 <li><strong>Functions sorted() and min() only require lt() method, while max() only requires gt(). However, it is best to define them all so that confusion doesn't arise in other contexts.</strong></li>
 <li><strong>When two lists, strings or dataclasses are compared, their values get compared in order 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 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>
@@ -1036,7 +1033,7 @@
 <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.</strong></li>
-<li><strong>Exit() should release the resources.</strong></li>
+<li><strong>Exit() should release the resources (for example close a file).</strong></li>
 <li><strong>Any exception that happens inside the with block is passed to the exit() method.</strong></li>
 <li><strong>The exit() method can suppress the exception by returning a true value.</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>
@@ -1315,7 +1312,7 @@
 <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 if input stream is exhausted.</strong></li>
+<li><strong>EOFError is raised if user hits EOF (ctrl-d/ctrl-z⏎) or if stream is already exhausted.</strong></li>
 </ul>
 <div><h2 id="commandlinearguments"><a href="#commandlinearguments" name="commandlinearguments">#</a>Command Line 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>]
@@ -1632,19 +1629,19 @@
 ┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
 </code></pre>
 <div><h2 id="bytes"><a href="#bytes" name="bytes">#</a>Bytes</h2><p><strong>A bytes object is an immutable sequence of single bytes. Mutable version is called bytearray.</strong></p><pre><code class="python language-python hljs">&lt;bytes&gt; = <span class="hljs-string">b'&lt;str&gt;'</span>                       <span class="hljs-comment"># Only accepts ASCII characters and \x00-\xff.</span>
-&lt;int&gt;   = &lt;bytes&gt;[index]                 <span class="hljs-comment"># Returns an int in range from 0 to 255.</span>
+&lt;int&gt;   = &lt;bytes&gt;[index]                 <span class="hljs-comment"># Returns an integer in range from 0 to 255.</span>
 &lt;bytes&gt; = &lt;bytes&gt;[&lt;slice&gt;]               <span class="hljs-comment"># Returns bytes even if it has only one element.</span>
-&lt;bytes&gt; = &lt;bytes&gt;.join(&lt;coll_of_bytes&gt;)  <span class="hljs-comment"># Joins elements using bytes as a separator.</span>
+&lt;bytes&gt; = &lt;bytes&gt;.join(&lt;coll_of_bytes&gt;)  <span class="hljs-comment"># Joins elements by using bytes as a separator.</span>
 </code></pre></div>
 
 
-<div><h3 id="encode-1">Encode</h3><pre><code class="python language-python hljs">&lt;bytes&gt; = bytes(&lt;coll_of_ints&gt;)          <span class="hljs-comment"># Ints must be in range from 0 to 255.</span>
+<div><h3 id="encode-1">Encode</h3><pre><code class="python language-python hljs">&lt;bytes&gt; = bytes(&lt;coll_of_ints&gt;)          <span class="hljs-comment"># Integers must be in range from 0 to 255.</span>
 &lt;bytes&gt; = bytes(&lt;str&gt;, <span class="hljs-string">'utf-8'</span>)          <span class="hljs-comment"># Encodes the string. Also &lt;str&gt;.encode().</span>
 &lt;bytes&gt; = bytes.fromhex(<span class="hljs-string">'&lt;hex&gt;'</span>)         <span class="hljs-comment"># Hex pairs can be separated by whitespaces.</span>
 &lt;bytes&gt; = &lt;int&gt;.to_bytes(n_bytes, …)     <span class="hljs-comment"># `byteorder='big/little', signed=False`.</span>
 </code></pre></div>
 
-<div><h3 id="decode-1">Decode</h3><pre><code class="python language-python hljs">&lt;list&gt;  = list(&lt;bytes&gt;)                  <span class="hljs-comment"># Returns ints in range from 0 to 255.</span>
+<div><h3 id="decode-1">Decode</h3><pre><code class="python language-python hljs">&lt;list&gt;  = list(&lt;bytes&gt;)                  <span class="hljs-comment"># Returns integers in range from 0 to 255.</span>
 &lt;str&gt;   = str(&lt;bytes&gt;, <span class="hljs-string">'utf-8'</span>)          <span class="hljs-comment"># Returns a string. Also &lt;bytes&gt;.decode().</span>
 &lt;str&gt;   = &lt;bytes&gt;.hex()                  <span class="hljs-comment"># Returns hex pairs. Accepts `sep=&lt;str&gt;`.</span>
 &lt;int&gt;   = int.from_bytes(&lt;bytes&gt;, …)     <span class="hljs-comment"># `byteorder='big/little', signed=False`.</span>
@@ -1713,7 +1710,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;file&gt;.write(&lt;array&gt;)                          <span class="hljs-comment"># Writes array's memory to the 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">&lt;mview&gt; = memoryview(&lt;bytes/bytearray/array&gt;)  <span class="hljs-comment"># Immutable if bytes is passed, else mutable.</span>
-&lt;obj&gt;   = &lt;mview&gt;[index]                       <span class="hljs-comment"># Returns int or float. Bytes if format is 'c'.</span>
+&lt;obj&gt;   = &lt;mview&gt;[index]                       <span class="hljs-comment"># Returns int/float. Bytes if format is 'c'.</span>
 &lt;mview&gt; = &lt;mview&gt;[&lt;slice&gt;]                     <span class="hljs-comment"># Returns memoryview with rearranged elements.</span>
 &lt;mview&gt; = &lt;mview&gt;.cast(<span class="hljs-string">'&lt;typecode&gt;'</span>)           <span class="hljs-comment"># Only works between B/b/c and other types.</span>
 &lt;mview&gt;.release()                              <span class="hljs-comment"># Releases memory buffer of the base object.</span>
@@ -1761,7 +1758,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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>Comparisons can be chained: <code class="python hljs"><span class="hljs-string">'x &lt; y &lt; z'</span></code> gets converted to <code class="python hljs"><span class="hljs-string">'(x &lt; y) and (y &lt; 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. Added in Python 3.10.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">match</span> &lt;object/expression&gt;:
+<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"><span class="hljs-keyword">match</span> &lt;object/expression&gt;:
     <span class="hljs-keyword">case</span> &lt;pattern&gt; [<span class="hljs-keyword">if</span> &lt;condition&gt;]:
         &lt;code&gt;
     ...
@@ -1780,7 +1777,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 <ul>
-<li><strong>Sequence pattern can also be written as a tuple.</strong></li>
+<li><strong>Sequence pattern can also be written as a tuple, i.e. <code class="python hljs"><span class="hljs-string">'(&lt;patt_1&gt;, [...])'</span></code>.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'*&lt;name&gt;'</span></code> and <code class="python hljs"><span class="hljs-string">'**&lt;name&gt;'</span></code> in sequence/mapping patterns to bind remaining items.</strong></li>
 <li><strong>Sequence pattern must match all items of the collection, while mapping pattern does not.</strong></li>
 <li><strong>Patterns can be surrounded with brackets to override precedence (<code class="python hljs"><span class="hljs-string">'|'</span></code> &gt; <code class="python hljs"><span class="hljs-string">'as'</span></code> &gt; <code class="python hljs"><span class="hljs-string">','</span></code>).</strong></li>
@@ -2945,7 +2942,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 16, 2025</aside>
+    <aside>May 21, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 32e730e930943384f96236ca370e7c29b700e005 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 30 May 2025 07:33:06 +0200
Subject: [PATCH 147/186] String, Class, Image, Pygame

---
 README.md  | 49 +++++++++++++++++++++++--------------------------
 index.html | 53 +++++++++++++++++++++++++----------------------------
 parse.js   |  3 +--
 3 files changed, 49 insertions(+), 56 deletions(-)

diff --git a/README.md b/README.md
index 82173e88f..38278b343 100644
--- a/README.md
+++ b/README.md
@@ -337,8 +337,8 @@ String
 ```
 
 ```python
-<str>  = chr(<int>)                          # Converts int to Unicode character.
-<int>  = ord(<str>)                          # Converts Unicode character to int.
+<str>  = chr(<int>)                          # Converts passed integer to Unicode character.
+<int>  = ord(<str>)                          # Converts passed Unicode character to integer.
 ```
 * **Use `'unicodedata.normalize("NFC", <str>)'` on strings like `'Motörhead'` before comparing them to other strings, because `'ö'` can be stored as one or two characters.**
 * **`'NFC'` converts such characters to a single character, while `'NFD'` converts them to two.**
@@ -972,9 +972,8 @@ class MyClass:
 >>> obj.a, str(obj), repr(obj)
 (1, '1', 'MyClass(1)')
 ```
-* **Return value of str() should be readable and of repr() unambiguous.**
-* **If only repr() is defined, it will also be used for str().**
-* **Methods decorated with `'@staticmethod'` do not receive 'self' nor 'cls' as their first argument.**
+* **Methods whose names start and end with two underscores are called special methods. They are executed when object is passed to a built-in function or used as an operand, for example, `'print(a)'` calls `'a.__str__()'` and `'a + b'` calls `'a.__add__(b)'`.**
+* **Return value of str() special method should be readable and of repr() unambiguous. If only repr() is defined, it will also be used for str().**
 
 #### Expressions that call the str() method:
 ```python
@@ -982,7 +981,6 @@ print(<obj>)
 f'{<obj>}'
 logging.warning(<obj>)
 csv.writer(<file>).writerow([<obj>])
-raise Exception(<obj>)
 ```
 
 #### Expressions that call the repr() method:
@@ -991,11 +989,10 @@ print/str/repr([<obj>])
 print/str/repr({<obj>: <obj>})
 f'{<obj>!r}'
 Z = make_dataclass('Z', ['a']); print/str/repr(Z(<obj>))
->>> <obj>
 ```
 
 ### Subclass
-* **Inheritance is a mechanism that enables a class to extend another class (subclass to extend its parent), and by doing so inherit all its methods and attributes.**
+* **Inheritance is a mechanism that enables a class to extend some other class (that is, subclass to extend its parent), and by doing so inherit all its methods and attributes.**
 * **Subclass can then add its own methods and attributes or override inherited ones by reusing their names.**
 
 ```python
@@ -1694,7 +1691,7 @@ from pathlib import Path
 ```
 
 ```python
-<str>  = str(<Path>)                # Returns path as str. Also <Path>.as_uri().
+<str>  = str(<Path>)                # Returns path as string. Also <Path>.as_uri().
 <file> = open(<Path>)               # Also <Path>.read/write_text/bytes(<args>).
 ```
 
@@ -2765,7 +2762,7 @@ from PIL import Image
 <Image> = Image.new('<mode>', (width, height))  # Creates new image. Also `color=<int/tuple>`.
 <Image> = Image.open(<path>)                    # Identifies format based on file's contents.
 <Image> = <Image>.convert('<mode>')             # Converts image to the new mode (see Modes).
-<Image>.save(<path>)                            # Selects format based on extension (PNG/JPG…).
+<Image>.save(<path>)                            # Accepts `quality=<int>` if extension is jpg.
 <Image>.show()                                  # Displays image in default preview app.
 ```
 
@@ -2788,8 +2785,8 @@ from PIL import Image
 ```
 
 ### Modes
-* **`'L'` - Lightness (greyscale image). Each pixel is an int between 0 and 255.**
-* **`'RGB'` - Red, green, blue (true color image). Each pixel is a tuple of three ints.**
+* **`'L'` - Lightness (greyscale image). Each pixel is an integer between 0 and 255.**
+* **`'RGB'` - Red, green, blue (true color image). Each pixel is a tuple of three integers.**
 * **`'RGBA'` - RGB with alpha. Low alpha (i.e. forth int) makes pixel more transparent.**
 * **`'HSV'` - Hue, saturation, value. Three ints representing color in HSV color space.**
 
@@ -2989,10 +2986,10 @@ pg.init()
 screen = pg.display.set_mode((500, 500))
 rect = pg.Rect(240, 240, 20, 20)
 while not pg.event.get(pg.QUIT):
-    deltas = {pg.K_UP: (0, -1), pg.K_RIGHT: (1, 0), pg.K_DOWN: (0, 1), pg.K_LEFT: (-1, 0)}
     for event in pg.event.get(pg.KEYDOWN):
-        x, y = deltas.get(event.key, (0, 0))
-        rect = rect.move((x*20, y*20))
+        dx = (event.key == pg.K_RIGHT) - (event.key == pg.K_LEFT)
+        dy = (event.key == pg.K_DOWN) - (event.key == pg.K_UP)
+        rect = rect.move((dx * 20, dy * 20))
     screen.fill(pg.Color('black'))
     pg.draw.rect(screen, pg.Color('white'), rect)
     pg.display.flip()
@@ -3004,13 +3001,13 @@ pg.quit()
 ```python
 <Rect> = pg.Rect(x, y, width, height)           # Creates Rect object. Truncates passed floats.
 <int>  = <Rect>.x/y/centerx/centery/…           # `top/right/bottom/left`. Allows assignments.
-<tup.> = <Rect>.topleft/center/…                # `topright/bottomright/bottomleft`. Same.
-<Rect> = <Rect>.move((delta_x, delta_y))        # Use move_ip() to move in-place.
+<tup.> = <Rect>.topleft/center/…                # `topright/bottomright/bottomleft/size`. Same.
+<Rect> = <Rect>.move((delta_x, delta_y))        # Use move_ip() to move the rectangle in-place.
 ```
 
 ```python
-<bool> = <Rect>.collidepoint((x, y))            # Checks if rectangle contains the point.
-<bool> = <Rect>.colliderect(<Rect>)             # Checks if the two rectangles overlap.
+<bool> = <Rect>.collidepoint((x, y))            # Checks whether rectangle contains the point.
+<bool> = <Rect>.colliderect(<Rect>)             # Checks whether the two rectangles overlap.
 <int>  = <Rect>.collidelist(<list_of_Rect>)     # Returns index of first colliding Rect or -1.
 <list> = <Rect>.collidelistall(<list_of_Rect>)  # Returns indices of all colliding rectangles.
 ```
@@ -3018,7 +3015,7 @@ pg.quit()
 ### Surface
 **Object for representing images.**
 ```python
-<Surf> = pg.display.set_mode((width, height))   # Opens new window and returns its surface.
+<Surf> = pg.display.set_mode((width, height))   # Opens a new window and returns its surface.
 <Surf> = pg.Surface((width, height))            # New RGB surface. RGBA if `flags=pg.SRCALPHA`.
 <Surf> = pg.image.load(<path/file>)             # Loads the image. Format depends on source.
 <Surf> = pg.surfarray.make_surface(<np_array>)  # Also `<np_arr> = surfarray.pixels3d(<Surf>)`.
@@ -3032,15 +3029,15 @@ pg.quit()
 ```
 
 ```python
-from pygame.transform import scale, ...
-<Surf> = scale(<Surf>, (width, height))         # Returns scaled surface.
-<Surf> = rotate(<Surf>, anticlock_degrees)      # Returns rotated and scaled surface.
-<Surf> = flip(<Surf>, x_bool, y_bool)           # Returns flipped surface.
+from pygame.transform import scale, rotate      # Also: flip, smoothscale, scale_by.
+<Surf> = scale(<Surf>, (width, height))         # Scales the surface. `smoothscale()` blurs it.
+<Surf> = rotate(<Surf>, angle)                  # Rotates the surface for counterclock degrees.
+<Surf> = flip(<Surf>, flip_x=False)             # Mirrors the surface. Also `flip_y=False`.
 ```
 
 ```python
-from pygame.draw import line, ...
-line(<Surf>, color, (x1, y1), (x2, y2), width)  # Draws a line to the surface.
+from pygame.draw import line, arc, rect         # Also: ellipse, polygon, circle, aaline.
+line(<Surf>, color, (x1, y1), (x2, y2))         # Draws a line to the surface. Also `width=1`.
 arc(<Surf>, color, <Rect>, from_rad, to_rad)    # Also ellipse(<Surf>, color, <Rect>, width=0).
 rect(<Surf>, color, <Rect>, width=0)            # Also polygon(<Surf>, color, points, width=0).
 ```
diff --git a/index.html b/index.html
index 7818c96d0..75a71a5d0 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 21, 2025</aside>
+    <aside>May 30, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -323,8 +323,8 @@
 &lt;str&gt;  = &lt;str&gt;.replace(old, new [, count])   <span class="hljs-comment"># Replaces 'old' with 'new' at most 'count' times.</span>
 &lt;str&gt;  = &lt;str&gt;.translate(&lt;table&gt;)            <span class="hljs-comment"># Use `str.maketrans(&lt;dict&gt;)` to generate table.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;str&gt;  = chr(&lt;int&gt;)                          <span class="hljs-comment"># Converts int to Unicode character.</span>
-&lt;int&gt;  = ord(&lt;str&gt;)                          <span class="hljs-comment"># Converts Unicode character to int.</span>
+<pre><code class="python language-python hljs">&lt;str&gt;  = chr(&lt;int&gt;)                          <span class="hljs-comment"># Converts passed integer to Unicode character.</span>
+&lt;int&gt;  = ord(&lt;str&gt;)                          <span class="hljs-comment"># Converts passed Unicode character to integer.</span>
 </code></pre>
 <ul>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'unicodedata.normalize("NFC", &lt;str&gt;)'</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>
@@ -830,26 +830,23 @@
 (<span class="hljs-number">1</span>, <span class="hljs-string">'1'</span>, <span class="hljs-string">'MyClass(1)'</span>)
 </code></pre>
 <ul>
-<li><strong>Return value of str() should be readable and of repr() unambiguous.</strong></li>
-<li><strong>If only repr() is defined, it will also be used for str().</strong></li>
-<li><strong>Methods decorated with <code class="python hljs"><span class="hljs-string">'@staticmethod'</span></code> do not receive 'self' nor 'cls' as their first argument.</strong></li>
+<li><strong>Methods whose names start and end with two underscores are called special methods. 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>Return value of str() special method should be readable and of repr() unambiguous. If only repr() is defined, it will also be used for str().</strong></li>
 </ul>
 <div><h4 id="expressionsthatcallthestrmethod">Expressions that call the str() method:</h4><pre><code class="python language-python hljs">print(&lt;obj&gt;)
 <span class="hljs-string">f'<span class="hljs-subst">{&lt;obj&gt;}</span>'</span>
 logging.warning(&lt;obj&gt;)
 csv.writer(&lt;file&gt;).writerow([&lt;obj&gt;])
-<span class="hljs-keyword">raise</span> Exception(&lt;obj&gt;)
 </code></pre></div>
 
 <div><h4 id="expressionsthatcallthereprmethod">Expressions that call the repr() method:</h4><pre><code class="python language-python hljs">print/str/repr([&lt;obj&gt;])
 print/str/repr({&lt;obj&gt;: &lt;obj&gt;})
 <span class="hljs-string">f'<span class="hljs-subst">{&lt;obj&gt;!r}</span>'</span>
 Z = make_dataclass(<span class="hljs-string">'Z'</span>, [<span class="hljs-string">'a'</span>]); print/str/repr(Z(&lt;obj&gt;))
-<span class="hljs-meta">&gt;&gt;&gt; </span>&lt;obj&gt;
 </code></pre></div>
 
 <div><h3 id="subclass">Subclass</h3><ul>
-<li><strong>Inheritance is a mechanism that enables a class to extend another class (subclass to extend its parent), and by doing so inherit all its methods and attributes.</strong></li>
+<li><strong>Inheritance is a mechanism that enables a class to extend some other class (that is, subclass to extend its parent), and by doing so inherit all 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>
@@ -1439,7 +1436,7 @@
 <pre><code class="python language-python hljs">&lt;iter&gt; = &lt;Path&gt;.iterdir()           <span class="hljs-comment"># Returns directory contents as Path objects.</span>
 &lt;iter&gt; = &lt;Path&gt;.glob(<span class="hljs-string">'&lt;pattern&gt;'</span>)   <span class="hljs-comment"># Returns Paths matching the wildcard pattern.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;str&gt;  = str(&lt;Path&gt;)                <span class="hljs-comment"># Returns path as str. Also &lt;Path&gt;.as_uri().</span>
+<pre><code class="python language-python hljs">&lt;str&gt;  = str(&lt;Path&gt;)                <span class="hljs-comment"># Returns path as string. Also &lt;Path&gt;.as_uri().</span>
 &lt;file&gt; = open(&lt;Path&gt;)               <span class="hljs-comment"># Also &lt;Path&gt;.read/write_text/bytes(&lt;args&gt;).</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, subprocess
@@ -2272,7 +2269,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <pre><code class="python language-python hljs">&lt;Image&gt; = Image.new(<span class="hljs-string">'&lt;mode&gt;'</span>, (width, height))  <span class="hljs-comment"># Creates new image. Also `color=&lt;int/tuple&gt;`.</span>
 &lt;Image&gt; = Image.open(&lt;path&gt;)                    <span class="hljs-comment"># Identifies format based on file's contents.</span>
 &lt;Image&gt; = &lt;Image&gt;.convert(<span class="hljs-string">'&lt;mode&gt;'</span>)             <span class="hljs-comment"># Converts image to the new mode (see Modes).</span>
-&lt;Image&gt;.save(&lt;path&gt;)                            <span class="hljs-comment"># Selects format based on extension (PNG/JPG…).</span>
+&lt;Image&gt;.save(&lt;path&gt;)                            <span class="hljs-comment"># Accepts `quality=&lt;int&gt;` if extension is jpg.</span>
 &lt;Image&gt;.show()                                  <span class="hljs-comment"># Displays image in default preview app.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;int/tup&gt; = &lt;Image&gt;.getpixel((x, y))            <span class="hljs-comment"># Returns pixel's value (its color).</span>
@@ -2288,8 +2285,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;Image&gt; = Image.fromarray(np.uint8(&lt;array&gt;))    <span class="hljs-comment"># Use &lt;array&gt;.clip(0, 255) to clip the values.</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 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 ints.</strong></li>
+<li><strong><code class="python hljs"><span class="hljs-string">'L'</span></code> - Lightness (greyscale image). Each pixel is an integer 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. forth 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">WIDTH, HEIGHT = <span class="hljs-number">100</span>, <span class="hljs-number">100</span>
@@ -2452,10 +2449,10 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 screen = 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):
-    deltas = {pg.K_UP: (<span class="hljs-number">0</span>, <span class="hljs-number">-1</span>), pg.K_RIGHT: (<span class="hljs-number">1</span>, <span class="hljs-number">0</span>), pg.K_DOWN: (<span class="hljs-number">0</span>, <span class="hljs-number">1</span>), pg.K_LEFT: (<span class="hljs-number">-1</span>, <span class="hljs-number">0</span>)}
     <span class="hljs-keyword">for</span> event <span class="hljs-keyword">in</span> pg.event.get(pg.KEYDOWN):
-        x, y = deltas.get(event.key, (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>))
-        rect = rect.move((x*<span class="hljs-number">20</span>, y*<span class="hljs-number">20</span>))
+        dx = (event.key == pg.K_RIGHT) - (event.key == pg.K_LEFT)
+        dy = (event.key == pg.K_DOWN) - (event.key == pg.K_UP)
+        rect = rect.move((dx * <span class="hljs-number">20</span>, dy * <span class="hljs-number">20</span>))
     screen.fill(pg.Color(<span class="hljs-string">'black'</span>))
     pg.draw.rect(screen, pg.Color(<span class="hljs-string">'white'</span>), rect)
     pg.display.flip()
@@ -2465,17 +2462,17 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <div><h3 id="rect">Rect</h3><p><strong>Object for storing rectangular coordinates.</strong></p><pre><code class="python language-python hljs">&lt;Rect&gt; = pg.Rect(x, y, width, height)           <span class="hljs-comment"># Creates Rect object. Truncates passed floats.</span>
 &lt;int&gt;  = &lt;Rect&gt;.x/y/centerx/centery/…           <span class="hljs-comment"># `top/right/bottom/left`. Allows assignments.</span>
-&lt;tup.&gt; = &lt;Rect&gt;.topleft/center/…                <span class="hljs-comment"># `topright/bottomright/bottomleft`. Same.</span>
-&lt;Rect&gt; = &lt;Rect&gt;.move((delta_x, delta_y))        <span class="hljs-comment"># Use move_ip() to move in-place.</span>
+&lt;tup.&gt; = &lt;Rect&gt;.topleft/center/…                <span class="hljs-comment"># `topright/bottomright/bottomleft/size`. Same.</span>
+&lt;Rect&gt; = &lt;Rect&gt;.move((delta_x, delta_y))        <span class="hljs-comment"># Use move_ip() to move the rectangle in-place.</span>
 </code></pre></div>
 
 
-<pre><code class="python language-python hljs">&lt;bool&gt; = &lt;Rect&gt;.collidepoint((x, y))            <span class="hljs-comment"># Checks if rectangle contains the point.</span>
-&lt;bool&gt; = &lt;Rect&gt;.colliderect(&lt;Rect&gt;)             <span class="hljs-comment"># Checks if the two rectangles overlap.</span>
+<pre><code class="python language-python hljs">&lt;bool&gt; = &lt;Rect&gt;.collidepoint((x, y))            <span class="hljs-comment"># Checks whether rectangle contains the point.</span>
+&lt;bool&gt; = &lt;Rect&gt;.colliderect(&lt;Rect&gt;)             <span class="hljs-comment"># Checks whether the two rectangles overlap.</span>
 &lt;int&gt;  = &lt;Rect&gt;.collidelist(&lt;list_of_Rect&gt;)     <span class="hljs-comment"># Returns index of first colliding Rect or -1.</span>
 &lt;list&gt; = &lt;Rect&gt;.collidelistall(&lt;list_of_Rect&gt;)  <span class="hljs-comment"># Returns indices of all colliding rectangles.</span>
 </code></pre>
-<div><h3 id="surface">Surface</h3><p><strong>Object for representing images.</strong></p><pre><code class="python language-python hljs">&lt;Surf&gt; = pg.display.set_mode((width, height))   <span class="hljs-comment"># Opens new window and returns its surface.</span>
+<div><h3 id="surface">Surface</h3><p><strong>Object for representing images.</strong></p><pre><code class="python language-python hljs">&lt;Surf&gt; = pg.display.set_mode((width, height))   <span class="hljs-comment"># Opens a new window and returns its surface.</span>
 &lt;Surf&gt; = pg.Surface((width, height))            <span class="hljs-comment"># New RGB surface. RGBA if `flags=pg.SRCALPHA`.</span>
 &lt;Surf&gt; = pg.image.load(&lt;path/file&gt;)             <span class="hljs-comment"># Loads the image. Format depends on source.</span>
 &lt;Surf&gt; = pg.surfarray.make_surface(&lt;np_array&gt;)  <span class="hljs-comment"># Also `&lt;np_arr&gt; = surfarray.pixels3d(&lt;Surf&gt;)`.</span>
@@ -2487,13 +2484,13 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;Surf&gt;.set_at((x, y), color)                    <span class="hljs-comment"># Updates pixel. Also &lt;Surf&gt;.get_at((x, y)).</span>
 &lt;Surf&gt;.blit(&lt;Surf&gt;, (x, y))                     <span class="hljs-comment"># Draws passed surface at specified location.</span>
 </code></pre>
-<pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> pygame.transform <span class="hljs-keyword">import</span> scale, ...
-&lt;Surf&gt; = scale(&lt;Surf&gt;, (width, height))         <span class="hljs-comment"># Returns scaled surface.</span>
-&lt;Surf&gt; = rotate(&lt;Surf&gt;, anticlock_degrees)      <span class="hljs-comment"># Returns rotated and scaled surface.</span>
-&lt;Surf&gt; = flip(&lt;Surf&gt;, x_bool, y_bool)           <span class="hljs-comment"># Returns flipped surface.</span>
+<pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> pygame.transform <span class="hljs-keyword">import</span> scale, rotate      <span class="hljs-comment"># Also: flip, smoothscale, scale_by.</span>
+&lt;Surf&gt; = scale(&lt;Surf&gt;, (width, height))         <span class="hljs-comment"># Scales the surface. `smoothscale()` blurs it.</span>
+&lt;Surf&gt; = rotate(&lt;Surf&gt;, angle)                  <span class="hljs-comment"># Rotates the surface for counterclock degrees.</span>
+&lt;Surf&gt; = flip(&lt;Surf&gt;, flip_x=<span class="hljs-keyword">False</span>)             <span class="hljs-comment"># Mirrors the surface. Also `flip_y=False`.</span>
 </code></pre>
-<pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> pygame.draw <span class="hljs-keyword">import</span> line, ...
-line(&lt;Surf&gt;, color, (x1, y1), (x2, y2), width)  <span class="hljs-comment"># Draws a line to the surface.</span>
+<pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> pygame.draw <span class="hljs-keyword">import</span> line, arc, rect         <span class="hljs-comment"># Also: ellipse, polygon, circle, aaline.</span>
+line(&lt;Surf&gt;, color, (x1, y1), (x2, y2))         <span class="hljs-comment"># Draws a line to the surface. Also `width=1`.</span>
 arc(&lt;Surf&gt;, color, &lt;Rect&gt;, from_rad, to_rad)    <span class="hljs-comment"># Also ellipse(&lt;Surf&gt;, color, &lt;Rect&gt;, width=0).</span>
 rect(&lt;Surf&gt;, color, &lt;Rect&gt;, width=<span class="hljs-number">0</span>)            <span class="hljs-comment"># Also polygon(&lt;Surf&gt;, color, points, width=0).</span>
 </code></pre>
@@ -2942,7 +2939,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 21, 2025</aside>
+    <aside>May 30, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 3d186693b..a54d578a8 100755
--- a/parse.js
+++ b/parse.js
@@ -83,8 +83,7 @@ const REPR_USE_CASES =
   'print/str/repr([&lt;obj&gt;])\n' +
   'print/str/repr({&lt;obj&gt;: &lt;obj&gt;})\n' +
   '<span class="hljs-string">f\'<span class="hljs-subst">{&lt;obj&gt;!r}</span>\'</span>\n' +
-  'Z = make_dataclass(<span class="hljs-string">\'Z\'</span>, [<span class="hljs-string">\'a\'</span>]); print/str/repr(Z(&lt;obj&gt;))\n' +
-  '<span class="hljs-meta">&gt;&gt;&gt; </span>&lt;obj&gt;\n';
+  'Z = make_dataclass(<span class="hljs-string">\'Z\'</span>, [<span class="hljs-string">\'a\'</span>]); print/str/repr(Z(&lt;obj&gt;))\n';
 
 const CONSTRUCTOR_OVERLOADING =
   '<span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">name</span>&gt;:</span>\n' +

From f7af2899f4311fd0d675379cedd658ba08d113e0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 30 May 2025 15:07:37 +0200
Subject: [PATCH 148/186] Class, Plotly

---
 README.md  | 13 +++++++------
 index.html | 13 +++++++------
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
index 38278b343..234849ff6 100644
--- a/README.md
+++ b/README.md
@@ -973,6 +973,7 @@ class MyClass:
 (1, '1', 'MyClass(1)')
 ```
 * **Methods whose names start and end with two underscores are called special methods. They are executed when object is passed to a built-in function or used as an operand, for example, `'print(a)'` calls `'a.__str__()'` and `'a + b'` calls `'a.__add__(b)'`.**
+* **Methods decorated with `'@staticmethod'` receive neither 'self' nor 'cls' argument.**
 * **Return value of str() special method should be readable and of repr() unambiguous. If only repr() is defined, it will also be used for str().**
 
 #### Expressions that call the str() method:
@@ -3408,16 +3409,16 @@ import plotly.express as px, pandas as pd
 ```
 
 ```python
-<Fig> = px.line(<DF>, x=col_key, y=col_key)           # Or: px.line(x=<list>, y=<list>)
-<Fig>.update_layout(margin=dict(t=0, r=0, b=0, l=0))  # Also `paper_bgcolor='rgb(0, 0, 0)'`.
+<Fig> = px.line(<DF> [, y=col_key/s [, x=col_key]])   # Also px.line(y=<list> [, x=<list>]).
+<Fig>.update_layout(paper_bgcolor='rgb(0, 0, 0)')     # Also `margin=dict(t=0, r=0, b=0, l=0)`.
 <Fig>.write_html/json/image('<path>')                 # `<Fig>.show()` displays the plot.
 ```
 
 ```python
-<Fig> = px.area/bar/box(<DF>, x=col_key, y=col_key)   # Also `color=col_key`.
-<Fig> = px.scatter(<DF>, x=col_key, y=col_key)        # Also `color/size/symbol=col_key`.
-<Fig> = px.scatter_3d(<DF>, x=col_key, y=col_key, …)  # `z=col_key`. Also color/size/symbol.
-<Fig> = px.histogram(<DF>, x=col_key)                 # Also `nbins=<int>`.
+<Fig> = px.area/bar/box(<DF>, x=col_key, y=col_keys)  # Also `color=col_key`. All are optional.
+<Fig> = px.scatter(<DF>, x=col_key, y=col_keys)       # Also `color/size/symbol=col_key`. Same.
+<Fig> = px.scatter_3d(<DF>, x=col_key, y=col_key, …)  # `z=col_key`. Also color, size, symbol.
+<Fig> = px.histogram(<DF>, x=col_keys, y=col_key)     # Also `nbins=<int>`. All are optional.
 ```
 
 #### Displays a line chart of total coronavirus deaths per million grouped by continent:
diff --git a/index.html b/index.html
index 75a71a5d0..3fb5e272c 100644
--- a/index.html
+++ b/index.html
@@ -831,6 +831,7 @@
 </code></pre>
 <ul>
 <li><strong>Methods whose names start and end with two underscores are called special methods. 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>Methods decorated with <code class="python hljs"><span class="hljs-string">'@staticmethod'</span></code> receive neither 'self' nor 'cls' argument.</strong></li>
 <li><strong>Return value of str() special method should be readable and of repr() unambiguous. If only repr() is defined, it will also be used for str().</strong></li>
 </ul>
 <div><h4 id="expressionsthatcallthestrmethod">Expressions that call the str() method:</h4><pre><code class="python language-python hljs">print(&lt;obj&gt;)
@@ -2787,14 +2788,14 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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">&lt;Fig&gt; = px.line(&lt;DF&gt;, x=col_key, y=col_key)           <span class="hljs-comment"># Or: px.line(x=&lt;list&gt;, y=&lt;list&gt;)</span>
-&lt;Fig&gt;.update_layout(margin=dict(t=<span class="hljs-number">0</span>, r=<span class="hljs-number">0</span>, b=<span class="hljs-number">0</span>, l=<span class="hljs-number">0</span>))  <span class="hljs-comment"># Also `paper_bgcolor='rgb(0, 0, 0)'`.</span>
+<pre><code class="python language-python hljs">&lt;Fig&gt; = px.line(&lt;DF&gt; [, y=col_key/s [, x=col_key]])   <span class="hljs-comment"># Also px.line(y=&lt;list&gt; [, x=&lt;list&gt;]).</span>
+&lt;Fig&gt;.update_layout(paper_bgcolor=<span class="hljs-string">'rgb(0, 0, 0)'</span>)     <span class="hljs-comment"># Also `margin=dict(t=0, r=0, b=0, l=0)`.</span>
 &lt;Fig&gt;.write_html/json/image(<span class="hljs-string">'&lt;path&gt;'</span>)                 <span class="hljs-comment"># `&lt;Fig&gt;.show()` displays the plot.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;Fig&gt; = px.area/bar/box(&lt;DF&gt;, x=col_key, y=col_key)   <span class="hljs-comment"># Also `color=col_key`.</span>
-&lt;Fig&gt; = px.scatter(&lt;DF&gt;, x=col_key, y=col_key)        <span class="hljs-comment"># Also `color/size/symbol=col_key`.</span>
-&lt;Fig&gt; = px.scatter_3d(&lt;DF&gt;, x=col_key, y=col_key, …)  <span class="hljs-comment"># `z=col_key`. Also color/size/symbol.</span>
-&lt;Fig&gt; = px.histogram(&lt;DF&gt;, x=col_key)                 <span class="hljs-comment"># Also `nbins=&lt;int&gt;`.</span>
+<pre><code class="python language-python hljs">&lt;Fig&gt; = px.area/bar/box(&lt;DF&gt;, x=col_key, y=col_keys)  <span class="hljs-comment"># Also `color=col_key`. All are optional.</span>
+&lt;Fig&gt; = px.scatter(&lt;DF&gt;, x=col_key, y=col_keys)       <span class="hljs-comment"># Also `color/size/symbol=col_key`. Same.</span>
+&lt;Fig&gt; = px.scatter_3d(&lt;DF&gt;, x=col_key, y=col_key, …)  <span class="hljs-comment"># `z=col_key`. Also color, size, symbol.</span>
+&lt;Fig&gt; = px.histogram(&lt;DF&gt;, x=col_keys, y=col_key)     <span class="hljs-comment"># Also `nbins=&lt;int&gt;`. All are optional.</span>
 </code></pre>
 <div><h4 id="displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">Displays a line chart of total coronavirus 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>,

From c3470220f365d059ef73c280cd874757a57ef0d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 31 May 2025 05:07:15 +0200
Subject: [PATCH 149/186] Plotly

---
 README.md  |  6 +++---
 index.html | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 234849ff6..b385b3f9f 100644
--- a/README.md
+++ b/README.md
@@ -3411,14 +3411,14 @@ import plotly.express as px, pandas as pd
 ```python
 <Fig> = px.line(<DF> [, y=col_key/s [, x=col_key]])   # Also px.line(y=<list> [, x=<list>]).
 <Fig>.update_layout(paper_bgcolor='rgb(0, 0, 0)')     # Also `margin=dict(t=0, r=0, b=0, l=0)`.
-<Fig>.write_html/json/image('<path>')                 # `<Fig>.show()` displays the plot.
+<Fig>.write_html/json/image('<path>')                 # Use <Fig>.show() to display the plot.
 ```
 
 ```python
 <Fig> = px.area/bar/box(<DF>, x=col_key, y=col_keys)  # Also `color=col_key`. All are optional.
 <Fig> = px.scatter(<DF>, x=col_key, y=col_keys)       # Also `color/size/symbol=col_key`. Same.
 <Fig> = px.scatter_3d(<DF>, x=col_key, y=col_key, …)  # `z=col_key`. Also color, size, symbol.
-<Fig> = px.histogram(<DF>, x=col_keys, y=col_key)     # Also `nbins=<int>`. All are optional.
+<Fig> = px.histogram(<DF>, x=col_keys, y=col_key)     # Also color, nbins. All are optional.
 ```
 
 #### Displays a line chart of total coronavirus deaths per million grouped by continent:
@@ -3437,7 +3437,7 @@ df = df.groupby(['Continent_Name', 'date']).sum().reset_index()
 df['Total Deaths per Million'] = df.total_deaths * 1e6 / df.population
 df = df[df.date > '2020-03-14']
 df = df.rename({'date': 'Date', 'Continent_Name': 'Continent'}, axis='columns')
-px.line(df, x='Date', y='Total Deaths per Million', color='Continent').show()
+px.line(df, x='Date', y='Total Deaths per Million', color='Continent')
 ```
 
 #### Displays a multi-axis line chart of total coronavirus cases and changes in prices of Bitcoin, Dow Jones and gold:
diff --git a/index.html b/index.html
index 3fb5e272c..eec6ff0e2 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 30, 2025</aside>
+    <aside>May 31, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2790,12 +2790,12 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <pre><code class="python language-python hljs">&lt;Fig&gt; = px.line(&lt;DF&gt; [, y=col_key/s [, x=col_key]])   <span class="hljs-comment"># Also px.line(y=&lt;list&gt; [, x=&lt;list&gt;]).</span>
 &lt;Fig&gt;.update_layout(paper_bgcolor=<span class="hljs-string">'rgb(0, 0, 0)'</span>)     <span class="hljs-comment"># Also `margin=dict(t=0, r=0, b=0, l=0)`.</span>
-&lt;Fig&gt;.write_html/json/image(<span class="hljs-string">'&lt;path&gt;'</span>)                 <span class="hljs-comment"># `&lt;Fig&gt;.show()` displays the plot.</span>
+&lt;Fig&gt;.write_html/json/image(<span class="hljs-string">'&lt;path&gt;'</span>)                 <span class="hljs-comment"># Use &lt;Fig&gt;.show() to display the plot.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Fig&gt; = px.area/bar/box(&lt;DF&gt;, x=col_key, y=col_keys)  <span class="hljs-comment"># Also `color=col_key`. All are optional.</span>
 &lt;Fig&gt; = px.scatter(&lt;DF&gt;, x=col_key, y=col_keys)       <span class="hljs-comment"># Also `color/size/symbol=col_key`. Same.</span>
 &lt;Fig&gt; = px.scatter_3d(&lt;DF&gt;, x=col_key, y=col_key, …)  <span class="hljs-comment"># `z=col_key`. Also color, size, symbol.</span>
-&lt;Fig&gt; = px.histogram(&lt;DF&gt;, x=col_keys, y=col_key)     <span class="hljs-comment"># Also `nbins=&lt;int&gt;`. All are optional.</span>
+&lt;Fig&gt; = px.histogram(&lt;DF&gt;, x=col_keys, y=col_key)     <span class="hljs-comment"># Also color, nbins. All are optional.</span>
 </code></pre>
 <div><h4 id="displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">Displays a line chart of total coronavirus 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>,
@@ -2807,7 +2807,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 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 &gt; <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>).show()
+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>
 
 
@@ -2940,7 +2940,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 30, 2025</aside>
+    <aside>May 31, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 36f823c8d50272a9a932e1d542cefc54abf3ff65 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 2 Jun 2025 09:08:12 +0200
Subject: [PATCH 150/186] String, Cython

---
 README.md  | 27 +++++++++++++++------------
 index.html | 29 ++++++++++++++---------------
 parse.js   | 17 +++++++++++------
 3 files changed, 40 insertions(+), 33 deletions(-)

diff --git a/README.md b/README.md
index b385b3f9f..59939a185 100644
--- a/README.md
+++ b/README.md
@@ -327,11 +327,11 @@ String
 <bool> = <sub_str> in <str>                  # Checks if string contains the substring.
 <bool> = <str>.startswith(<sub_str>)         # Pass tuple of strings for multiple options.
 <int>  = <str>.find(<sub_str>)               # Returns start index of the first match or -1.
-<int>  = <str>.index(<sub_str>)              # Same, but raises ValueError if there's no match.
 ```
 
 ```python
-<str>  = <str>.lower()                       # Changes the case. Also upper/capitalize/title().
+<str>  = <str>.lower()                       # Lowers the case. Also upper/capitalize/title().
+<str>  = <str>.casefold()                    # Same, but converts ẞ/ß to ss, Σ/ς to σ, etc.
 <str>  = <str>.replace(old, new [, count])   # Replaces 'old' with 'new' at most 'count' times.
 <str>  = <str>.translate(<table>)            # Use `str.maketrans(<dict>)` to generate table.
 ```
@@ -2788,7 +2788,7 @@ from PIL import Image
 ### Modes
 * **`'L'` - Lightness (greyscale image). Each pixel is an integer between 0 and 255.**
 * **`'RGB'` - Red, green, blue (true color image). Each pixel is a tuple of three integers.**
-* **`'RGBA'` - RGB with alpha. Low alpha (i.e. forth int) makes pixel more transparent.**
+* **`'RGBA'` - RGB with alpha. Low alpha (i.e. fourth int) makes pixel more transparent.**
 * **`'HSV'` - Hue, saturation, value. Three ints representing color in HSV color space.**
 
 
@@ -3410,7 +3410,7 @@ import plotly.express as px, pandas as pd
 
 ```python
 <Fig> = px.line(<DF> [, y=col_key/s [, x=col_key]])   # Also px.line(y=<list> [, x=<list>]).
-<Fig>.update_layout(paper_bgcolor='rgb(0, 0, 0)')     # Also `margin=dict(t=0, r=0, b=0, l=0)`.
+<Fig>.update_layout(paper_bgcolor='#rrggbb')          # Also `margin=dict(t=0, r=0, b=0, l=0)`.
 <Fig>.write_html/json/image('<path>')                 # Use <Fig>.show() to display the plot.
 ```
 
@@ -3518,21 +3518,24 @@ import <cython_script>                 # Script must be saved with '.pyx' extens
 <cython_script>.main()                 # Main() isn't automatically executed.
 ```
 
-#### Definitions:
-* **All `'cdef'` definitions are optional, but they contribute to the speed-up.**
-* **Also supports C pointers (via `'*'` and `'&'`), structs, unions and enums.**
+#### All `'cdef'` definitions are optional, but they contribute to the speed-up:
 
 ```python
-cdef <ctype/type> <var_name> [= <obj>]
+cdef <ctype/type> [*]<var_name> [= <obj>]
 cdef <ctype>[n_elements] <var_name> [= <coll_of_nums>]
-cdef <ctype/type/void> <func_name>(<ctype/type> <arg_name>): ...
+cdef <ctype/type/void> <func_name>(<ctype/type> [*]<arg_name>): ...
 ```
 
 ```python
 cdef class <class_name>:
-    cdef public <ctype/type> <attr_name>
-    def __init__(self, <ctype/type> <arg_name>):
-        self.<attr_name> = <arg_name>
+    cdef public <ctype/type> [*]<attr_name>
+    def __init__(self, <ctype/type> [*]<arg_name>):
+        self.<attr_name> = [&]<arg_name>
+```
+
+```python
+cdef struct <struct_name>:
+    <ctype> [*]<field_name>
 ```
 
 ### Virtual Environments
diff --git a/index.html b/index.html
index eec6ff0e2..3947ffffb 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>May 31, 2025</aside>
+    <aside>June 2, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -317,9 +317,9 @@
 <pre><code class="python language-python hljs">&lt;bool&gt; = &lt;sub_str&gt; <span class="hljs-keyword">in</span> &lt;str&gt;                  <span class="hljs-comment"># Checks if string contains the substring.</span>
 &lt;bool&gt; = &lt;str&gt;.startswith(&lt;sub_str&gt;)         <span class="hljs-comment"># Pass tuple of strings for multiple options.</span>
 &lt;int&gt;  = &lt;str&gt;.find(&lt;sub_str&gt;)               <span class="hljs-comment"># Returns start index of the first match or -1.</span>
-&lt;int&gt;  = &lt;str&gt;.index(&lt;sub_str&gt;)              <span class="hljs-comment"># Same, but raises ValueError if there's no match.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;str&gt;  = &lt;str&gt;.lower()                       <span class="hljs-comment"># Changes the case. Also upper/capitalize/title().</span>
+<pre><code class="python language-python hljs">&lt;str&gt;  = &lt;str&gt;.lower()                       <span class="hljs-comment"># Lowers the case. Also upper/capitalize/title().</span>
+&lt;str&gt;  = &lt;str&gt;.casefold()                    <span class="hljs-comment"># Same, but converts ẞ/ß to ss, Σ/ς to σ, etc.</span>
 &lt;str&gt;  = &lt;str&gt;.replace(old, new [, count])   <span class="hljs-comment"># Replaces 'old' with 'new' at most 'count' times.</span>
 &lt;str&gt;  = &lt;str&gt;.translate(&lt;table&gt;)            <span class="hljs-comment"># Use `str.maketrans(&lt;dict&gt;)` to generate table.</span>
 </code></pre>
@@ -2288,7 +2288,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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 an integer 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. forth int) makes pixel more transparent.</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">WIDTH, HEIGHT = <span class="hljs-number">100</span>, <span class="hljs-number">100</span>
 n_pixels = WIDTH * HEIGHT
@@ -2789,7 +2789,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 <pre><code class="python language-python hljs">&lt;Fig&gt; = px.line(&lt;DF&gt; [, y=col_key/s [, x=col_key]])   <span class="hljs-comment"># Also px.line(y=&lt;list&gt; [, x=&lt;list&gt;]).</span>
-&lt;Fig&gt;.update_layout(paper_bgcolor=<span class="hljs-string">'rgb(0, 0, 0)'</span>)     <span class="hljs-comment"># Also `margin=dict(t=0, r=0, b=0, l=0)`.</span>
+&lt;Fig&gt;.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>
 &lt;Fig&gt;.write_html/json/image(<span class="hljs-string">'&lt;path&gt;'</span>)                 <span class="hljs-comment"># Use &lt;Fig&gt;.show() to display the plot.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Fig&gt; = px.area/bar/box(&lt;DF&gt;, x=col_key, y=col_keys)  <span class="hljs-comment"># Also `color=col_key`. All are optional.</span>
@@ -2881,19 +2881,18 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<div><h4 id="definitions">Definitions:</h4><ul>
-<li><strong>All <code class="python hljs"><span class="hljs-string">'cdef'</span></code> definitions are optional, but they contribute to the speed-up.</strong></li>
-<li><strong>Also supports C pointers (via <code class="python hljs"><span class="hljs-string">'*'</span></code> and <code class="python hljs"><span class="hljs-string">'&amp;'</span></code>), structs, unions and enums.</strong></li>
-</ul><pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; &lt;var_name&gt; [= &lt;obj&gt;]
+<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> &lt;ctype/type&gt; [*]&lt;var_name&gt; [= &lt;obj&gt;]
 <span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;coll_of_nums&gt;]
-<span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; &lt;arg_name&gt;): ...
+<span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; [*]&lt;arg_name&gt;): ...
 </code></pre></div>
 
-
 <pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>
-    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype/type&gt; &lt;attr_name&gt;
-    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; &lt;arg_name&gt;)</span>:</span>
-        self.&lt;attr_name&gt; = &lt;arg_name&gt;
+    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype/type&gt; [*]&lt;attr_name&gt;
+    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; [*]&lt;arg_name&gt;)</span>:</span>
+        self.&lt;attr_name&gt; = [&amp;]&lt;arg_name&gt;
+</code></pre>
+<pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <span class="hljs-keyword">struct</span> &lt;<span class="hljs-title">struct_name</span>&gt;:
+    &lt;ctype&gt; [*]&lt;field_name&gt;
 </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 current directory.</span>
 $ source NAME/bin/activate  <span class="hljs-comment"># Activates it. On Windows run `NAME\Scripts\activate`.</span>
@@ -2940,7 +2939,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>May 31, 2025</aside>
+    <aside>June 2, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index a54d578a8..41bfb6b29 100755
--- a/parse.js
+++ b/parse.js
@@ -327,15 +327,19 @@ const GROUPBY =
 
 
 const CYTHON_1 =
-  '<span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; &lt;var_name&gt; [= &lt;obj&gt;]\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; [*]&lt;var_name&gt; [= &lt;obj&gt;]\n' +
   '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;coll_of_nums&gt;]\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; &lt;arg_name&gt;): ...\n';
+  '<span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; [*]&lt;arg_name&gt;): ...\n';
 
 const CYTHON_2 =
   '<span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>\n' +
-  '    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype/type&gt; &lt;attr_name&gt;\n' +
-  '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; &lt;arg_name&gt;)</span>:</span>\n' +
-  '        self.&lt;attr_name&gt; = &lt;arg_name&gt;\n';
+  '    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype/type&gt; [*]&lt;attr_name&gt;\n' +
+  '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; [*]&lt;arg_name&gt;)</span>:</span>\n' +
+  '        self.&lt;attr_name&gt; = [&amp;]&lt;arg_name&gt;\n';
+
+const CYTHON_3 =
+  '<span class="hljs-keyword">cdef</span> <span class="hljs-keyword">struct</span> &lt;<span class="hljs-title">struct_name</span>&gt;:\n' +
+  '    &lt;ctype&gt; [*]&lt;field_name&gt;\n';
 
 const INDEX =
   '<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>\n' +
@@ -938,8 +942,9 @@ function fixHighlights() {
   $(`code:contains(samples_f = (sin(i *)`).html(AUDIO_2);
   $(`code:contains(collections, dataclasses, enum, io, itertools)`).html(MARIO);
   $(`code:contains(>>> gb = df.groupby)`).html(GROUPBY);
-  $(`code:contains(cdef <ctype/type> <var_name> [= <obj>])`).html(CYTHON_1);
+  $(`code:contains(cdef <ctype/type> [*]<var_name> [= <obj>])`).html(CYTHON_1);
   $(`code:contains(cdef class <class_name>:)`).html(CYTHON_2);
+  $(`code:contains(cdef struct <struct_name>:)`).html(CYTHON_3);
   $(`ul:contains(Ctrl+F / ⌘F is usually sufficient.)`).html(INDEX);
 }
 

From fed9b8f90b3ffe19c6f6163f596e65c91cf5dc58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 2 Jun 2025 11:05:45 +0200
Subject: [PATCH 151/186] String

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 59939a185..b64c5b5b6 100644
--- a/README.md
+++ b/README.md
@@ -318,7 +318,7 @@ String
 
 ```python
 <list> = <str>.split()                       # Splits on one or more whitespace characters.
-<list> = <str>.split(sep=None, maxsplit=-1)  # Splits on 'sep' str at most 'maxsplit' times.
+<list> = <str>.split(sep=None, maxsplit=-1)  # Splits on 'sep' string at most 'maxsplit' times.
 <list> = <str>.splitlines(keepends=False)    # On [\n\r\f\v\x1c-\x1e\x85\u2028\u2029] and \r\n.
 <str>  = <str>.join(<coll_of_strings>)       # Joins elements by using string as a separator.
 ```
diff --git a/index.html b/index.html
index 3947ffffb..79d802ab6 100644
--- a/index.html
+++ b/index.html
@@ -310,7 +310,7 @@
 
 
 <pre><code class="python language-python hljs">&lt;list&gt; = &lt;str&gt;.split()                       <span class="hljs-comment"># Splits on one or more whitespace characters.</span>
-&lt;list&gt; = &lt;str&gt;.split(sep=<span class="hljs-keyword">None</span>, maxsplit=<span class="hljs-number">-1</span>)  <span class="hljs-comment"># Splits on 'sep' str at most 'maxsplit' times.</span>
+&lt;list&gt; = &lt;str&gt;.split(sep=<span class="hljs-keyword">None</span>, maxsplit=<span class="hljs-number">-1</span>)  <span class="hljs-comment"># Splits on 'sep' string at most 'maxsplit' times.</span>
 &lt;list&gt; = &lt;str&gt;.splitlines(keepends=<span class="hljs-keyword">False</span>)    <span class="hljs-comment"># On [\n\r\f\v\x1c-\x1e\x85\u2028\u2029] and \r\n.</span>
 &lt;str&gt;  = &lt;str&gt;.join(&lt;coll_of_strings&gt;)       <span class="hljs-comment"># Joins elements by using string as a separator.</span>
 </code></pre>

From 78175bb93cf501bfdf63a54a5fc6b34440d60f82 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 4 Jun 2025 10:11:57 +0200
Subject: [PATCH 152/186] Cython

---
 README.md  | 4 ++--
 index.html | 8 ++++----
 parse.js   | 4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index b64c5b5b6..f40a7cafd 100644
--- a/README.md
+++ b/README.md
@@ -3515,14 +3515,14 @@ Appendix
 # $ pip3 install cython
 import pyximport; pyximport.install()  # Module that runs imported Cython scripts.
 import <cython_script>                 # Script must be saved with '.pyx' extension.
-<cython_script>.main()                 # Main() isn't automatically executed.
 ```
 
 #### All `'cdef'` definitions are optional, but they contribute to the speed-up:
 
 ```python
 cdef <ctype/type> [*]<var_name> [= <obj>]
-cdef <ctype>[n_elements] <var_name> [= <coll_of_nums>]
+cdef <ctype>[n_items] <array_name> [= <coll_of_nums/structs>]
+cdef <ctype> *<array_name> = <<ctype> *> malloc(n_items * sizeof(<ctype>))
 cdef <ctype/type/void> <func_name>(<ctype/type> [*]<arg_name>): ...
 ```
 
diff --git a/index.html b/index.html
index 79d802ab6..d2d9abb26 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>June 2, 2025</aside>
+    <aside>June 4, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2876,13 +2876,13 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <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 imported Cython scripts.</span>
 <span class="hljs-keyword">import</span> &lt;cython_script&gt;                 <span class="hljs-comment"># Script must be saved with '.pyx' extension.</span>
-&lt;cython_script&gt;.main()                 <span class="hljs-comment"># Main() isn't automatically executed.</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> &lt;ctype/type&gt; [*]&lt;var_name&gt; [= &lt;obj&gt;]
-<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;coll_of_nums&gt;]
+<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_items] &lt;array_name&gt; [= &lt;coll_of_nums/structs&gt;]
+<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; = &lt;&lt;ctype&gt; *&gt; malloc(n_items * sizeof(&lt;ctype&gt;))
 <span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; [*]&lt;arg_name&gt;): ...
 </code></pre></div>
 
@@ -2939,7 +2939,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>June 2, 2025</aside>
+    <aside>June 4, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 41bfb6b29..57a4e427c 100755
--- a/parse.js
+++ b/parse.js
@@ -325,10 +325,10 @@ const GROUPBY =
   '<span class="hljs-number">3</span>   <span class="hljs-number">1</span>   <span class="hljs-number">2</span>\n' +
   '<span class="hljs-number">6</span>  <span class="hljs-number">11</span>  <span class="hljs-number">13</span>';
 
-
 const CYTHON_1 =
   '<span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; [*]&lt;var_name&gt; [= &lt;obj&gt;]\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_elements] &lt;var_name&gt; [= &lt;coll_of_nums&gt;]\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_items] &lt;array_name&gt; [= &lt;coll_of_nums/structs&gt;]\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; = &lt;&lt;ctype&gt; *&gt; malloc(n_items * sizeof(&lt;ctype&gt;))\n' +
   '<span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; [*]&lt;arg_name&gt;): ...\n';
 
 const CYTHON_2 =

From 896eec8ddce8979c57ae54d6ec8e2a54009ceef8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 5 Jun 2025 10:27:52 +0200
Subject: [PATCH 153/186] Cython

---
 README.md  | 4 ++--
 index.html | 8 ++++----
 parse.js   | 6 +++---
 3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/README.md b/README.md
index f40a7cafd..84eaf524d 100644
--- a/README.md
+++ b/README.md
@@ -3520,7 +3520,7 @@ import <cython_script>                 # Script must be saved with '.pyx' extens
 #### All `'cdef'` definitions are optional, but they contribute to the speed-up:
 
 ```python
-cdef <ctype/type> [*]<var_name> [= <obj>]
+cdef <ctype/type> [*]<var_name> [= <object>]
 cdef <ctype>[n_items] <array_name> [= <coll_of_nums/structs>]
 cdef <ctype> *<array_name> = <<ctype> *> malloc(n_items * sizeof(<ctype>))
 cdef <ctype/type/void> <func_name>(<ctype/type> [*]<arg_name>): ...
@@ -3530,7 +3530,7 @@ cdef <ctype/type/void> <func_name>(<ctype/type> [*]<arg_name>): ...
 cdef class <class_name>:
     cdef public <ctype/type> [*]<attr_name>
     def __init__(self, <ctype/type> [*]<arg_name>):
-        self.<attr_name> = [&]<arg_name>
+        self.<attr_name> = <arg_name>
 ```
 
 ```python
diff --git a/index.html b/index.html
index d2d9abb26..f5cf53e52 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>June 4, 2025</aside>
+    <aside>June 5, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2880,7 +2880,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<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> &lt;ctype/type&gt; [*]&lt;var_name&gt; [= &lt;obj&gt;]
+<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> &lt;ctype/type&gt; [*]&lt;var_name&gt; [= &lt;object&gt;]
 <span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_items] &lt;array_name&gt; [= &lt;coll_of_nums/structs&gt;]
 <span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; = &lt;&lt;ctype&gt; *&gt; malloc(n_items * sizeof(&lt;ctype&gt;))
 <span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; [*]&lt;arg_name&gt;): ...
@@ -2889,7 +2889,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>
     <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype/type&gt; [*]&lt;attr_name&gt;
     <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; [*]&lt;arg_name&gt;)</span>:</span>
-        self.&lt;attr_name&gt; = [&amp;]&lt;arg_name&gt;
+        self.&lt;attr_name&gt; = &lt;arg_name&gt;
 </code></pre>
 <pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <span class="hljs-keyword">struct</span> &lt;<span class="hljs-title">struct_name</span>&gt;:
     &lt;ctype&gt; [*]&lt;field_name&gt;
@@ -2939,7 +2939,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>June 4, 2025</aside>
+    <aside>June 5, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 57a4e427c..6e5fb305e 100755
--- a/parse.js
+++ b/parse.js
@@ -326,7 +326,7 @@ const GROUPBY =
   '<span class="hljs-number">6</span>  <span class="hljs-number">11</span>  <span class="hljs-number">13</span>';
 
 const CYTHON_1 =
-  '<span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; [*]&lt;var_name&gt; [= &lt;obj&gt;]\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; [*]&lt;var_name&gt; [= &lt;object&gt;]\n' +
   '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_items] &lt;array_name&gt; [= &lt;coll_of_nums/structs&gt;]\n' +
   '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; = &lt;&lt;ctype&gt; *&gt; malloc(n_items * sizeof(&lt;ctype&gt;))\n' +
   '<span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; [*]&lt;arg_name&gt;): ...\n';
@@ -335,7 +335,7 @@ const CYTHON_2 =
   '<span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>\n' +
   '    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype/type&gt; [*]&lt;attr_name&gt;\n' +
   '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; [*]&lt;arg_name&gt;)</span>:</span>\n' +
-  '        self.&lt;attr_name&gt; = [&amp;]&lt;arg_name&gt;\n';
+  '        self.&lt;attr_name&gt; = &lt;arg_name&gt;\n';
 
 const CYTHON_3 =
   '<span class="hljs-keyword">cdef</span> <span class="hljs-keyword">struct</span> &lt;<span class="hljs-title">struct_name</span>&gt;:\n' +
@@ -942,7 +942,7 @@ function fixHighlights() {
   $(`code:contains(samples_f = (sin(i *)`).html(AUDIO_2);
   $(`code:contains(collections, dataclasses, enum, io, itertools)`).html(MARIO);
   $(`code:contains(>>> gb = df.groupby)`).html(GROUPBY);
-  $(`code:contains(cdef <ctype/type> [*]<var_name> [= <obj>])`).html(CYTHON_1);
+  $(`code:contains(cdef <ctype/type> [*]<var_name> [= <object>])`).html(CYTHON_1);
   $(`code:contains(cdef class <class_name>:)`).html(CYTHON_2);
   $(`code:contains(cdef struct <struct_name>:)`).html(CYTHON_3);
   $(`ul:contains(Ctrl+F / ⌘F is usually sufficient.)`).html(INDEX);

From ee85425cc79172cdc19519c0fd52f56d97ae2fe4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 11 Jun 2025 00:46:34 +0200
Subject: [PATCH 154/186] Big changes in Cython

---
 README.md  | 26 ++++++++++++--------------
 index.html | 29 ++++++++++++++---------------
 parse.js   | 25 ++++++++++++-------------
 3 files changed, 38 insertions(+), 42 deletions(-)

diff --git a/README.md b/README.md
index 84eaf524d..45697179f 100644
--- a/README.md
+++ b/README.md
@@ -379,7 +379,7 @@ import re
 ```python
 <str>   = <Match>.group()                         # Returns the whole match. Also group(0).
 <str>   = <Match>.group(1)                        # Returns part inside the first brackets.
-<tuple> = <Match>.groups()                        # Returns all bracketed parts.
+<tuple> = <Match>.groups()                        # Returns all bracketed parts as strings.
 <int>   = <Match>.start()                         # Returns start index of the match.
 <int>   = <Match>.end()                           # Returns exclusive end index of the match.
 ```
@@ -3513,29 +3513,27 @@ Appendix
 
 ```python
 # $ pip3 install cython
-import pyximport; pyximport.install()  # Module that runs imported Cython scripts.
-import <cython_script>                 # Script must be saved with '.pyx' extension.
+import pyximport; pyximport.install()               # Module that runs Cython scripts.
+import <cython_script>                              # Script must have '.pyx' extension.
 ```
 
 #### All `'cdef'` definitions are optional, but they contribute to the speed-up:
-
 ```python
-cdef <ctype/type> [*]<var_name> [= <object>]
-cdef <ctype>[n_items] <array_name> [= <coll_of_nums/structs>]
-cdef <ctype> *<array_name> = <<ctype> *> malloc(n_items * sizeof(<ctype>))
-cdef <ctype/type/void> <func_name>(<ctype/type> [*]<arg_name>): ...
+cdef <type> <var_name> [= <obj/var>]                # Either Python or C type variable.
+cdef <ctype> *<pointer_name> [= &<var>]             # Use <pointer>[0] to get the value.
+cdef <ctype>[size] <array_name> [= <coll/array>]    # Also `from cpython cimport array`.
+cdef <ctype> *<array_name> [= <coll/array>]         # Also `<<ctype> *> malloc(n_bytes)`.
 ```
 
 ```python
-cdef class <class_name>:
-    cdef public <ctype/type> [*]<attr_name>
-    def __init__(self, <ctype/type> [*]<arg_name>):
-        self.<attr_name> = <arg_name>
+cdef <type> <func_name>(<type> [*]<arg_name>): ...  # Omitted types default to `object`.
 ```
 
 ```python
-cdef struct <struct_name>:
-    <ctype> [*]<field_name>
+cdef class <class_name>:                            # Also `cdef struct <struct_name>:`.
+    cdef public <type> [*]<attr_name>               # Also `... <ctype> [*]<field_name>`.
+    def __init__(self, <type> <arg_name>):          # Also `cdef __dealloc__(self):`.
+        self.<attr_name> = <arg_name>               # Also `... free(<pointer/array>)`.
 ```
 
 ### Virtual Environments
diff --git a/index.html b/index.html
index f5cf53e52..a785cb1a2 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>June 5, 2025</aside>
+    <aside>June 11, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -358,7 +358,7 @@
 </ul>
 <div><h3 id="matchobject">Match Object</h3><pre><code class="python language-python hljs">&lt;str&gt;   = &lt;Match&gt;.group()                         <span class="hljs-comment"># Returns the whole match. Also group(0).</span>
 &lt;str&gt;   = &lt;Match&gt;.group(<span class="hljs-number">1</span>)                        <span class="hljs-comment"># Returns part inside the first brackets.</span>
-&lt;tuple&gt; = &lt;Match&gt;.groups()                        <span class="hljs-comment"># Returns all bracketed parts.</span>
+&lt;tuple&gt; = &lt;Match&gt;.groups()                        <span class="hljs-comment"># Returns all bracketed parts as strings.</span>
 &lt;int&gt;   = &lt;Match&gt;.start()                         <span class="hljs-comment"># Returns start index of the match.</span>
 &lt;int&gt;   = &lt;Match&gt;.end()                           <span class="hljs-comment"># Returns exclusive end index of the match.</span>
 </code></pre></div>
@@ -2874,25 +2874,24 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 <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 imported Cython scripts.</span>
-<span class="hljs-keyword">import</span> &lt;cython_script&gt;                 <span class="hljs-comment"># Script must be saved with '.pyx' extension.</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> &lt;cython_script&gt;                              <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> &lt;ctype/type&gt; [*]&lt;var_name&gt; [= &lt;object&gt;]
-<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_items] &lt;array_name&gt; [= &lt;coll_of_nums/structs&gt;]
-<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; = &lt;&lt;ctype&gt; *&gt; malloc(n_items * sizeof(&lt;ctype&gt;))
-<span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; [*]&lt;arg_name&gt;): ...
+<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> &lt;type&gt; &lt;var_name&gt; [= &lt;obj/var&gt;]                <span class="hljs-comment"># Either Python or C type variable.</span>
+<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;pointer_name&gt; [= &amp;&lt;var&gt;]             <span class="hljs-comment"># Use &lt;pointer&gt;[0] to get the value.</span>
+<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[size] &lt;array_name&gt; [= &lt;coll/array&gt;]    <span class="hljs-comment"># Also `from cpython cimport array`.</span>
+<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; [= &lt;coll/array&gt;]         <span class="hljs-comment"># Also `&lt;&lt;ctype&gt; *&gt; malloc(n_bytes)`.</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>
-    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype/type&gt; [*]&lt;attr_name&gt;
-    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; [*]&lt;arg_name&gt;)</span>:</span>
-        self.&lt;attr_name&gt; = &lt;arg_name&gt;
+<pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> &lt;type&gt; &lt;func_name&gt;(&lt;type&gt; [*]&lt;arg_name&gt;): ...  <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-keyword">struct</span> &lt;<span class="hljs-title">struct_name</span>&gt;:
-    &lt;ctype&gt; [*]&lt;field_name&gt;
+<pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>                            <span class="hljs-comment"># Also `cdef struct &lt;struct_name&gt;:`.</span>
+    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;type&gt; [*]&lt;attr_name&gt;               <span class="hljs-comment"># Also `... &lt;ctype&gt; [*]&lt;field_name&gt;`.</span>
+    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;type&gt; &lt;arg_name&gt;)</span>:</span>          <span class="hljs-comment"># Also `cdef __dealloc__(self):`.</span>
+        self.&lt;attr_name&gt; = &lt;arg_name&gt;               <span class="hljs-comment"># Also `... free(&lt;pointer/array&gt;)`.</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 current directory.</span>
 $ source NAME/bin/activate  <span class="hljs-comment"># Activates it. On Windows run `NAME\Scripts\activate`.</span>
@@ -2939,7 +2938,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>June 5, 2025</aside>
+    <aside>June 11, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 6e5fb305e..3f27730d0 100755
--- a/parse.js
+++ b/parse.js
@@ -326,20 +326,19 @@ const GROUPBY =
   '<span class="hljs-number">6</span>  <span class="hljs-number">11</span>  <span class="hljs-number">13</span>';
 
 const CYTHON_1 =
-  '<span class="hljs-keyword">cdef</span> &lt;ctype/type&gt; [*]&lt;var_name&gt; [= &lt;object&gt;]\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[n_items] &lt;array_name&gt; [= &lt;coll_of_nums/structs&gt;]\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; = &lt;&lt;ctype&gt; *&gt; malloc(n_items * sizeof(&lt;ctype&gt;))\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype/type/void&gt; &lt;func_name&gt;(&lt;ctype/type&gt; [*]&lt;arg_name&gt;): ...\n';
+  '<span class="hljs-keyword">cdef</span> &lt;type&gt; &lt;var_name&gt; [= &lt;obj/var&gt;]                <span class="hljs-comment"># Either Python or C type variable.</span>\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;pointer_name&gt; [= &amp;&lt;var&gt;]             <span class="hljs-comment"># Use &lt;pointer&gt;[0] to get the value.</span>\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[size] &lt;array_name&gt; [= &lt;coll/array&gt;]    <span class="hljs-comment"># Also `from cpython cimport array`.</span>\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; [= &lt;coll/array&gt;]         <span class="hljs-comment"># Also `&lt;&lt;ctype&gt; *&gt; malloc(n_bytes)`.</span>\n';
 
 const CYTHON_2 =
-  '<span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>\n' +
-  '    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;ctype/type&gt; [*]&lt;attr_name&gt;\n' +
-  '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;ctype/type&gt; [*]&lt;arg_name&gt;)</span>:</span>\n' +
-  '        self.&lt;attr_name&gt; = &lt;arg_name&gt;\n';
+  '<span class="hljs-keyword">cdef</span> &lt;type&gt; &lt;func_name&gt;(&lt;type&gt; [*]&lt;arg_name&gt;): ...  <span class="hljs-comment"># Omitted types default to `object`.</span>\n';
 
 const CYTHON_3 =
-  '<span class="hljs-keyword">cdef</span> <span class="hljs-keyword">struct</span> &lt;<span class="hljs-title">struct_name</span>&gt;:\n' +
-  '    &lt;ctype&gt; [*]&lt;field_name&gt;\n';
+  '<span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>                            <span class="hljs-comment"># Also `cdef struct &lt;struct_name&gt;:`.</span>\n' +
+  '    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;type&gt; [*]&lt;attr_name&gt;               <span class="hljs-comment"># Also `... &lt;ctype&gt; [*]&lt;field_name&gt;`.</span>\n' +
+  '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;type&gt; &lt;arg_name&gt;)</span>:</span>          <span class="hljs-comment"># Also `cdef __dealloc__(self):`.</span>\n' +
+  '        self.&lt;attr_name&gt; = &lt;arg_name&gt;               <span class="hljs-comment"># Also `... free(&lt;pointer/array&gt;)`.</span>\n';
 
 const INDEX =
   '<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>\n' +
@@ -942,9 +941,9 @@ function fixHighlights() {
   $(`code:contains(samples_f = (sin(i *)`).html(AUDIO_2);
   $(`code:contains(collections, dataclasses, enum, io, itertools)`).html(MARIO);
   $(`code:contains(>>> gb = df.groupby)`).html(GROUPBY);
-  $(`code:contains(cdef <ctype/type> [*]<var_name> [= <object>])`).html(CYTHON_1);
-  $(`code:contains(cdef class <class_name>:)`).html(CYTHON_2);
-  $(`code:contains(cdef struct <struct_name>:)`).html(CYTHON_3);
+  $(`code:contains(cdef <type> <var_name> [= <obj/var>])`).html(CYTHON_1);
+  $(`code:contains(cdef <type> <func_name>(<type> [*]<arg_name>): ...)`).html(CYTHON_2);
+  $(`code:contains(cdef class <class_name>:)`).html(CYTHON_3);
   $(`ul:contains(Ctrl+F / ⌘F is usually sufficient.)`).html(INDEX);
 }
 

From 79fca7028dcbf6e3dc63cd00e3601791b2944fd3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 18 Jun 2025 14:05:38 +0200
Subject: [PATCH 155/186] Big changes in Numbers, Inline, Closure

---
 README.md  | 78 +++++++++++++++++++++++++--------------------------
 index.html | 82 +++++++++++++++++++++++++++---------------------------
 parse.js   |  9 +++---
 3 files changed, 84 insertions(+), 85 deletions(-)

diff --git a/README.md b/README.md
index 45697179f..8ad7ed538 100644
--- a/README.md
+++ b/README.md
@@ -493,11 +493,11 @@ Format
 Numbers
 -------
 ```python
-<int>      = int(<float/str/bool>)           # Or: math.trunc(<float>)
-<float>    = float(<int/str/bool>)           # Or: <int/float>e±<int>
-<complex>  = complex(real=0, imag=0)         # Or: <int/float> ± <int/float>j
-<Fraction> = fractions.Fraction(0, 1)        # Or: Fraction(numerator=0, denominator=1)
-<Decimal>  = decimal.Decimal(<str/int>)      # Or: Decimal((sign, digits, exponent))
+<int>      = int(<float/str/bool>)             # Whole number of any size. Truncates floats.
+<float>    = float(<int/str/bool>)             # 64-bit decimal number. Also <float>e±<int>.
+<complex>  = complex(real=0, imag=0)           # Complex number. Also `<float> ± <float>j`.
+<Fraction> = fractions.Fraction(<int>, <int>)  # E.g. `Fraction(1, 2) / 3 == Fraction(1, 6)`.
+<Decimal>  = decimal.Decimal(<str/int/tuple>)  # E.g. `Decimal((1, (2, 3), 4)) == -230_000`.
 ```
 * **`'int(<str>)'` and `'float(<str>)'` raise ValueError on malformed strings.**
 * **Decimal numbers are stored exactly, unlike most floats where `'1.1 + 2.2 != 3.3'`.**
@@ -507,54 +507,55 @@ Numbers
 
 ### Built-in Functions
 ```python
-<num> = pow(<num>, <num>)                    # Or: <number> ** <number>
-<num> = abs(<num>)                           # <float> = abs(<complex>)
-<num> = round(<num> [, ±ndigits])            # Also math.floor/ceil(<number>).
-<num> = min(<collection>)                    # Also max(<num>, <num> [, ...]).
-<num> = sum(<collection>)                    # Also math.prod(<collection>).
+<num> = pow(<num>, <num>)                      # E.g. `pow(2, 3) == 2 ** 3 == 8`.
+<num> = abs(<num>)                             # E.g. `abs(complex(3, 4)) == 5`.
+<num> = round(<num> [, ±ndigits])              # E.g. `round(123, -1) == 120`.
+<num> = min(<collection>)                      # Also max(<num>, <num> [, ...]).
+<num> = sum(<collection>)                      # Also math.prod(<collection>).
 ```
 
 ### Math
 ```python
-from math import pi, inf, nan, isnan         # `inf*0` and `nan+1` return nan.
-from math import sqrt, factorial             # `sqrt(-1)` raises ValueError.
-from math import sin, cos, tan               # Also: asin, degrees, radians.
-from math import log, log10, log2            # Log accepts base as second arg.
+from math import floor, ceil, trunc            # They convert floats into integers.
+from math import pi, inf, nan, isnan           # `inf * 0` and `nan + 1` return nan.
+from math import sqrt, factorial               # `sqrt(-1)` will raise ValueError.
+from math import sin, cos, tan                 # Also: asin, acos, degrees, radians.
+from math import log, log10, log2              # Log accepts base as second argument.
 ```
 
 ### Statistics
 ```python
-from statistics import mean, median, mode    # Also: variance, stdev, quantiles.
+from statistics import mean, median, mode      # Mode returns the most common item.
+from statistics import variance, stdev         # Also: pvariance, pstdev, quantiles.
 ```
 
 ### Random
 ```python
-from random import random, randint, uniform  # Also: gauss, choice, shuffle, seed.
+from random import random, randint, uniform    # Also: gauss, choice, shuffle, seed.
 ```
 
 ```python
-<float> = random()                           # Returns a float inside [0, 1).
-<num>   = randint/uniform(a, b)              # Returns an int/float inside [a, b].
-<float> = gauss(mean, stdev)                 # Also triangular(low, high, mode).
-<el>    = choice(<sequence>)                 # Keeps it intact. Also sample(pop, k).
-shuffle(<list>)                              # Shuffles the list in place.
+<float> = random()                             # Returns a float inside [0, 1).
+<num>   = randint/uniform(a, b)                # Returns an int/float inside [a, b].
+<float> = gauss(mean, stdev)                   # Also triangular(low, high, mode).
+<el>    = choice(<sequence>)                   # Keeps it intact. Also sample(p, n).
+shuffle(<list>)                                # Works on any mutable sequence.
 ```
 
 ### Hexadecimal Numbers
 ```python
-<int> = ±0x<hex>                             # Or: ±0b<bin>
-<int> = int('±<hex>', 16)                    # Or: int('±<bin>', 2)
-<int> = int('±0x<hex>', 0)                   # Or: int('±0b<bin>', 0)
-<str> = hex(<int>)                           # Returns '[-]0x<hex>'. Also bin().
+<int> = 0x<hex>                                # E.g. `0xFF == 255`. Also 0b<bin>.
+<int> = int('±<hex>', 16)                      # Also int('±0x<hex>/±0b<bin>', 0).
+<str> = hex(<int>)                             # Returns '[-]0x<hex>'. Also bin().
 ```
 
 ### Bitwise Operators
 ```python
-<int> = <int> & <int>                        # And (0b1100 & 0b1010 == 0b1000).
-<int> = <int> | <int>                        # Or  (0b1100 | 0b1010 == 0b1110).
-<int> = <int> ^ <int>                        # Xor (0b1100 ^ 0b1010 == 0b0110).
-<int> = <int> << n_bits                      # Left shift. Use >> for right.
-<int> = ~<int>                               # Not. Also -<int> - 1.
+<int> = <int> & <int>                          # E.g. `0b1100 & 0b1010 == 0b1000`.
+<int> = <int> | <int>                          # E.g. `0b1100 | 0b1010 == 0b1110`.
+<int> = <int> ^ <int>                          # E.g. `0b1100 ^ 0b1010 == 0b0110`.
+<int> = <int> << n_bits                        # Left shift. Use >> for right.
+<int> = ~<int>                                 # Not. Same as `-<int> - 1`.
 ```
 
 
@@ -747,10 +748,10 @@ Inline
 
 ### Comprehensions
 ```python
-<list> = [i+1 for i in range(10)]                   # Or: [1, 2, ..., 10]
-<iter> = (i for i in range(10) if i > 5)            # Or: iter([6, 7, 8, 9])
-<set>  = {i+5 for i in range(10)}                   # Or: {5, 6, ..., 14}
-<dict> = {i: i*2 for i in range(10)}                # Or: {0: 0, 1: 2, ..., 9: 18}
+<list> = [i+1 for i in range(10)]                   # Returns `[1, 2, ..., 10]`.
+<iter> = (i for i in range(10) if i > 5)            # Returns `iter([6, 7, 8, 9])`.
+<set>  = {i+5 for i in range(10)}                   # Returns `{5, 6, ..., 14}`.
+<dict> = {i: i*2 for i in range(10)}                # Returns `{0: 0, 1: 2, ..., 9: 18}`.
 ```
 
 ```python
@@ -764,9 +765,9 @@ from functools import reduce
 ```
 
 ```python
-<iter> = map(lambda x: x + 1, range(10))            # Or: iter([1, 2, ..., 10])
-<iter> = filter(lambda x: x > 5, range(10))         # Or: iter([6, 7, 8, 9])
-<obj>  = reduce(lambda out, x: out + x, range(10))  # Or: 45
+<iter> = map(lambda x: x + 1, range(10))            # Returns `iter([1, 2, ..., 10])`.
+<iter> = filter(lambda x: x > 5, range(10))         # Returns `iter([6, 7, 8, 9])`.
+<obj>  = reduce(lambda out, x: out + x, range(10))  # Returns `45`.
 ```
 
 ### Any, All
@@ -860,8 +861,7 @@ from functools import partial
 >>> multiply_by_3(10)
 30
 ```
-* **Partial is also useful in cases when a function needs to be passed as an argument because it enables us to set its arguments beforehand.**
-* **A few examples being: `'defaultdict(<func>)'`, `'iter(<func>, to_exc)'` and dataclass's `'field(default_factory=<func>)'`.**
+* **Partial is also useful in cases when a function needs to be passed as an argument because it enables us to set its arguments beforehand (`'collections.defaultdict(<func>)'`, `'iter(<func>, to_exc)'` and `'dataclasses.field(default_factory=<func>)'`).**
 
 ### Non-Local
 **If variable is being assigned to anywhere in the scope, it is regarded as a local variable, unless it is declared as a 'global' or a 'nonlocal'.**
diff --git a/index.html b/index.html
index a785cb1a2..5695cd8a4 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>June 11, 2025</aside>
+    <aside>June 18, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -453,11 +453,11 @@
 {<span class="hljs-number">90</span>:X}                                   <span class="hljs-comment"># '5A'. Hexadecimal with upper-case letters.</span>
 </code></pre></div>
 
-<div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs">&lt;int&gt;      = int(&lt;float/str/bool&gt;)           <span class="hljs-comment"># Or: math.trunc(&lt;float&gt;)</span>
-&lt;float&gt;    = float(&lt;int/str/bool&gt;)           <span class="hljs-comment"># Or: &lt;int/float&gt;e±&lt;int&gt;</span>
-&lt;complex&gt;  = complex(real=<span class="hljs-number">0</span>, imag=<span class="hljs-number">0</span>)         <span class="hljs-comment"># Or: &lt;int/float&gt; ± &lt;int/float&gt;j</span>
-&lt;Fraction&gt; = fractions.Fraction(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>)        <span class="hljs-comment"># Or: Fraction(numerator=0, denominator=1)</span>
-&lt;Decimal&gt;  = decimal.Decimal(&lt;str/int&gt;)      <span class="hljs-comment"># Or: Decimal((sign, digits, exponent))</span>
+<div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs">&lt;int&gt;      = int(&lt;float/str/bool&gt;)             <span class="hljs-comment"># Whole number of any size. Truncates floats.</span>
+&lt;float&gt;    = float(&lt;int/str/bool&gt;)             <span class="hljs-comment"># 64-bit decimal number. Also &lt;float&gt;e±&lt;int&gt;.</span>
+&lt;complex&gt;  = complex(real=<span class="hljs-number">0</span>, imag=<span class="hljs-number">0</span>)           <span class="hljs-comment"># Complex number. Also `&lt;float&gt; ± &lt;float&gt;j`.</span>
+&lt;Fraction&gt; = fractions.Fraction(&lt;int&gt;, &lt;int&gt;)  <span class="hljs-comment"># E.g. `Fraction(1, 2) / 3 == Fraction(1, 6)`.</span>
+&lt;Decimal&gt;  = decimal.Decimal(&lt;str/int/tuple&gt;)  <span class="hljs-comment"># E.g. `Decimal((1, (2, 3), 4)) == -230_000`.</span>
 </code></pre></div>
 
 <ul>
@@ -467,42 +467,43 @@
 <li><strong>Precision of decimal operations is set with: <code class="python hljs"><span class="hljs-string">'decimal.getcontext().prec = &lt;int&gt;'</span></code>.</strong></li>
 <li><strong>Bools can be used anywhere ints can, because 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="builtinfunctions">Built-in Functions</h3><pre><code class="python language-python hljs">&lt;num&gt; = pow(&lt;num&gt;, &lt;num&gt;)                    <span class="hljs-comment"># Or: &lt;number&gt; ** &lt;number&gt;</span>
-&lt;num&gt; = abs(&lt;num&gt;)                           <span class="hljs-comment"># &lt;float&gt; = abs(&lt;complex&gt;)</span>
-&lt;num&gt; = round(&lt;num&gt; [, ±ndigits])            <span class="hljs-comment"># Also math.floor/ceil(&lt;number&gt;).</span>
-&lt;num&gt; = min(&lt;collection&gt;)                    <span class="hljs-comment"># Also max(&lt;num&gt;, &lt;num&gt; [, ...]).</span>
-&lt;num&gt; = sum(&lt;collection&gt;)                    <span class="hljs-comment"># Also math.prod(&lt;collection&gt;).</span>
+<div><h3 id="builtinfunctions">Built-in Functions</h3><pre><code class="python language-python hljs">&lt;num&gt; = pow(&lt;num&gt;, &lt;num&gt;)                      <span class="hljs-comment"># E.g. `pow(2, 3) == 2 ** 3 == 8`.</span>
+&lt;num&gt; = abs(&lt;num&gt;)                             <span class="hljs-comment"># E.g. `abs(complex(3, 4)) == 5`.</span>
+&lt;num&gt; = round(&lt;num&gt; [, ±ndigits])              <span class="hljs-comment"># E.g. `round(123, -1) == 120`.</span>
+&lt;num&gt; = min(&lt;collection&gt;)                      <span class="hljs-comment"># Also max(&lt;num&gt;, &lt;num&gt; [, ...]).</span>
+&lt;num&gt; = sum(&lt;collection&gt;)                      <span class="hljs-comment"># Also math.prod(&lt;collection&gt;).</span>
 </code></pre></div>
 
-<div><h3 id="math">Math</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> pi, inf, nan, isnan         <span class="hljs-comment"># `inf*0` and `nan+1` return nan.</span>
-<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> sqrt, factorial             <span class="hljs-comment"># `sqrt(-1)` raises ValueError.</span>
-<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> sin, cos, tan               <span class="hljs-comment"># Also: asin, degrees, radians.</span>
-<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> log, log10, log2            <span class="hljs-comment"># Log accepts base as second arg.</span>
+<div><h3 id="math">Math</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> floor, ceil, trunc            <span class="hljs-comment"># They convert floats into integers.</span>
+<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> pi, inf, nan, isnan           <span class="hljs-comment"># `inf * 0` and `nan + 1` return nan.</span>
+<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> sqrt, factorial               <span class="hljs-comment"># `sqrt(-1)` will raise ValueError.</span>
+<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> sin, cos, tan                 <span class="hljs-comment"># Also: asin, acos, degrees, radians.</span>
+<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> log, log10, log2              <span class="hljs-comment"># Log accepts base as second argument.</span>
 </code></pre></div>
 
-<div><h3 id="statistics">Statistics</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> statistics <span class="hljs-keyword">import</span> mean, median, mode    <span class="hljs-comment"># Also: variance, stdev, quantiles.</span>
+<div><h3 id="statistics">Statistics</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> statistics <span class="hljs-keyword">import</span> mean, median, mode      <span class="hljs-comment"># Mode returns the most common item.</span>
+<span class="hljs-keyword">from</span> statistics <span class="hljs-keyword">import</span> variance, stdev         <span class="hljs-comment"># Also: pvariance, pstdev, quantiles.</span>
 </code></pre></div>
 
-<div><h3 id="random">Random</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> random, randint, uniform  <span class="hljs-comment"># Also: gauss, choice, shuffle, seed.</span>
+<div><h3 id="random">Random</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> random, randint, uniform    <span class="hljs-comment"># Also: gauss, choice, shuffle, seed.</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs">&lt;float&gt; = random()                           <span class="hljs-comment"># Returns a float inside [0, 1).</span>
-&lt;num&gt;   = randint/uniform(a, b)              <span class="hljs-comment"># Returns an int/float inside [a, b].</span>
-&lt;float&gt; = gauss(mean, stdev)                 <span class="hljs-comment"># Also triangular(low, high, mode).</span>
-&lt;el&gt;    = choice(&lt;sequence&gt;)                 <span class="hljs-comment"># Keeps it intact. Also sample(pop, k).</span>
-shuffle(&lt;list&gt;)                              <span class="hljs-comment"># Shuffles the list in place.</span>
+<pre><code class="python language-python hljs">&lt;float&gt; = random()                             <span class="hljs-comment"># Returns a float inside [0, 1).</span>
+&lt;num&gt;   = randint/uniform(a, b)                <span class="hljs-comment"># Returns an int/float inside [a, b].</span>
+&lt;float&gt; = gauss(mean, stdev)                   <span class="hljs-comment"># Also triangular(low, high, mode).</span>
+&lt;el&gt;    = choice(&lt;sequence&gt;)                   <span class="hljs-comment"># Keeps it intact. Also sample(p, n).</span>
+shuffle(&lt;list&gt;)                                <span class="hljs-comment"># Works on any mutable sequence.</span>
 </code></pre>
-<div><h3 id="hexadecimalnumbers">Hexadecimal Numbers</h3><pre><code class="python language-python hljs">&lt;int&gt; = ±<span class="hljs-number">0x</span>&lt;hex&gt;                             <span class="hljs-comment"># Or: ±0b&lt;bin&gt;</span>
-&lt;int&gt; = int(<span class="hljs-string">'±&lt;hex&gt;'</span>, <span class="hljs-number">16</span>)                    <span class="hljs-comment"># Or: int('±&lt;bin&gt;', 2)</span>
-&lt;int&gt; = int(<span class="hljs-string">'±0x&lt;hex&gt;'</span>, <span class="hljs-number">0</span>)                   <span class="hljs-comment"># Or: int('±0b&lt;bin&gt;', 0)</span>
-&lt;str&gt; = hex(&lt;int&gt;)                           <span class="hljs-comment"># Returns '[-]0x&lt;hex&gt;'. Also bin().</span>
+<div><h3 id="hexadecimalnumbers">Hexadecimal Numbers</h3><pre><code class="python language-python hljs">&lt;int&gt; = <span class="hljs-number">0x</span>&lt;hex&gt;                                <span class="hljs-comment"># E.g. `0xFF == 255`. Also 0b&lt;bin&gt;.</span>
+&lt;int&gt; = int(<span class="hljs-string">'±&lt;hex&gt;'</span>, <span class="hljs-number">16</span>)                      <span class="hljs-comment"># Also int('±0x&lt;hex&gt;/±0b&lt;bin&gt;', 0).</span>
+&lt;str&gt; = hex(&lt;int&gt;)                             <span class="hljs-comment"># Returns '[-]0x&lt;hex&gt;'. Also bin().</span>
 </code></pre></div>
 
-<div><h3 id="bitwiseoperators">Bitwise Operators</h3><pre><code class="python language-python hljs">&lt;int&gt; = &lt;int&gt; &amp; &lt;int&gt;                        <span class="hljs-comment"># And (0b1100 &amp; 0b1010 == 0b1000).</span>
-&lt;int&gt; = &lt;int&gt; | &lt;int&gt;                        <span class="hljs-comment"># Or  (0b1100 | 0b1010 == 0b1110).</span>
-&lt;int&gt; = &lt;int&gt; ^ &lt;int&gt;                        <span class="hljs-comment"># Xor (0b1100 ^ 0b1010 == 0b0110).</span>
-&lt;int&gt; = &lt;int&gt; &lt;&lt; n_bits                      <span class="hljs-comment"># Left shift. Use &gt;&gt; for right.</span>
-&lt;int&gt; = ~&lt;int&gt;                               <span class="hljs-comment"># Not. Also -&lt;int&gt; - 1.</span>
+<div><h3 id="bitwiseoperators">Bitwise Operators</h3><pre><code class="python language-python hljs">&lt;int&gt; = &lt;int&gt; &amp; &lt;int&gt;                          <span class="hljs-comment"># E.g. `0b1100 &amp; 0b1010 == 0b1000`.</span>
+&lt;int&gt; = &lt;int&gt; | &lt;int&gt;                          <span class="hljs-comment"># E.g. `0b1100 | 0b1010 == 0b1110`.</span>
+&lt;int&gt; = &lt;int&gt; ^ &lt;int&gt;                          <span class="hljs-comment"># E.g. `0b1100 ^ 0b1010 == 0b0110`.</span>
+&lt;int&gt; = &lt;int&gt; &lt;&lt; n_bits                        <span class="hljs-comment"># Left shift. Use &gt;&gt; for right.</span>
+&lt;int&gt; = ~&lt;int&gt;                                 <span class="hljs-comment"># Not. Same as `-&lt;int&gt; - 1`.</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
@@ -649,10 +650,10 @@
 </code></pre></div></div>
 
 
-<div><h3 id="comprehensions">Comprehensions</h3><pre><code class="python language-python hljs">&lt;list&gt; = [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">10</span>)]                   <span class="hljs-comment"># Or: [1, 2, ..., 10]</span>
-&lt;iter&gt; = (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 &gt; <span class="hljs-number">5</span>)            <span class="hljs-comment"># Or: iter([6, 7, 8, 9])</span>
-&lt;set&gt;  = {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">10</span>)}                   <span class="hljs-comment"># Or: {5, 6, ..., 14}</span>
-&lt;dict&gt; = {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">10</span>)}                <span class="hljs-comment"># Or: {0: 0, 1: 2, ..., 9: 18}</span>
+<div><h3 id="comprehensions">Comprehensions</h3><pre><code class="python language-python hljs">&lt;list&gt; = [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">10</span>)]                   <span class="hljs-comment"># Returns `[1, 2, ..., 10]`.</span>
+&lt;iter&gt; = (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 &gt; <span class="hljs-number">5</span>)            <span class="hljs-comment"># Returns `iter([6, 7, 8, 9])`.</span>
+&lt;set&gt;  = {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">10</span>)}                   <span class="hljs-comment"># Returns `{5, 6, ..., 14}`.</span>
+&lt;dict&gt; = {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">10</span>)}                <span class="hljs-comment"># Returns `{0: 0, 1: 2, ..., 9: 18}`.</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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">'abc'</span>]             <span class="hljs-comment"># Inner loop is on the right side.</span>
@@ -661,9 +662,9 @@
 <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">&lt;iter&gt; = map(<span class="hljs-keyword">lambda</span> x: x + <span class="hljs-number">1</span>, range(<span class="hljs-number">10</span>))            <span class="hljs-comment"># Or: iter([1, 2, ..., 10])</span>
-&lt;iter&gt; = filter(<span class="hljs-keyword">lambda</span> x: x &gt; <span class="hljs-number">5</span>, range(<span class="hljs-number">10</span>))         <span class="hljs-comment"># Or: iter([6, 7, 8, 9])</span>
-&lt;obj&gt;  = reduce(<span class="hljs-keyword">lambda</span> out, x: out + x, range(<span class="hljs-number">10</span>))  <span class="hljs-comment"># Or: 45</span>
+<pre><code class="python language-python hljs">&lt;iter&gt; = map(<span class="hljs-keyword">lambda</span> x: x + <span class="hljs-number">1</span>, range(<span class="hljs-number">10</span>))            <span class="hljs-comment"># Returns `iter([1, 2, ..., 10])`.</span>
+&lt;iter&gt; = filter(<span class="hljs-keyword">lambda</span> x: x &gt; <span class="hljs-number">5</span>, range(<span class="hljs-number">10</span>))         <span class="hljs-comment"># Returns `iter([6, 7, 8, 9])`.</span>
+&lt;obj&gt;  = reduce(<span class="hljs-keyword">lambda</span> out, x: out + x, range(<span class="hljs-number">10</span>))  <span class="hljs-comment"># Returns `45`.</span>
 </code></pre>
 <div><h3 id="anyall">Any, All</h3><pre><code class="python language-python hljs">&lt;bool&gt; = any(&lt;collection&gt;)                          <span class="hljs-comment"># Is `bool(&lt;el&gt;)` True for any el?</span>
 &lt;bool&gt; = all(&lt;collection&gt;)                          <span class="hljs-comment"># True for all? Also True if empty.</span>
@@ -734,8 +735,7 @@
 <span class="hljs-number">30</span>
 </code></pre>
 <ul>
-<li><strong>Partial is also useful in cases when a function needs to be passed as an argument because it enables us to set its arguments beforehand.</strong></li>
-<li><strong>A few examples being: <code class="python hljs"><span class="hljs-string">'defaultdict(&lt;func&gt;)'</span></code>, <code class="python hljs"><span class="hljs-string">'iter(&lt;func&gt;, to_exc)'</span></code> and dataclass's <code class="python hljs"><span class="hljs-string">'field(default_factory=&lt;func&gt;)'</span></code>.</strong></li>
+<li><strong>Partial is also useful in cases when a function needs to be passed as an argument because it enables us to set its arguments beforehand (<code class="python hljs"><span class="hljs-string">'collections.defaultdict(&lt;func&gt;)'</span></code>, <code class="python hljs"><span class="hljs-string">'iter(&lt;func&gt;, to_exc)'</span></code> and <code class="python hljs"><span class="hljs-string">'dataclasses.field(default_factory=&lt;func&gt;)'</span></code>).</strong></li>
 </ul>
 <div><h3 id="nonlocal">Non-Local</h3><p><strong>If variable is being assigned to anywhere in the scope, it is regarded as a local variable, unless it is declared as a 'global' or a 'nonlocal'.</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>
@@ -2938,7 +2938,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>June 11, 2025</aside>
+    <aside>June 18, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 3f27730d0..a9fc9e69a 100755
--- a/parse.js
+++ b/parse.js
@@ -43,10 +43,9 @@ const TOC =
   '</code></pre>\n';
 
 const BIN_HEX =
-  '&lt;int&gt; = ±<span class="hljs-number">0x</span>&lt;hex&gt;                             <span class="hljs-comment"># Or: ±0b&lt;bin&gt;</span>\n' +
-  '&lt;int&gt; = int(<span class="hljs-string">\'±&lt;hex&gt;\'</span>, <span class="hljs-number">16</span>)                    <span class="hljs-comment"># Or: int(\'±&lt;bin&gt;\', 2)</span>\n' +
-  '&lt;int&gt; = int(<span class="hljs-string">\'±0x&lt;hex&gt;\'</span>, <span class="hljs-number">0</span>)                   <span class="hljs-comment"># Or: int(\'±0b&lt;bin&gt;\', 0)</span>\n' +
-  '&lt;str&gt; = hex(&lt;int&gt;)                           <span class="hljs-comment"># Returns \'[-]0x&lt;hex&gt;\'. Also bin().</span>\n';
+  '&lt;int&gt; = <span class="hljs-number">0x</span>&lt;hex&gt;                                <span class="hljs-comment"># E.g. `0xFF == 255`. Also 0b&lt;bin&gt;.</span>\n' +
+  '&lt;int&gt; = int(<span class="hljs-string">\'±&lt;hex&gt;\'</span>, <span class="hljs-number">16</span>)                      <span class="hljs-comment"># Also int(\'±0x&lt;hex&gt;/±0b&lt;bin&gt;\', 0).</span>\n' +
+  '&lt;str&gt; = hex(&lt;int&gt;)                             <span class="hljs-comment"># Returns \'[-]0x&lt;hex&gt;\'. Also bin().</span>\n';
 
 const CACHE =
   '<span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> cache\n' +
@@ -923,7 +922,7 @@ function fixClasses() {
 }
 
 function fixHighlights() {
-  $(`code:contains(<int> = ±0x<hex>)`).html(BIN_HEX);
+  $(`code:contains(<int> = 0x<hex>)`).html(BIN_HEX);
   $(`code:contains( + fib(n)`).html(CACHE);
   $(`code:contains(>>> def add)`).html(SPLAT);
   $(`code:contains(@debug(print_result=True))`).html(PARAMETRIZED_DECORATOR);

From fea82d569976ebe55737f91976db90fe9810687e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 18 Jun 2025 14:18:41 +0200
Subject: [PATCH 156/186] Numbers

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 8ad7ed538..5b2e624ec 100644
--- a/README.md
+++ b/README.md
@@ -500,7 +500,7 @@ Numbers
 <Decimal>  = decimal.Decimal(<str/int/tuple>)  # E.g. `Decimal((1, (2, 3), 4)) == -230_000`.
 ```
 * **`'int(<str>)'` and `'float(<str>)'` raise ValueError on malformed strings.**
-* **Decimal numbers are stored exactly, unlike most floats where `'1.1 + 2.2 != 3.3'`.**
+* **Decimal objects store numbers exactly, unlike most floats where `'1.1 + 2.2 != 3.3'`.**
 * **Floats can be compared with: `'math.isclose(<float>, <float>)'`.**
 * **Precision of decimal operations is set with: `'decimal.getcontext().prec = <int>'`.**
 * **Bools can be used anywhere ints can, because bool is a subclass of int: `'True + 1 == 2'`.**
diff --git a/index.html b/index.html
index 5695cd8a4..eddbef2f7 100644
--- a/index.html
+++ b/index.html
@@ -462,7 +462,7 @@
 
 <ul>
 <li><strong><code class="python hljs"><span class="hljs-string">'int(&lt;str&gt;)'</span></code> and <code class="python hljs"><span class="hljs-string">'float(&lt;str&gt;)'</span></code> raise ValueError on malformed strings.</strong></li>
-<li><strong>Decimal numbers are stored 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>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(&lt;float&gt;, &lt;float&gt;)'</span></code>.</strong></li>
 <li><strong>Precision of decimal operations is set with: <code class="python hljs"><span class="hljs-string">'decimal.getcontext().prec = &lt;int&gt;'</span></code>.</strong></li>
 <li><strong>Bools can be used anywhere ints can, because bool is a subclass of int: <code class="python hljs"><span class="hljs-string">'True + 1 == 2'</span></code>.</strong></li>

From bdc43f29c5bb170accef34ce4bb82a0b66e98999 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 18 Jun 2025 17:08:35 +0200
Subject: [PATCH 157/186] Pandas

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index 5b2e624ec..4ed872432 100644
--- a/README.md
+++ b/README.md
@@ -3184,10 +3184,10 @@ Name: a, dtype: int64
 <S>.plot.line/area/bar/pie/hist()              # Generates a plot. Accepts `title=<str>`.
 plt.show()                                     # Displays the plot. Also plt.savefig(<path>).
 ```
-* **Use `'print(<S>.to_string())'` to print a Series that has more than 60 items.**
+* **Use `'print(<S>.to_string())'` to print a Series that has more than sixty items.**
 * **Use `'<S>.index'` to get collection of keys and `'<S>.index = <coll>'` to update them.**
 * **Only pass a list or Series to loc/iloc because `'obj[x, y]'` is converted to `'obj[(x, y)]'` and `'<S>.loc[key_1, key_2]'` is how you retrieve a value from a multi-indexed Series.**
-* **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
+* **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if np.nan is assigned to any item. Use `'<S>.astype(<str/type>)'` to get converted Series.**
 
 #### Series — Aggregate, Transform, Map:
 ```python
diff --git a/index.html b/index.html
index eddbef2f7..74d8b2acd 100644
--- a/index.html
+++ b/index.html
@@ -2612,10 +2612,10 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 plt.show()                                     <span class="hljs-comment"># Displays the plot. Also plt.savefig(&lt;path&gt;).</span>
 </code></pre>
 <ul>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'print(&lt;S&gt;.to_string())'</span></code> to print a Series that has more than 60 items.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'print(&lt;S&gt;.to_string())'</span></code> to print a Series that has more than sixty items.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.index'</span></code> to get collection of keys and <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.index = &lt;coll&gt;'</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">'&lt;S&gt;.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 we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'&lt;S&gt;.astype(&lt;str/type&gt;)'</span></code> to get converted 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">'&lt;S&gt;.astype(&lt;str/type&gt;)'</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">&lt;el&gt; = &lt;S&gt;.sum/max/mean/std/idxmax/count()     <span class="hljs-comment"># Or: &lt;S&gt;.agg(lambda &lt;S&gt;: &lt;el&gt;)</span>
 &lt;S&gt;  = &lt;S&gt;.rank/diff/cumsum/ffill/interpol…()  <span class="hljs-comment"># Or: &lt;S&gt;.agg/transform(lambda &lt;S&gt;: &lt;S&gt;)</span>

From 2e33d654c9a0443f400fc077d9efac0f026a6814 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 19 Jun 2025 23:09:53 +0200
Subject: [PATCH 158/186] Cython

---
 README.md  | 22 +++++++++++-----------
 index.html | 26 +++++++++++++-------------
 parse.js   | 18 +++++++++---------
 3 files changed, 33 insertions(+), 33 deletions(-)

diff --git a/README.md b/README.md
index 4ed872432..5881daf54 100644
--- a/README.md
+++ b/README.md
@@ -3513,27 +3513,27 @@ Appendix
 
 ```python
 # $ pip3 install cython
-import pyximport; pyximport.install()               # Module that runs Cython scripts.
-import <cython_script>                              # Script must have '.pyx' extension.
+import pyximport; pyximport.install()                # Module that runs Cython scripts.
+import <cython_script>                               # Script must have '.pyx' extension.
 ```
 
 #### All `'cdef'` definitions are optional, but they contribute to the speed-up:
 ```python
-cdef <type> <var_name> [= <obj/var>]                # Either Python or C type variable.
-cdef <ctype> *<pointer_name> [= &<var>]             # Use <pointer>[0] to get the value.
-cdef <ctype>[size] <array_name> [= <coll/array>]    # Also `from cpython cimport array`.
-cdef <ctype> *<array_name> [= <coll/array>]         # Also `<<ctype> *> malloc(n_bytes)`.
+cdef <type> <var_name> [= <obj/var>]                 # Either Python or C type variable.
+cdef <ctype> *<pointer_name> [= &<var>]              # Use <pointer>[0] to get the value.
+cdef <ctype>[size] <array_name> [= <coll/array>]     # Also `<ctype>[:] <mview> = <array>`.
+cdef <ctype> *<array_name> [= <coll/array/pointer>]  # E.g. `<<ctype> *> malloc(n_bytes)`.
 ```
 
 ```python
-cdef <type> <func_name>(<type> [*]<arg_name>): ...  # Omitted types default to `object`.
+cdef <type> <func_name>(<type> [*]<arg_name>): ...   # Omitted types default to `object`.
 ```
 
 ```python
-cdef class <class_name>:                            # Also `cdef struct <struct_name>:`.
-    cdef public <type> [*]<attr_name>               # Also `... <ctype> [*]<field_name>`.
-    def __init__(self, <type> <arg_name>):          # Also `cdef __dealloc__(self):`.
-        self.<attr_name> = <arg_name>               # Also `... free(<pointer/array>)`.
+cdef class <class_name>:                             # Also `cdef struct <struct_name>:`.
+    cdef public <type> [*]<attr_name>                # Also `... <ctype> [*]<field_name>`.
+    def __init__(self, <type> <arg_name>):           # Also `cdef __dealloc__(self):`.
+        self.<attr_name> = <arg_name>                # Also `... free(<pointer/array>)`.
 ```
 
 ### Virtual Environments
diff --git a/index.html b/index.html
index 74d8b2acd..93cf2d0bc 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>June 18, 2025</aside>
+    <aside>June 19, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2874,24 +2874,24 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 <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> &lt;cython_script&gt;                              <span class="hljs-comment"># Script must have '.pyx' extension.</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> &lt;cython_script&gt;                               <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> &lt;type&gt; &lt;var_name&gt; [= &lt;obj/var&gt;]                <span class="hljs-comment"># Either Python or C type variable.</span>
-<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;pointer_name&gt; [= &amp;&lt;var&gt;]             <span class="hljs-comment"># Use &lt;pointer&gt;[0] to get the value.</span>
-<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[size] &lt;array_name&gt; [= &lt;coll/array&gt;]    <span class="hljs-comment"># Also `from cpython cimport array`.</span>
-<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; [= &lt;coll/array&gt;]         <span class="hljs-comment"># Also `&lt;&lt;ctype&gt; *&gt; malloc(n_bytes)`.</span>
+<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> &lt;type&gt; &lt;var_name&gt; [= &lt;obj/var&gt;]                 <span class="hljs-comment"># Either Python or C type variable.</span>
+<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;pointer_name&gt; [= &amp;&lt;var&gt;]              <span class="hljs-comment"># Use &lt;pointer&gt;[0] to get the value.</span>
+<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[size] &lt;array_name&gt; [= &lt;coll/array&gt;]     <span class="hljs-comment"># Also `&lt;ctype&gt;[:] &lt;mview&gt; = &lt;array&gt;`.</span>
+<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; [= &lt;coll/array/pointer&gt;]  <span class="hljs-comment"># E.g. `&lt;&lt;ctype&gt; *&gt; malloc(n_bytes)`.</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> &lt;type&gt; &lt;func_name&gt;(&lt;type&gt; [*]&lt;arg_name&gt;): ...  <span class="hljs-comment"># Omitted types default to `object`.</span>
+<pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> &lt;type&gt; &lt;func_name&gt;(&lt;type&gt; [*]&lt;arg_name&gt;): ...   <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> &lt;<span class="hljs-title">class_name</span>&gt;:</span>                            <span class="hljs-comment"># Also `cdef struct &lt;struct_name&gt;:`.</span>
-    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;type&gt; [*]&lt;attr_name&gt;               <span class="hljs-comment"># Also `... &lt;ctype&gt; [*]&lt;field_name&gt;`.</span>
-    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;type&gt; &lt;arg_name&gt;)</span>:</span>          <span class="hljs-comment"># Also `cdef __dealloc__(self):`.</span>
-        self.&lt;attr_name&gt; = &lt;arg_name&gt;               <span class="hljs-comment"># Also `... free(&lt;pointer/array&gt;)`.</span>
+<pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>                             <span class="hljs-comment"># Also `cdef struct &lt;struct_name&gt;:`.</span>
+    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;type&gt; [*]&lt;attr_name&gt;                <span class="hljs-comment"># Also `... &lt;ctype&gt; [*]&lt;field_name&gt;`.</span>
+    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;type&gt; &lt;arg_name&gt;)</span>:</span>           <span class="hljs-comment"># Also `cdef __dealloc__(self):`.</span>
+        self.&lt;attr_name&gt; = &lt;arg_name&gt;                <span class="hljs-comment"># Also `... free(&lt;pointer/array&gt;)`.</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 current directory.</span>
 $ source NAME/bin/activate  <span class="hljs-comment"># Activates it. On Windows run `NAME\Scripts\activate`.</span>
@@ -2938,7 +2938,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>June 18, 2025</aside>
+    <aside>June 19, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index a9fc9e69a..0e5261706 100755
--- a/parse.js
+++ b/parse.js
@@ -325,19 +325,19 @@ const GROUPBY =
   '<span class="hljs-number">6</span>  <span class="hljs-number">11</span>  <span class="hljs-number">13</span>';
 
 const CYTHON_1 =
-  '<span class="hljs-keyword">cdef</span> &lt;type&gt; &lt;var_name&gt; [= &lt;obj/var&gt;]                <span class="hljs-comment"># Either Python or C type variable.</span>\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;pointer_name&gt; [= &amp;&lt;var&gt;]             <span class="hljs-comment"># Use &lt;pointer&gt;[0] to get the value.</span>\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[size] &lt;array_name&gt; [= &lt;coll/array&gt;]    <span class="hljs-comment"># Also `from cpython cimport array`.</span>\n' +
-  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; [= &lt;coll/array&gt;]         <span class="hljs-comment"># Also `&lt;&lt;ctype&gt; *&gt; malloc(n_bytes)`.</span>\n';
+  '<span class="hljs-keyword">cdef</span> &lt;type&gt; &lt;var_name&gt; [= &lt;obj/var&gt;]                 <span class="hljs-comment"># Either Python or C type variable.</span>\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;pointer_name&gt; [= &amp;&lt;var&gt;]              <span class="hljs-comment"># Use &lt;pointer&gt;[0] to get the value.</span>\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt;[size] &lt;array_name&gt; [= &lt;coll/array&gt;]     <span class="hljs-comment"># Also `&lt;ctype&gt;[:] &lt;mview&gt; = &lt;array&gt;`.</span>\n' +
+  '<span class="hljs-keyword">cdef</span> &lt;ctype&gt; *&lt;array_name&gt; [= &lt;coll/array/pointer&gt;]  <span class="hljs-comment"># E.g. `&lt;&lt;ctype&gt; *&gt; malloc(n_bytes)`.</span>\n';
 
 const CYTHON_2 =
-  '<span class="hljs-keyword">cdef</span> &lt;type&gt; &lt;func_name&gt;(&lt;type&gt; [*]&lt;arg_name&gt;): ...  <span class="hljs-comment"># Omitted types default to `object`.</span>\n';
+  '<span class="hljs-keyword">cdef</span> &lt;type&gt; &lt;func_name&gt;(&lt;type&gt; [*]&lt;arg_name&gt;): ...   <span class="hljs-comment"># Omitted types default to `object`.</span>\n';
 
 const CYTHON_3 =
-  '<span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>                            <span class="hljs-comment"># Also `cdef struct &lt;struct_name&gt;:`.</span>\n' +
-  '    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;type&gt; [*]&lt;attr_name&gt;               <span class="hljs-comment"># Also `... &lt;ctype&gt; [*]&lt;field_name&gt;`.</span>\n' +
-  '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;type&gt; &lt;arg_name&gt;)</span>:</span>          <span class="hljs-comment"># Also `cdef __dealloc__(self):`.</span>\n' +
-  '        self.&lt;attr_name&gt; = &lt;arg_name&gt;               <span class="hljs-comment"># Also `... free(&lt;pointer/array&gt;)`.</span>\n';
+  '<span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>                             <span class="hljs-comment"># Also `cdef struct &lt;struct_name&gt;:`.</span>\n' +
+  '    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;type&gt; [*]&lt;attr_name&gt;                <span class="hljs-comment"># Also `... &lt;ctype&gt; [*]&lt;field_name&gt;`.</span>\n' +
+  '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;type&gt; &lt;arg_name&gt;)</span>:</span>           <span class="hljs-comment"># Also `cdef __dealloc__(self):`.</span>\n' +
+  '        self.&lt;attr_name&gt; = &lt;arg_name&gt;                <span class="hljs-comment"># Also `... free(&lt;pointer/array&gt;)`.</span>\n';
 
 const INDEX =
   '<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>\n' +

From 8fe3bc8aec65e653ed5d2094200695fbeb5af7e8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 20 Jun 2025 10:35:00 +0200
Subject: [PATCH 159/186] Cython

---
 README.md  | 2 +-
 index.html | 6 +++---
 parse.js   | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 5881daf54..0547e696d 100644
--- a/README.md
+++ b/README.md
@@ -3533,7 +3533,7 @@ cdef <type> <func_name>(<type> [*]<arg_name>): ...   # Omitted types default to
 cdef class <class_name>:                             # Also `cdef struct <struct_name>:`.
     cdef public <type> [*]<attr_name>                # Also `... <ctype> [*]<field_name>`.
     def __init__(self, <type> <arg_name>):           # Also `cdef __dealloc__(self):`.
-        self.<attr_name> = <arg_name>                # Also `... free(<pointer/array>)`.
+        self.<attr_name> = <arg_name>                # Also `... free(<array/pointer>)`.
 ```
 
 ### Virtual Environments
diff --git a/index.html b/index.html
index 93cf2d0bc..981dccf05 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>June 19, 2025</aside>
+    <aside>June 20, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -2891,7 +2891,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <pre><code class="python language-python hljs"><span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>                             <span class="hljs-comment"># Also `cdef struct &lt;struct_name&gt;:`.</span>
     <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;type&gt; [*]&lt;attr_name&gt;                <span class="hljs-comment"># Also `... &lt;ctype&gt; [*]&lt;field_name&gt;`.</span>
     <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;type&gt; &lt;arg_name&gt;)</span>:</span>           <span class="hljs-comment"># Also `cdef __dealloc__(self):`.</span>
-        self.&lt;attr_name&gt; = &lt;arg_name&gt;                <span class="hljs-comment"># Also `... free(&lt;pointer/array&gt;)`.</span>
+        self.&lt;attr_name&gt; = &lt;arg_name&gt;                <span class="hljs-comment"># Also `... free(&lt;array/pointer&gt;)`.</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 current directory.</span>
 $ source NAME/bin/activate  <span class="hljs-comment"># Activates it. On Windows run `NAME\Scripts\activate`.</span>
@@ -2938,7 +2938,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>June 19, 2025</aside>
+    <aside>June 20, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 0e5261706..42cf8c6d7 100755
--- a/parse.js
+++ b/parse.js
@@ -337,7 +337,7 @@ const CYTHON_3 =
   '<span class="hljs-keyword">cdef</span> <span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">class_name</span>&gt;:</span>                             <span class="hljs-comment"># Also `cdef struct &lt;struct_name&gt;:`.</span>\n' +
   '    <span class="hljs-keyword">cdef</span> <span class="hljs-keyword">public</span> &lt;type&gt; [*]&lt;attr_name&gt;                <span class="hljs-comment"># Also `... &lt;ctype&gt; [*]&lt;field_name&gt;`.</span>\n' +
   '    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, &lt;type&gt; &lt;arg_name&gt;)</span>:</span>           <span class="hljs-comment"># Also `cdef __dealloc__(self):`.</span>\n' +
-  '        self.&lt;attr_name&gt; = &lt;arg_name&gt;                <span class="hljs-comment"># Also `... free(&lt;pointer/array&gt;)`.</span>\n';
+  '        self.&lt;attr_name&gt; = &lt;arg_name&gt;                <span class="hljs-comment"># Also `... free(&lt;array/pointer&gt;)`.</span>\n';
 
 const INDEX =
   '<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>\n' +

From 48ca55b40e98b216c89e0bb0ab35aba5ca7e45f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 21 Jun 2025 15:06:44 +0200
Subject: [PATCH 160/186] Tuple, Inline, Class, Path

---
 README.md  | 32 ++++++++++++++++----------------
 index.html | 36 ++++++++++++++++++------------------
 2 files changed, 34 insertions(+), 34 deletions(-)

diff --git a/README.md b/README.md
index 0547e696d..a0012ae21 100644
--- a/README.md
+++ b/README.md
@@ -168,8 +168,8 @@ Tuple
 >>> p = Point(1, y=2)
 >>> print(p)
 Point(x=1, y=2)
->>> p[0], p.x
-(1, 1)
+>>> p[0], p.y
+(1, 2)
 ```
 
 
@@ -748,10 +748,10 @@ Inline
 
 ### Comprehensions
 ```python
-<list> = [i+1 for i in range(10)]                   # Returns `[1, 2, ..., 10]`.
-<iter> = (i for i in range(10) if i > 5)            # Returns `iter([6, 7, 8, 9])`.
-<set>  = {i+5 for i in range(10)}                   # Returns `{5, 6, ..., 14}`.
-<dict> = {i: i*2 for i in range(10)}                # Returns `{0: 0, 1: 2, ..., 9: 18}`.
+<list> = [i+1 for i in range(10)]                   # Returns [1, 2, ..., 10].
+<iter> = (i for i in range(10) if i > 5)            # Returns iter([6, 7, 8, 9]).
+<set>  = {i+5 for i in range(10)}                   # Returns {5, 6, ..., 14}.
+<dict> = {i: i*2 for i in range(10)}                # Returns {0: 0, 1: 2, ..., 9: 18}.
 ```
 
 ```python
@@ -765,9 +765,9 @@ from functools import reduce
 ```
 
 ```python
-<iter> = map(lambda x: x + 1, range(10))            # Returns `iter([1, 2, ..., 10])`.
-<iter> = filter(lambda x: x > 5, range(10))         # Returns `iter([6, 7, 8, 9])`.
-<obj>  = reduce(lambda out, x: out + x, range(10))  # Returns `45`.
+<iter> = map(lambda x: x + 1, range(10))            # Returns iter([1, 2, ..., 10]).
+<iter> = filter(lambda x: x > 5, range(10))         # Returns iter([6, 7, 8, 9]).
+<obj>  = reduce(lambda out, x: out + x, range(10))  # Returns 45.
 ```
 
 ### Any, All
@@ -993,7 +993,7 @@ Z = make_dataclass('Z', ['a']); print/str/repr(Z(<obj>))
 ```
 
 ### Subclass
-* **Inheritance is a mechanism that enables a class to extend some other class (that is, subclass to extend its parent), and by doing so inherit all its methods and attributes.**
+* **Inheritance is a mechanism that enables a class to extend some other class (that is, subclass to extend its parent), and by doing so inherit all of its methods and attributes.**
 * **Subclass can then add its own methods and attributes or override inherited ones by reusing their names.**
 
 ```python
@@ -1027,7 +1027,7 @@ from collections import abc
 
 <name>: <type> [| ...] [= <obj>]
 <name>: list/set/abc.Iterable/abc.Sequence[<type>] [= <obj>]
-<name>: dict/tuple[<type>, ...] [= <obj>]
+<name>: tuple/dict[<type>, ...] [= <obj>]
 ```
 
 ### Dataclass
@@ -1644,13 +1644,13 @@ from pathlib import Path
 ```
 
 ```python
-<bool> = os.path.exists(<path>)     # Or: <Path>.exists()
-<bool> = os.path.isfile(<path>)     # Or: <DirEntry/Path>.is_file()
-<bool> = os.path.isdir(<path>)      # Or: <DirEntry/Path>.is_dir()
+<bool> = os.path.exists(<path>)     # Same as <Path>.exists().
+<bool> = os.path.isfile(<path>)     # Same as <DirEntry/Path>.is_file().
+<bool> = os.path.isdir(<path>)      # Same as <DirEntry/Path>.is_dir().
 ```
 
 ```python
-<stat> = os.stat(<path>)            # Or: <DirEntry/Path>.stat()
+<stat> = os.stat(<path>)            # Same as <DirEntry/Path>.stat().
 <num>  = <stat>.st_mtime/st_size/…  # Modification time, size in bytes, etc.
 ```
 
@@ -1820,7 +1820,7 @@ import csv
 * **File must be opened with a `'newline=""'` argument, or every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'!**
 * **To print the spreadsheet to the console use [Tabulate](#table) library.**
 * **For XML and binary Excel files (xlsx, xlsm and xlsb) use [Pandas](#dataframe-plot-encode-decode) library.**
-* **Reader accepts any collection of strings, not just files.**
+* **Reader accepts any iterator or collection of strings, not just files.**
 
 ### Write
 ```python
diff --git a/index.html b/index.html
index 981dccf05..f592a1f4b 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>June 20, 2025</aside>
+    <aside>June 21, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -209,8 +209,8 @@
 <span class="hljs-meta">&gt;&gt;&gt; </span>p = Point(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>)
 <span class="hljs-meta">&gt;&gt;&gt; </span>print(p)
 Point(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>)
-<span class="hljs-meta">&gt;&gt;&gt; </span>p[<span class="hljs-number">0</span>], p.x
-(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>)
+<span class="hljs-meta">&gt;&gt;&gt; </span>p[<span class="hljs-number">0</span>], p.y
+(<span class="hljs-number">1</span>, <span class="hljs-number">2</span>)
 </code></pre></div>
 
 
@@ -650,10 +650,10 @@
 </code></pre></div></div>
 
 
-<div><h3 id="comprehensions">Comprehensions</h3><pre><code class="python language-python hljs">&lt;list&gt; = [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">10</span>)]                   <span class="hljs-comment"># Returns `[1, 2, ..., 10]`.</span>
-&lt;iter&gt; = (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 &gt; <span class="hljs-number">5</span>)            <span class="hljs-comment"># Returns `iter([6, 7, 8, 9])`.</span>
-&lt;set&gt;  = {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">10</span>)}                   <span class="hljs-comment"># Returns `{5, 6, ..., 14}`.</span>
-&lt;dict&gt; = {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">10</span>)}                <span class="hljs-comment"># Returns `{0: 0, 1: 2, ..., 9: 18}`.</span>
+<div><h3 id="comprehensions">Comprehensions</h3><pre><code class="python language-python hljs">&lt;list&gt; = [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">10</span>)]                   <span class="hljs-comment"># Returns [1, 2, ..., 10].</span>
+&lt;iter&gt; = (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 &gt; <span class="hljs-number">5</span>)            <span class="hljs-comment"># Returns iter([6, 7, 8, 9]).</span>
+&lt;set&gt;  = {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">10</span>)}                   <span class="hljs-comment"># Returns {5, 6, ..., 14}.</span>
+&lt;dict&gt; = {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">10</span>)}                <span class="hljs-comment"># Returns {0: 0, 1: 2, ..., 9: 18}.</span>
 </code></pre></div>
 
 <pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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">'abc'</span>]             <span class="hljs-comment"># Inner loop is on the right side.</span>
@@ -662,9 +662,9 @@
 <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">&lt;iter&gt; = map(<span class="hljs-keyword">lambda</span> x: x + <span class="hljs-number">1</span>, range(<span class="hljs-number">10</span>))            <span class="hljs-comment"># Returns `iter([1, 2, ..., 10])`.</span>
-&lt;iter&gt; = filter(<span class="hljs-keyword">lambda</span> x: x &gt; <span class="hljs-number">5</span>, range(<span class="hljs-number">10</span>))         <span class="hljs-comment"># Returns `iter([6, 7, 8, 9])`.</span>
-&lt;obj&gt;  = reduce(<span class="hljs-keyword">lambda</span> out, x: out + x, range(<span class="hljs-number">10</span>))  <span class="hljs-comment"># Returns `45`.</span>
+<pre><code class="python language-python hljs">&lt;iter&gt; = map(<span class="hljs-keyword">lambda</span> x: x + <span class="hljs-number">1</span>, range(<span class="hljs-number">10</span>))            <span class="hljs-comment"># Returns iter([1, 2, ..., 10]).</span>
+&lt;iter&gt; = filter(<span class="hljs-keyword">lambda</span> x: x &gt; <span class="hljs-number">5</span>, range(<span class="hljs-number">10</span>))         <span class="hljs-comment"># Returns iter([6, 7, 8, 9]).</span>
+&lt;obj&gt;  = reduce(<span class="hljs-keyword">lambda</span> out, x: out + x, range(<span class="hljs-number">10</span>))  <span class="hljs-comment"># Returns 45.</span>
 </code></pre>
 <div><h3 id="anyall">Any, All</h3><pre><code class="python language-python hljs">&lt;bool&gt; = any(&lt;collection&gt;)                          <span class="hljs-comment"># Is `bool(&lt;el&gt;)` True for any el?</span>
 &lt;bool&gt; = all(&lt;collection&gt;)                          <span class="hljs-comment"># True for all? Also True if empty.</span>
@@ -847,7 +847,7 @@
 </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 (that is, subclass to extend its parent), and by doing so inherit all its methods and attributes.</strong></li>
+<li><strong>Inheritance is a mechanism that enables a class to extend some other class (that is, 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>
@@ -877,7 +877,7 @@
 
 &lt;name&gt;: &lt;type&gt; [| ...] [= &lt;obj&gt;]
 &lt;name&gt;: list/set/abc.Iterable/abc.Sequence[&lt;type&gt;] [= &lt;obj&gt;]
-&lt;name&gt;: dict/tuple[&lt;type&gt;, ...] [= &lt;obj&gt;]
+&lt;name&gt;: tuple/dict[&lt;type&gt;, ...] [= &lt;obj&gt;]
 </code></pre></div>
 
 
@@ -1404,11 +1404,11 @@
 <pre><code class="python language-python hljs">&lt;list&gt; = os.listdir(path=<span class="hljs-string">'.'</span>)       <span class="hljs-comment"># Returns filenames located at the path.</span>
 &lt;list&gt; = glob.glob(<span class="hljs-string">'&lt;pattern&gt;'</span>)     <span class="hljs-comment"># Returns paths matching the wildcard pattern.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;bool&gt; = os.path.exists(&lt;path&gt;)     <span class="hljs-comment"># Or: &lt;Path&gt;.exists()</span>
-&lt;bool&gt; = os.path.isfile(&lt;path&gt;)     <span class="hljs-comment"># Or: &lt;DirEntry/Path&gt;.is_file()</span>
-&lt;bool&gt; = os.path.isdir(&lt;path&gt;)      <span class="hljs-comment"># Or: &lt;DirEntry/Path&gt;.is_dir()</span>
+<pre><code class="python language-python hljs">&lt;bool&gt; = os.path.exists(&lt;path&gt;)     <span class="hljs-comment"># Same as &lt;Path&gt;.exists().</span>
+&lt;bool&gt; = os.path.isfile(&lt;path&gt;)     <span class="hljs-comment"># Same as &lt;DirEntry/Path&gt;.is_file().</span>
+&lt;bool&gt; = os.path.isdir(&lt;path&gt;)      <span class="hljs-comment"># Same as &lt;DirEntry/Path&gt;.is_dir().</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;stat&gt; = os.stat(&lt;path&gt;)            <span class="hljs-comment"># Or: &lt;DirEntry/Path&gt;.stat()</span>
+<pre><code class="python language-python hljs">&lt;stat&gt; = os.stat(&lt;path&gt;)            <span class="hljs-comment"># Same as &lt;DirEntry/Path&gt;.stat().</span>
 &lt;num&gt;  = &lt;stat&gt;.st_mtime/st_size/…  <span class="hljs-comment"># Modification time, size in bytes, etc.</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">&lt;iter&gt; = os.scandir(path=<span class="hljs-string">'.'</span>)       <span class="hljs-comment"># Returns DirEntry objects located at the path.</span>
@@ -1525,7 +1525,7 @@
 <li><strong>File must be opened with a <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, or every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'!</strong></li>
 <li><strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong></li>
 <li><strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#dataframeplotencodedecode">Pandas</a> library.</strong></li>
-<li><strong>Reader accepts any collection of strings, not just files.</strong></li>
+<li><strong>Reader accepts any iterator or collection of strings, not just files.</strong></li>
 </ul>
 <div><h3 id="write">Write</h3><pre><code class="python language-python hljs">&lt;writer&gt; = csv.writer(&lt;file&gt;)       <span class="hljs-comment"># Also: `dialect='excel', delimiter=','`.</span>
 &lt;writer&gt;.writerow(&lt;collection&gt;)     <span class="hljs-comment"># Encodes objects using `str(&lt;el&gt;)`.</span>
@@ -2938,7 +2938,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>June 20, 2025</aside>
+    <aside>June 21, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 8b2d95d3b229591de39fad047a318c792cde5164 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 21 Jun 2025 18:44:25 +0200
Subject: [PATCH 161/186] Regex, Format, Threading, NumPy

---
 README.md              | 14 +++++++-------
 index.html             | 20 +++++++++-----------
 pdf/index_for_pdf.html | 10 +++++-----
 3 files changed, 21 insertions(+), 23 deletions(-)

diff --git a/README.md b/README.md
index a0012ae21..6c7899fa0 100644
--- a/README.md
+++ b/README.md
@@ -361,7 +361,7 @@ Regex
 ```python
 import re
 <str>   = re.sub(r'<regex>', new, text, count=0)  # Substitutes all occurrences with 'new'.
-<list>  = re.findall(r'<regex>', text)            # Returns all occurrences as strings.
+<list>  = re.findall(r'<regex>', text)            # Returns all occurrences of the pattern.
 <list>  = re.split(r'<regex>', text, maxsplit=0)  # Add brackets around regex to keep matches.
 <Match> = re.search(r'<regex>', text)             # First occurrence of the pattern or None.
 <Match> = re.match(r'<regex>', text)              # Searches only at the beginning of the text.
@@ -398,7 +398,7 @@ Format
 ------
 ```perl
 <str> = f'{<el_1>}, {<el_2>}'            # Curly brackets can also contain expressions.
-<str> = '{}, {}'.format(<el_1>, <el_2>)  # Or: '{0}, {a}'.format(<el_1>, a=<el_2>)
+<str> = '{}, {}'.format(<el_1>, <el_2>)  # Same as '{0}, {a}'.format(<el_1>, a=<el_2>).
 <str> = '%s, %s' % (<el_1>, <el_2>)      # Redundant and inferior C-style formatting.
 ```
 
@@ -2289,7 +2289,7 @@ with <lock>:                                   # Enters the block by calling acq
 
 ### Thread Pool Executor
 ```python
-<Exec> = ThreadPoolExecutor(max_workers=None)  # Or: `with ThreadPoolExecutor() as <name>: ...`
+<Exec> = ThreadPoolExecutor(max_workers=None)  # Also `with ThreadPoolExecutor() as <name>: …`.
 <iter> = <Exec>.map(<func>, <args_1>, ...)     # Multithreaded and non-lazy map(). Keeps order.
 <Futr> = <Exec>.submit(<func>, <arg_1>, ...)   # Creates a thread and returns its Future obj.
 <Exec>.shutdown()                              # Waits for all submitted threads to finish.
@@ -2663,7 +2663,7 @@ import numpy as np
 ```python
 <view>  = <array>.reshape(<shape>)                      # Also `<array>.shape = <shape>`.
 <array> = <array>.flatten()                             # Also `<view> = <array>.ravel()`.
-<view>  = <array>.transpose()                           # Or: <array>.T
+<view>  = <array>.transpose()                           # Flips the table over its diagonal.
 ```
 
 ```python
@@ -2827,7 +2827,7 @@ from PIL import ImageDraw
 * **Use `'fill=<color>'` to set the primary color.**
 * **Use `'width=<int>'` to set the width of lines or contours.**
 * **Use `'outline=<color>'` to set the color of the contours.**
-* **Color can be an int, tuple, `'#rrggbb[aa]'` or a color name.**
+* **Color can be an int, tuple, `'#rrggbb[aa]'` string or a color name.**
 
 
 Animation
@@ -3421,7 +3421,7 @@ import plotly.express as px, pandas as pd
 <Fig> = px.histogram(<DF>, x=col_keys, y=col_key)     # Also color, nbins. All are optional.
 ```
 
-#### Displays a line chart of total coronavirus deaths per million grouped by continent:
+#### Displays a line chart of total COVID-19 deaths per million grouped by continent:
 
 ![Covid Deaths](web/covid_deaths.png)
 <div id="2a950764-39fc-416d-97fe-0a6226a3095f" class="plotly-graph-div" style="height:312px; width:914px;"></div>
@@ -3440,7 +3440,7 @@ df = df.rename({'date': 'Date', 'Continent_Name': 'Continent'}, axis='columns')
 px.line(df, x='Date', y='Total Deaths per Million', color='Continent')
 ```
 
-#### Displays a multi-axis line chart of total coronavirus cases and changes in prices of Bitcoin, Dow Jones and gold:
+#### Displays a multi-axis line chart of total COVID-19 cases and changes in prices of Bitcoin, Dow Jones and gold:
 
 ![Covid Cases](web/covid_cases.png)
 <div id="e23ccacc-a456-478b-b467-7282a2165921" class="plotly-graph-div" style="height:285px; width:935px;"></div>
diff --git a/index.html b/index.html
index f592a1f4b..ac30454b2 100644
--- a/index.html
+++ b/index.html
@@ -60,7 +60,8 @@
     <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>.
+   <div class="pagebreak"></div>
+<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"></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.
@@ -340,7 +341,7 @@
 
 <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
 &lt;str&gt;   = re.sub(<span class="hljs-string">r'&lt;regex&gt;'</span>, new, text, count=<span class="hljs-number">0</span>)  <span class="hljs-comment"># Substitutes all occurrences with 'new'.</span>
-&lt;list&gt;  = re.findall(<span class="hljs-string">r'&lt;regex&gt;'</span>, text)            <span class="hljs-comment"># Returns all occurrences as strings.</span>
+&lt;list&gt;  = re.findall(<span class="hljs-string">r'&lt;regex&gt;'</span>, text)            <span class="hljs-comment"># Returns all occurrences of the pattern.</span>
 &lt;list&gt;  = re.split(<span class="hljs-string">r'&lt;regex&gt;'</span>, text, maxsplit=<span class="hljs-number">0</span>)  <span class="hljs-comment"># Add brackets around regex to keep matches.</span>
 &lt;Match&gt; = re.search(<span class="hljs-string">r'&lt;regex&gt;'</span>, text)             <span class="hljs-comment"># First occurrence of the pattern or None.</span>
 &lt;Match&gt; = re.match(<span class="hljs-string">r'&lt;regex&gt;'</span>, text)              <span class="hljs-comment"># Searches only at the beginning of the text.</span>
@@ -373,7 +374,7 @@
 <li><strong>Use a capital letter for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).</strong></li>
 </ul>
 <div><h2 id="format"><a href="#format" name="format">#</a>Format</h2><pre><code class="python hljs">&lt;str&gt; = <span class="hljs-string">f'<span class="hljs-subst">{&lt;el_1&gt;}</span>, <span class="hljs-subst">{&lt;el_2&gt;}</span>'</span>            <span class="hljs-comment"># Curly brackets can also contain expressions.</span>
-&lt;str&gt; = <span class="hljs-string">'{}, {}'</span>.format(&lt;el_1&gt;, &lt;el_2&gt;)  <span class="hljs-comment"># Or: '{0}, {a}'.format(&lt;el_1&gt;, a=&lt;el_2&gt;)</span>
+&lt;str&gt; = <span class="hljs-string">'{}, {}'</span>.format(&lt;el_1&gt;, &lt;el_2&gt;)  <span class="hljs-comment"># Same as '{0}, {a}'.format(&lt;el_1&gt;, a=&lt;el_2&gt;).</span>
 &lt;str&gt; = <span class="hljs-string">'%s, %s'</span> % (&lt;el_1&gt;, &lt;el_2&gt;)      <span class="hljs-comment"># Redundant and inferior C-style formatting.</span>
 </code></pre></div>
 
@@ -593,7 +594,6 @@
 &lt;TD&gt;     = &lt;DTa&gt;     - &lt;DTa&gt;                <span class="hljs-comment"># Ignores jumps if they share tzinfo object.</span>
 &lt;D/DT&gt;   = &lt;D/DT&gt;    ± &lt;TD&gt;                 <span class="hljs-comment"># Returned datetime can fall into missing hour.</span>
 &lt;TD&gt;     = &lt;TD&gt;      * &lt;float&gt;              <span class="hljs-comment"># Also `&lt;TD&gt; = abs(&lt;TD&gt;)`, `&lt;TD&gt; = &lt;TD&gt; ± &lt;TD&gt;`.</span>
-&lt;float&gt;  = &lt;TD&gt;      / &lt;TD&gt;                 <span class="hljs-comment"># Also `(&lt;int&gt;, &lt;TD&gt;) = divmod(&lt;TD&gt;, &lt;TD&gt;)`.</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> &lt;<span class="hljs-title">func_name</span>&gt;<span class="hljs-params">(&lt;nondefault_args&gt;)</span>:</span> ...                  <span class="hljs-comment"># E.g. `def func(x, y): ...`.</span>
@@ -1568,7 +1568,6 @@
 <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
@@ -1888,7 +1887,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;el&gt; = &lt;Queue&gt;.get_nowait()                    <span class="hljs-comment"># Raises queue.Empty exception if empty.</span>
 </code></pre></div>
 
-<div><h3 id="threadpoolexecutor">Thread Pool Executor</h3><pre><code class="python language-python hljs">&lt;Exec&gt; = ThreadPoolExecutor(max_workers=<span class="hljs-keyword">None</span>)  <span class="hljs-comment"># Or: `with ThreadPoolExecutor() as &lt;name&gt;: ...`</span>
+<div><h3 id="threadpoolexecutor">Thread Pool Executor</h3><pre><code class="python language-python hljs">&lt;Exec&gt; = ThreadPoolExecutor(max_workers=<span class="hljs-keyword">None</span>)  <span class="hljs-comment"># Also `with ThreadPoolExecutor() as &lt;name&gt;: …`.</span>
 &lt;iter&gt; = &lt;Exec&gt;.map(&lt;func&gt;, &lt;args_1&gt;, ...)     <span class="hljs-comment"># Multithreaded and non-lazy map(). Keeps order.</span>
 &lt;Futr&gt; = &lt;Exec&gt;.submit(&lt;func&gt;, &lt;arg_1&gt;, ...)   <span class="hljs-comment"># Creates a thread and returns its Future obj.</span>
 &lt;Exec&gt;.shutdown()                              <span class="hljs-comment"># Waits for all submitted threads to finish.</span>
@@ -1974,7 +1973,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     curses.wrapper(main)
 </code></pre></div>
 
-<p><br></p>
 <div><h1 id="libraries">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">&gt;&gt;&gt; </span><span class="hljs-keyword">import</span> tqdm, time
 <span class="hljs-meta">&gt;&gt;&gt; </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>):
@@ -2191,7 +2189,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <pre><code class="python language-python hljs">&lt;view&gt;  = &lt;array&gt;.reshape(&lt;shape&gt;)                      <span class="hljs-comment"># Also `&lt;array&gt;.shape = &lt;shape&gt;`.</span>
 &lt;array&gt; = &lt;array&gt;.flatten()                             <span class="hljs-comment"># Also `&lt;view&gt; = &lt;array&gt;.ravel()`.</span>
-&lt;view&gt;  = &lt;array&gt;.transpose()                           <span class="hljs-comment"># Or: &lt;array&gt;.T</span>
+&lt;view&gt;  = &lt;array&gt;.transpose()                           <span class="hljs-comment"># Flips the table over its diagonal.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;array&gt; = np.copy/abs/sqrt/log/int64(&lt;array&gt;)           <span class="hljs-comment"># Returns new array of the same shape.</span>
 &lt;array&gt; = &lt;array&gt;.sum/max/mean/argmax/all(axis)         <span class="hljs-comment"># Aggregates specified dimension.</span>
@@ -2323,7 +2321,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'fill=&lt;color&gt;'</span></code> to set the primary color.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'width=&lt;int&gt;'</span></code> to set the width of lines or contours.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'outline=&lt;color&gt;'</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 a color name.</strong></li>
+<li><strong>Color can be an int, tuple, <code class="python hljs"><span class="hljs-string">'#rrggbb[aa]'</span></code> string or a 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
@@ -2797,7 +2795,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;Fig&gt; = px.scatter_3d(&lt;DF&gt;, x=col_key, y=col_key, …)  <span class="hljs-comment"># `z=col_key`. Also color, size, symbol.</span>
 &lt;Fig&gt; = px.histogram(&lt;DF&gt;, x=col_keys, y=col_key)     <span class="hljs-comment"># Also color, nbins. All are optional.</span>
 </code></pre>
-<div><h4 id="displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">Displays a line chart of total coronavirus 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>
+<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>,
@@ -2812,7 +2810,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<div><h4 id="displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">Displays a multi-axis line chart of total coronavirus 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>
+<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>
diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html
index 4327865bf..b151d3527 100644
--- a/pdf/index_for_pdf.html
+++ b/pdf/index_for_pdf.html
@@ -30,7 +30,7 @@ <h3 id="c">C</h3>
 <strong>copy function, <a href="#copy">15</a></strong><br>
 <strong>coroutine, <a href="#coroutines">33</a></strong><br>
 <strong>counter, <a href="#counter">2</a>, <a href="#generator">4</a>, <a href="#nonlocal">12</a>, <a href="#iterator-1">17</a></strong><br>
-<strong>csv, <a href="#csv">26</a>, <a href="#printsacsvspreadsheettotheconsole">34</a>, <a href="#fileformats">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a></strong><br>
+<strong>csv, <a href="#csv">26</a>, <a href="#printsacsvspreadsheettotheconsole">34</a>, <a href="#fileformats">46</a>, <a href="#displaysalinechartoftotalcovid19deathspermilliongroupedbycontinent">47</a></strong><br>
 <strong>curses module, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a>, <a href="#consoleapp">34</a></strong><br>
 <strong>cython, <a href="#typeannotations">15</a>, <a href="#cython">49</a></strong>  </p>
 <h3 id="d">D</h3>
@@ -97,12 +97,12 @@ <h3 id="o">O</h3>
 <strong>operator module, <a href="#operator">30</a></strong><br>
 <strong>os commands, <a href="#paths">23</a>-<a href="#shellcommands">25</a>, <a href="#runsabasicfileexplorerintheconsole">34</a></strong>  </p>
 <h3 id="p">P</h3>
-<p><strong>pandas library, <a href="#pandas">44</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
+<p><strong>pandas library, <a href="#pandas">44</a>-<a href="#displaysamultiaxislinechartoftotalcovid19casesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
 <strong>partial function, <a href="#partial">12</a>, <a href="#userdefinedfunctionscannotbevaluessotheymustbewrapped">20</a></strong><br>
 <strong>paths, <a href="#paths">23</a>-<a href="#oscommands">24</a>, <a href="#runsabasicfileexplorerintheconsole">34</a></strong><br>
 <strong>pickle module, <a href="#pickle">25</a></strong><br>
 <strong>pillow library, <a href="#image">39</a>-<a href="#animation">40</a></strong><br>
-<strong>plotting, <a href="#plot">34</a>, <a href="#pandas">44</a>, <a href="#dataframe">45</a>, <a href="#plotly">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
+<strong>plotting, <a href="#plot">34</a>, <a href="#pandas">44</a>, <a href="#dataframe">45</a>, <a href="#plotly">47</a>-<a href="#displaysamultiaxislinechartoftotalcovid19casesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
 <strong>print function, <a href="#class">14</a>, <a href="#print">22</a></strong><br>
 <strong>profiling, <a href="#profiling">36</a>-<a href="#profilingbyline">37</a></strong><br>
 <strong>progress bar, <a href="#progressbar">34</a></strong><br>
@@ -119,7 +119,7 @@ <h3 id="r">R</h3>
 <strong>requests library, <a href="#scrapespythonsurlandlogofromitswikipediapage">35</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong>  </p>
 <h3 id="s">S</h3>
 <p><strong>scope, <a href="#insidefunctiondefinition">10</a>, <a href="#nonlocal">12</a>, <a href="#complexexample">20</a></strong><br>
-<strong>scraping, <a href="#scraping">35</a>, <a href="#basicmariobrothersexample">43</a>, <a href="#fileformats">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
+<strong>scraping, <a href="#scraping">35</a>, <a href="#basicmariobrothersexample">43</a>, <a href="#fileformats">46</a>, <a href="#displaysalinechartoftotalcovid19deathspermilliongroupedbycontinent">47</a>-<a href="#displaysamultiaxislinechartoftotalcovid19casesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
 <strong>sequence, <a href="#abstractbaseclasses">4</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a></strong><br>
 <strong>sets, <a href="#set">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">10</a>-<a href="#comprehensions">11</a>, <a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br>
 <strong>shell commands, <a href="#shellcommands">25</a></strong><br>
@@ -127,7 +127,7 @@ <h3 id="s">S</h3>
 <strong>sortable, <a href="#list">1</a>, <a href="#sortable">16</a></strong><br>
 <strong>splat operator, <a href="#splatoperator">10</a>, <a href="#readrowsfromcsvfile">26</a></strong><br>
 <strong>sql, <a href="#sqlite">27</a>, <a href="#fileformats">46</a></strong><br>
-<strong>statistics, <a href="#statistics">7</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#pandas">44</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
+<strong>statistics, <a href="#statistics">7</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#pandas">44</a>-<a href="#displaysamultiaxislinechartoftotalcovid19casesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br>
 <strong>strings, <a href="#abstractbaseclasses">4</a>-<a href="#comparisonofpresentationtypes">7</a>, <a href="#class">14</a></strong><br>
 <strong>struct module, <a href="#struct">28</a>-<a href="#integertypesuseacapitalletterforunsignedtypeminimumandstandardsizesareinbrackets">29</a></strong><br>
 <strong>subprocess module, <a href="#sends11tothebasiccalculatorandcapturesitsoutput">25</a></strong><br>

From e97360e84a4e32fccd058777a15d81cc0441714b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 19 Jul 2025 06:25:27 +0200
Subject: [PATCH 162/186] Reverted Datetime and Csv

---
 index.html | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/index.html b/index.html
index ac30454b2..f5b43c5cd 100644
--- a/index.html
+++ b/index.html
@@ -56,12 +56,11 @@
 
 <body>
   <header>
-    <aside>June 21, 2025</aside>
+    <aside>July 19, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
-   <div class="pagebreak"></div>
-<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>.
+   <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"></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.
@@ -594,6 +593,7 @@
 &lt;TD&gt;     = &lt;DTa&gt;     - &lt;DTa&gt;                <span class="hljs-comment"># Ignores jumps if they share tzinfo object.</span>
 &lt;D/DT&gt;   = &lt;D/DT&gt;    ± &lt;TD&gt;                 <span class="hljs-comment"># Returned datetime can fall into missing hour.</span>
 &lt;TD&gt;     = &lt;TD&gt;      * &lt;float&gt;              <span class="hljs-comment"># Also `&lt;TD&gt; = abs(&lt;TD&gt;)`, `&lt;TD&gt; = &lt;TD&gt; ± &lt;TD&gt;`.</span>
+&lt;float&gt;  = &lt;TD&gt;      / &lt;TD&gt;                 <span class="hljs-comment"># Also `(&lt;int&gt;, &lt;TD&gt;) = divmod(&lt;TD&gt;, &lt;TD&gt;)`.</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> &lt;<span class="hljs-title">func_name</span>&gt;<span class="hljs-params">(&lt;nondefault_args&gt;)</span>:</span> ...                  <span class="hljs-comment"># E.g. `def func(x, y): ...`.</span>
@@ -1568,6 +1568,7 @@
 <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
@@ -1973,6 +1974,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     curses.wrapper(main)
 </code></pre></div>
 
+<p><br></p>
 <div><h1 id="libraries">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">&gt;&gt;&gt; </span><span class="hljs-keyword">import</span> tqdm, time
 <span class="hljs-meta">&gt;&gt;&gt; </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>):
@@ -2936,7 +2938,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>June 21, 2025</aside>
+    <aside>July 19, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 91dea910b0c31021c146bc097424c0afeb0e4fc7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 20 Jul 2025 19:53:49 +0200
Subject: [PATCH 163/186] List, Dictionary, Iterator

---
 README.md  | 14 +++++++-------
 index.html | 18 +++++++++---------
 2 files changed, 16 insertions(+), 16 deletions(-)

diff --git a/README.md b/README.md
index 6c7899fa0..30b102f1c 100644
--- a/README.md
+++ b/README.md
@@ -43,9 +43,9 @@ List
 ```
 
 ```python
-<list>.sort()                   # Sorts elements in ascending order.
-<list>.reverse()                # Reverses the list in-place.
-<list> = sorted(<collection>)   # Returns new list with sorted elements.
+<list>.sort()                   # Sorts the elements in ascending order.
+<list>.reverse()                # Reverses the order of list's elements.
+<list> = sorted(<collection>)   # Returns a new list with sorted elements.
 <iter> = reversed(<list>)       # Returns reversed iterator of elements.
 ```
 
@@ -88,7 +88,7 @@ Dictionary
 ```
 
 ```python
-value  = <dict>.get(key, default=None)          # Returns default if key is missing.
+value  = <dict>.get(key, default=None)          # Returns default argument if key is missing.
 value  = <dict>.setdefault(key, default=None)   # Returns and writes default if key is missing.
 <dict> = collections.defaultdict(<type>)        # Returns a dict with default value `<type>()`.
 <dict> = collections.defaultdict(lambda: 1)     # Returns a dict with default value 1.
@@ -168,7 +168,7 @@ Tuple
 >>> p = Point(1, y=2)
 >>> print(p)
 Point(x=1, y=2)
->>> p[0], p.y
+>>> p.x, p[1]
 (1, 2)
 ```
 
@@ -215,11 +215,11 @@ import itertools as it
 ```python
 <iter> = it.count(start=0, step=1)         # Returns updated value endlessly. Accepts floats.
 <iter> = it.repeat(<el> [, times])         # Returns element endlessly or 'times' times.
-<iter> = it.cycle(<collection>)            # Repeats the sequence endlessly.
+<iter> = it.cycle(<collection>)            # Repeats the passed sequence of elements endlessly.
 ```
 
 ```python
-<iter> = it.chain(<coll>, <coll> [, ...])  # Empties collections in order (figuratively).
+<iter> = it.chain(<coll>, <coll> [, ...])  # Empties collections in order (only figuratively).
 <iter> = it.chain.from_iterable(<coll>)    # Empties collections inside a collection in order.
 ```
 
diff --git a/index.html b/index.html
index f5b43c5cd..0b78835ff 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>July 19, 2025</aside>
+    <aside>July 20, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -120,9 +120,9 @@
 <pre><code class="python language-python hljs">&lt;list&gt;.append(&lt;el&gt;)             <span class="hljs-comment"># Appends element to the end. Also &lt;list&gt; += [&lt;el&gt;].</span>
 &lt;list&gt;.extend(&lt;collection&gt;)     <span class="hljs-comment"># Appends elements to the end. Also &lt;list&gt; += &lt;coll&gt;.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;list&gt;.sort()                   <span class="hljs-comment"># Sorts elements in ascending order.</span>
-&lt;list&gt;.reverse()                <span class="hljs-comment"># Reverses the list in-place.</span>
-&lt;list&gt; = sorted(&lt;collection&gt;)   <span class="hljs-comment"># Returns new list with sorted elements.</span>
+<pre><code class="python language-python hljs">&lt;list&gt;.sort()                   <span class="hljs-comment"># Sorts the elements in ascending order.</span>
+&lt;list&gt;.reverse()                <span class="hljs-comment"># Reverses the order of list's elements.</span>
+&lt;list&gt; = sorted(&lt;collection&gt;)   <span class="hljs-comment"># Returns a new list with sorted elements.</span>
 &lt;iter&gt; = reversed(&lt;list&gt;)       <span class="hljs-comment"># Returns reversed iterator of elements.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;el&gt;  = max(&lt;collection&gt;)       <span class="hljs-comment"># Returns largest element. Also min(&lt;el_1&gt;, ...).</span>
@@ -153,7 +153,7 @@
 &lt;view&gt; = &lt;dict&gt;.values()                        <span class="hljs-comment"># Collection of values that reflects changes.</span>
 &lt;view&gt; = &lt;dict&gt;.items()                         <span class="hljs-comment"># Coll. of key-value tuples that reflects chgs.</span>
 </code></pre>
-<pre><code class="python language-python hljs">value  = &lt;dict&gt;.get(key, default=<span class="hljs-keyword">None</span>)          <span class="hljs-comment"># Returns default if key is missing.</span>
+<pre><code class="python language-python hljs">value  = &lt;dict&gt;.get(key, default=<span class="hljs-keyword">None</span>)          <span class="hljs-comment"># Returns default argument if key is missing.</span>
 value  = &lt;dict&gt;.setdefault(key, default=<span class="hljs-keyword">None</span>)   <span class="hljs-comment"># Returns and writes default if key is missing.</span>
 &lt;dict&gt; = collections.defaultdict(&lt;type&gt;)        <span class="hljs-comment"># Returns a dict with default value `&lt;type&gt;()`.</span>
 &lt;dict&gt; = collections.defaultdict(<span class="hljs-keyword">lambda</span>: <span class="hljs-number">1</span>)     <span class="hljs-comment"># Returns a dict with default value 1.</span>
@@ -209,7 +209,7 @@
 <span class="hljs-meta">&gt;&gt;&gt; </span>p = Point(<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>)
 <span class="hljs-meta">&gt;&gt;&gt; </span>print(p)
 Point(x=<span class="hljs-number">1</span>, y=<span class="hljs-number">2</span>)
-<span class="hljs-meta">&gt;&gt;&gt; </span>p[<span class="hljs-number">0</span>], p.y
+<span class="hljs-meta">&gt;&gt;&gt; </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>
 
@@ -239,9 +239,9 @@
 
 <pre><code class="python language-python hljs">&lt;iter&gt; = it.count(start=<span class="hljs-number">0</span>, step=<span class="hljs-number">1</span>)         <span class="hljs-comment"># Returns updated value endlessly. Accepts floats.</span>
 &lt;iter&gt; = it.repeat(&lt;el&gt; [, times])         <span class="hljs-comment"># Returns element endlessly or 'times' times.</span>
-&lt;iter&gt; = it.cycle(&lt;collection&gt;)            <span class="hljs-comment"># Repeats the sequence endlessly.</span>
+&lt;iter&gt; = it.cycle(&lt;collection&gt;)            <span class="hljs-comment"># Repeats the passed sequence of elements endlessly.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;iter&gt; = it.chain(&lt;coll&gt;, &lt;coll&gt; [, ...])  <span class="hljs-comment"># Empties collections in order (figuratively).</span>
+<pre><code class="python language-python hljs">&lt;iter&gt; = it.chain(&lt;coll&gt;, &lt;coll&gt; [, ...])  <span class="hljs-comment"># Empties collections in order (only figuratively).</span>
 &lt;iter&gt; = it.chain.from_iterable(&lt;coll&gt;)    <span class="hljs-comment"># Empties collections inside a collection in order.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;iter&gt; = it.islice(&lt;coll&gt;, to_exclusive)   <span class="hljs-comment"># Only returns first 'to_exclusive' elements.</span>
@@ -2938,7 +2938,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>July 19, 2025</aside>
+    <aside>July 20, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From 5196ca52c09c2faad71afbeb95c1a835cbebe386 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 23 Jul 2025 02:28:03 +0200
Subject: [PATCH 164/186] List, Regex, Format, Numbers, Datetime

---
 README.md  | 48 ++++++++++++++++++++++++------------------------
 index.html | 50 +++++++++++++++++++++++++-------------------------
 2 files changed, 49 insertions(+), 49 deletions(-)

diff --git a/README.md b/README.md
index 30b102f1c..e54bfdd4e 100644
--- a/README.md
+++ b/README.md
@@ -69,9 +69,9 @@ flatter_list     = list(itertools.chain.from_iterable(<list>))
 <int> = <list>.count(<el>)      # Returns number of occurrences. Also `if <el> in <coll>: ...`.
 <int> = <list>.index(<el>)      # Returns index of the first occurrence or raises ValueError.
 <el>  = <list>.pop()            # Removes and returns item from the end or at index if passed.
-<list>.insert(<int>, <el>)      # Inserts item at index and moves the rest to the right.
+<list>.insert(<int>, <el>)      # Inserts item at passed index and moves the rest to the right.
 <list>.remove(<el>)             # Removes first occurrence of the item or raises ValueError.
-<list>.clear()                  # Removes all items. Also works on dictionary and set.
+<list>.clear()                  # Removes all items. Also works on dictionaries and sets.
 ```
 
 
@@ -370,9 +370,9 @@ import re
 
 * **Raw string literals do not interpret escape sequences, thus enabling us to use regex-specific escape sequences that cause SyntaxWarning in normal string literals (since 3.12).**
 * **Argument 'new' of re.sub() can be a function that accepts Match object and returns a str.**
-* **Argument `'flags=re.IGNORECASE'` can be used with all functions.**
+* **Argument `'flags=re.IGNORECASE'` can be used with all listed regex functions.**
 * **Argument `'flags=re.MULTILINE'` makes `'^'` and `'$'` match the start/end of each line.**
-* **Argument `'flags=re.DOTALL'` makes `'.'` also accept the `'\n'`.**
+* **Argument `'flags=re.DOTALL'` makes `'.'` also accept the `'\n'` (besides all other chars).**
 * **`'re.compile(<regex>)'` returns a Pattern object with methods sub(), findall(), etc.**
 
 ### Match Object
@@ -380,8 +380,8 @@ import re
 <str>   = <Match>.group()                         # Returns the whole match. Also group(0).
 <str>   = <Match>.group(1)                        # Returns part inside the first brackets.
 <tuple> = <Match>.groups()                        # Returns all bracketed parts as strings.
-<int>   = <Match>.start()                         # Returns start index of the match.
-<int>   = <Match>.end()                           # Returns exclusive end index of the match.
+<int>   = <Match>.start()                         # Returns start index of the whole match.
+<int>   = <Match>.end()                           # Returns its exclusive end index.
 ```
 
 ### Special Sequences
@@ -397,7 +397,7 @@ import re
 Format
 ------
 ```perl
-<str> = f'{<el_1>}, {<el_2>}'            # Curly brackets can also contain expressions.
+<str> = f'{<el_1>}, {<el_2>}'            # Curly braces can also contain expressions.
 <str> = '{}, {}'.format(<el_1>, <el_2>)  # Same as '{0}, {a}'.format(<el_1>, a=<el_2>).
 <str> = '%s, %s' % (<el_1>, <el_2>)      # Redundant and inferior C-style formatting.
 ```
@@ -418,8 +418,8 @@ Format
 {<el>:.<10}                              # '<el>......'
 {<el>:0}                                 # '<el>'
 ```
-* **Objects are rendered using `'format(<el>, "<options>")'`.**
-* **Options can be generated dynamically: `f'{<el>:{<str/int>}[…]}'`.**
+* **Objects are rendered by calling the `'format(<el>, "<options>")'` function.**
+* **Options inside curly braces can be generated dynamically: `f'{<el>:{<str/int>}[…]}'`.**
 * **Adding `'='` to the expression prepends it to the output: `f'{1+1=}'` returns `'1+1=2'`.**
 * **Adding `'!r'` to the expression converts object to string by calling its [repr()](#class) method.**
 
@@ -495,13 +495,13 @@ Numbers
 ```python
 <int>      = int(<float/str/bool>)             # Whole number of any size. Truncates floats.
 <float>    = float(<int/str/bool>)             # 64-bit decimal number. Also <float>e±<int>.
-<complex>  = complex(real=0, imag=0)           # Complex number. Also `<float> ± <float>j`.
+<complex>  = complex(real=0, imag=0)           # A complex number. Also `<float> ± <float>j`.
 <Fraction> = fractions.Fraction(<int>, <int>)  # E.g. `Fraction(1, 2) / 3 == Fraction(1, 6)`.
 <Decimal>  = decimal.Decimal(<str/int/tuple>)  # E.g. `Decimal((1, (2, 3), 4)) == -230_000`.
 ```
-* **`'int(<str>)'` and `'float(<str>)'` raise ValueError on malformed strings.**
+* **`'int(<str>)'` and `'float(<str>)'` raise ValueError if passed string is malformed.**
 * **Decimal objects store numbers exactly, unlike most floats where `'1.1 + 2.2 != 3.3'`.**
-* **Floats can be compared with: `'math.isclose(<float>, <float>)'`.**
+* **Floats can be compared with: `'math.isclose(<float>, <float>, rel_tol=1e-09)'`.**
 * **Precision of decimal operations is set with: `'decimal.getcontext().prec = <int>'`.**
 * **Bools can be used anywhere ints can, because bool is a subclass of int: `'True + 1 == 2'`.**
 
@@ -539,7 +539,7 @@ from random import random, randint, uniform    # Also: gauss, choice, shuffle, s
 <num>   = randint/uniform(a, b)                # Returns an int/float inside [a, b].
 <float> = gauss(mean, stdev)                   # Also triangular(low, high, mode).
 <el>    = choice(<sequence>)                   # Keeps it intact. Also sample(p, n).
-shuffle(<list>)                                # Works on any mutable sequence.
+shuffle(<list>)                                # Works on all mutable sequences.
 ```
 
 ### Hexadecimal Numbers
@@ -554,8 +554,8 @@ shuffle(<list>)                                # Works on any mutable sequence.
 <int> = <int> & <int>                          # E.g. `0b1100 & 0b1010 == 0b1000`.
 <int> = <int> | <int>                          # E.g. `0b1100 | 0b1010 == 0b1110`.
 <int> = <int> ^ <int>                          # E.g. `0b1100 ^ 0b1010 == 0b0110`.
-<int> = <int> << n_bits                        # Left shift. Use >> for right.
-<int> = ~<int>                                 # Not. Same as `-<int> - 1`.
+<int> = <int> << n_bits                        # E.g. `0b1100 << 4 == 0b1100_0000`.
+<int> = ~<int>                                 # E.g. `~0b1 == -0b10 == -(0b1+1)`.
 ```
 
 
@@ -603,8 +603,8 @@ import zoneinfo, dateutil.tz
 <DT> = datetime(year, month, day, hour=0)   # Also: `minute=0, second=0, microsecond=0, …`.
 <TD> = timedelta(weeks=0, days=0, hours=0)  # Also: `minutes=0, seconds=0, microseconds=0`.
 ```
-* **Times and datetimes that have defined timezone are called aware and ones that don't, naive. If object is naive, it is presumed to be in the system's timezone!**
-* **`'fold=1'` means the second pass in case of time jumping back for one hour.**
+* **Times and datetimes that have defined timezone are called aware and ones that don't, naive. If time or datetime object is naive, it is presumed to be in the system's timezone!**
+* **`'fold=1'` means the second pass in case of time jumping back (usually for one hour).**
 * **Timedelta normalizes arguments to ±days, seconds (< 86 400) and microseconds (< 1M). Its str() method returns `'[±D, ]H:MM:SS[.…]'` and total_seconds() a float of all seconds.**
 * **Use `'<D/DT>.weekday()'` to get the day of the week as an integer, with Monday being 0.**
 
@@ -615,10 +615,10 @@ import zoneinfo, dateutil.tz
 ```
 * **To extract time use `'<DTn>.time()'`, `'<DTa>.time()'` or `'<DTa>.timetz()'`.**
 
-### Timezone
+### Timezones
 ```python
-<tzinfo> = timezone.utc                     # London without daylight saving time (DST).
-<tzinfo> = timezone(<timedelta>)            # Timezone with fixed offset from UTC.
+<tzinfo> = timezone.utc                     # Coordinated universal time (UK without DST).
+<tzinfo> = timezone(<timedelta>)            # Timezone with fixed offset from universal time.
 <tzinfo> = dateutil.tz.tzlocal()            # Local timezone with dynamic offset from UTC.
 <tzinfo> = zoneinfo.ZoneInfo('<iana_key>')  # 'Continent/City_Name' zone with dynamic offset.
 <DTa>    = <DT>.astimezone([<tzinfo>])      # Converts DT to the passed or local fixed zone.
@@ -642,7 +642,7 @@ import zoneinfo, dateutil.tz
 ```python
 <str>    = <D/T/DT>.isoformat(sep='T')      # Also `timespec='auto/hours/minutes/seconds/…'`.
 <str>    = <D/T/DT>.strftime('<format>')    # Custom string representation of the object.
-<int>    = <D/DT>.toordinal()               # Days since Gregorian NYE 1, ignoring time and tz.
+<int>    = <D/DT>.toordinal()               # Days since NYE 1, ignoring time and timezone.
 <float>  = <DTn>.timestamp()                # Seconds since the Epoch, from local naive DT.
 <float>  = <DTa>.timestamp()                # Seconds since the Epoch, from aware datetime.
 ```
@@ -661,7 +661,7 @@ import zoneinfo, dateutil.tz
 <bool>   = <D/T/DTn> > <D/T/DTn>            # Ignores time jumps (fold attribute). Also ==.
 <bool>   = <DTa>     > <DTa>                # Ignores time jumps if they share tzinfo object.
 <TD>     = <D/DTn>   - <D/DTn>              # Ignores jumps. Convert to UTC for actual delta.
-<TD>     = <DTa>     - <DTa>                # Ignores jumps if they share tzinfo object.
+<TD>     = <DTa>     - <DTa>                # Ignores jumps if they share the tzinfo object.
 <D/DT>   = <D/DT>    ± <TD>                 # Returned datetime can fall into missing hour.
 <TD>     = <TD>      * <float>              # Also `<TD> = abs(<TD>)`, `<TD> = <TD> ± <TD>`.
 <float>  = <TD>      / <TD>                 # Also `(<int>, <TD>) = divmod(<TD>, <TD>)`.
@@ -788,8 +788,8 @@ from functools import reduce
 
 ### And, Or
 ```python
-<obj> = <exp> and <exp> [and ...]                   # Returns first false or last operand.
-<obj> = <exp> or <exp> [or ...]                     # Returns first true or last operand.
+<obj> = <exp> and <exp> [and ...]                   # Returns first false or last object.
+<obj> = <exp> or <exp> [or ...]                     # Returns first true or last object.
 ```
 
 ### Walrus Operator
diff --git a/index.html b/index.html
index 0b78835ff..e12914352 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>July 20, 2025</aside>
+    <aside>July 23, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -142,9 +142,9 @@
 &lt;int&gt; = &lt;list&gt;.count(&lt;el&gt;)      <span class="hljs-comment"># Returns number of occurrences. Also `if &lt;el&gt; in &lt;coll&gt;: ...`.</span>
 &lt;int&gt; = &lt;list&gt;.index(&lt;el&gt;)      <span class="hljs-comment"># Returns index of the first occurrence or raises ValueError.</span>
 &lt;el&gt;  = &lt;list&gt;.pop()            <span class="hljs-comment"># Removes and returns item from the end or at index if passed.</span>
-&lt;list&gt;.insert(&lt;int&gt;, &lt;el&gt;)      <span class="hljs-comment"># Inserts item at index and moves the rest to the right.</span>
+&lt;list&gt;.insert(&lt;int&gt;, &lt;el&gt;)      <span class="hljs-comment"># Inserts item at passed index and moves the rest to the right.</span>
 &lt;list&gt;.remove(&lt;el&gt;)             <span class="hljs-comment"># Removes first occurrence of the item or raises ValueError.</span>
-&lt;list&gt;.clear()                  <span class="hljs-comment"># Removes all items. Also works on dictionary and set.</span>
+&lt;list&gt;.clear()                  <span class="hljs-comment"># Removes all items. Also works on dictionaries and sets.</span>
 </code></pre>
 <div><h2 id="dictionary"><a href="#dictionary" name="dictionary">#</a>Dictionary</h2><pre><code class="python language-python hljs">&lt;dict&gt; = {key_1: val_1, key_2: val_2, ...}      <span class="hljs-comment"># Use `&lt;dict&gt;[key]` to get or set the value.</span>
 </code></pre></div>
@@ -351,16 +351,16 @@
 <ul>
 <li><strong>Raw string literals do not interpret escape sequences, thus enabling us to use regex-specific escape sequences that cause SyntaxWarning in normal string literals (since 3.12).</strong></li>
 <li><strong>Argument 'new' of re.sub() can be a function that accepts Match object and returns a str.</strong></li>
-<li><strong>Argument <code class="python hljs"><span class="hljs-string">'flags=re.IGNORECASE'</span></code> can be used with all functions.</strong></li>
+<li><strong>Argument <code class="python hljs"><span class="hljs-string">'flags=re.IGNORECASE'</span></code> can be used with all listed regex functions.</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>.</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(&lt;regex&gt;)'</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">&lt;str&gt;   = &lt;Match&gt;.group()                         <span class="hljs-comment"># Returns the whole match. Also group(0).</span>
 &lt;str&gt;   = &lt;Match&gt;.group(<span class="hljs-number">1</span>)                        <span class="hljs-comment"># Returns part inside the first brackets.</span>
 &lt;tuple&gt; = &lt;Match&gt;.groups()                        <span class="hljs-comment"># Returns all bracketed parts as strings.</span>
-&lt;int&gt;   = &lt;Match&gt;.start()                         <span class="hljs-comment"># Returns start index of the match.</span>
-&lt;int&gt;   = &lt;Match&gt;.end()                           <span class="hljs-comment"># Returns exclusive end index of the match.</span>
+&lt;int&gt;   = &lt;Match&gt;.start()                         <span class="hljs-comment"># Returns start index of the whole match.</span>
+&lt;int&gt;   = &lt;Match&gt;.end()                           <span class="hljs-comment"># Returns its exclusive end index.</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 a decimal character.</span>
@@ -372,7 +372,7 @@
 <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 for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).</strong></li>
 </ul>
-<div><h2 id="format"><a href="#format" name="format">#</a>Format</h2><pre><code class="python hljs">&lt;str&gt; = <span class="hljs-string">f'<span class="hljs-subst">{&lt;el_1&gt;}</span>, <span class="hljs-subst">{&lt;el_2&gt;}</span>'</span>            <span class="hljs-comment"># Curly brackets can also contain expressions.</span>
+<div><h2 id="format"><a href="#format" name="format">#</a>Format</h2><pre><code class="python hljs">&lt;str&gt; = <span class="hljs-string">f'<span class="hljs-subst">{&lt;el_1&gt;}</span>, <span class="hljs-subst">{&lt;el_2&gt;}</span>'</span>            <span class="hljs-comment"># Curly braces can also contain expressions.</span>
 &lt;str&gt; = <span class="hljs-string">'{}, {}'</span>.format(&lt;el_1&gt;, &lt;el_2&gt;)  <span class="hljs-comment"># Same as '{0}, {a}'.format(&lt;el_1&gt;, a=&lt;el_2&gt;).</span>
 &lt;str&gt; = <span class="hljs-string">'%s, %s'</span> % (&lt;el_1&gt;, &lt;el_2&gt;)      <span class="hljs-comment"># Redundant and inferior C-style formatting.</span>
 </code></pre></div>
@@ -391,8 +391,8 @@
 </code></pre></div>
 
 <ul>
-<li><strong>Objects are rendered using <code class="python hljs"><span class="hljs-string">'format(&lt;el&gt;, "&lt;options&gt;")'</span></code>.</strong></li>
-<li><strong>Options can be generated dynamically: <code class="python hljs"><span class="hljs-string">f'<span class="hljs-subst">{&lt;el&gt;:{&lt;str/int&gt;}</span>[…]}'</span></code>.</strong></li>
+<li><strong>Objects are rendered by calling the <code class="python hljs"><span class="hljs-string">'format(&lt;el&gt;, "&lt;options&gt;")'</span></code> function.</strong></li>
+<li><strong>Options inside curly braces can be generated dynamically: <code class="python hljs"><span class="hljs-string">f'<span class="hljs-subst">{&lt;el&gt;:{&lt;str/int&gt;}</span>[…]}'</span></code>.</strong></li>
 <li><strong>Adding <code class="python hljs"><span class="hljs-string">'='</span></code> to the expression prepends it to the output: <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 converts object to string by calling its <a href="#class">repr()</a> method.</strong></li>
 </ul>
@@ -455,15 +455,15 @@
 
 <div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs">&lt;int&gt;      = int(&lt;float/str/bool&gt;)             <span class="hljs-comment"># Whole number of any size. Truncates floats.</span>
 &lt;float&gt;    = float(&lt;int/str/bool&gt;)             <span class="hljs-comment"># 64-bit decimal number. Also &lt;float&gt;e±&lt;int&gt;.</span>
-&lt;complex&gt;  = complex(real=<span class="hljs-number">0</span>, imag=<span class="hljs-number">0</span>)           <span class="hljs-comment"># Complex number. Also `&lt;float&gt; ± &lt;float&gt;j`.</span>
+&lt;complex&gt;  = complex(real=<span class="hljs-number">0</span>, imag=<span class="hljs-number">0</span>)           <span class="hljs-comment"># A complex number. Also `&lt;float&gt; ± &lt;float&gt;j`.</span>
 &lt;Fraction&gt; = fractions.Fraction(&lt;int&gt;, &lt;int&gt;)  <span class="hljs-comment"># E.g. `Fraction(1, 2) / 3 == Fraction(1, 6)`.</span>
 &lt;Decimal&gt;  = decimal.Decimal(&lt;str/int/tuple&gt;)  <span class="hljs-comment"># E.g. `Decimal((1, (2, 3), 4)) == -230_000`.</span>
 </code></pre></div>
 
 <ul>
-<li><strong><code class="python hljs"><span class="hljs-string">'int(&lt;str&gt;)'</span></code> and <code class="python hljs"><span class="hljs-string">'float(&lt;str&gt;)'</span></code> raise ValueError on malformed strings.</strong></li>
+<li><strong><code class="python hljs"><span class="hljs-string">'int(&lt;str&gt;)'</span></code> and <code class="python hljs"><span class="hljs-string">'float(&lt;str&gt;)'</span></code> raise ValueError if passed 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(&lt;float&gt;, &lt;float&gt;)'</span></code>.</strong></li>
+<li><strong>Floats can be compared with: <code class="python hljs"><span class="hljs-string">'math.isclose(&lt;float&gt;, &lt;float&gt;, rel_tol=1e-09)'</span></code>.</strong></li>
 <li><strong>Precision of decimal operations is set with: <code class="python hljs"><span class="hljs-string">'decimal.getcontext().prec = &lt;int&gt;'</span></code>.</strong></li>
 <li><strong>Bools can be used anywhere ints can, because bool is a subclass of int: <code class="python hljs"><span class="hljs-string">'True + 1 == 2'</span></code>.</strong></li>
 </ul>
@@ -492,7 +492,7 @@
 &lt;num&gt;   = randint/uniform(a, b)                <span class="hljs-comment"># Returns an int/float inside [a, b].</span>
 &lt;float&gt; = gauss(mean, stdev)                   <span class="hljs-comment"># Also triangular(low, high, mode).</span>
 &lt;el&gt;    = choice(&lt;sequence&gt;)                   <span class="hljs-comment"># Keeps it intact. Also sample(p, n).</span>
-shuffle(&lt;list&gt;)                                <span class="hljs-comment"># Works on any mutable sequence.</span>
+shuffle(&lt;list&gt;)                                <span class="hljs-comment"># Works on all mutable sequences.</span>
 </code></pre>
 <div><h3 id="hexadecimalnumbers">Hexadecimal Numbers</h3><pre><code class="python language-python hljs">&lt;int&gt; = <span class="hljs-number">0x</span>&lt;hex&gt;                                <span class="hljs-comment"># E.g. `0xFF == 255`. Also 0b&lt;bin&gt;.</span>
 &lt;int&gt; = int(<span class="hljs-string">'±&lt;hex&gt;'</span>, <span class="hljs-number">16</span>)                      <span class="hljs-comment"># Also int('±0x&lt;hex&gt;/±0b&lt;bin&gt;', 0).</span>
@@ -502,8 +502,8 @@
 <div><h3 id="bitwiseoperators">Bitwise Operators</h3><pre><code class="python language-python hljs">&lt;int&gt; = &lt;int&gt; &amp; &lt;int&gt;                          <span class="hljs-comment"># E.g. `0b1100 &amp; 0b1010 == 0b1000`.</span>
 &lt;int&gt; = &lt;int&gt; | &lt;int&gt;                          <span class="hljs-comment"># E.g. `0b1100 | 0b1010 == 0b1110`.</span>
 &lt;int&gt; = &lt;int&gt; ^ &lt;int&gt;                          <span class="hljs-comment"># E.g. `0b1100 ^ 0b1010 == 0b0110`.</span>
-&lt;int&gt; = &lt;int&gt; &lt;&lt; n_bits                        <span class="hljs-comment"># Left shift. Use &gt;&gt; for right.</span>
-&lt;int&gt; = ~&lt;int&gt;                                 <span class="hljs-comment"># Not. Same as `-&lt;int&gt; - 1`.</span>
+&lt;int&gt; = &lt;int&gt; &lt;&lt; n_bits                        <span class="hljs-comment"># E.g. `0b1100 &lt;&lt; 4 == 0b1100_0000`.</span>
+&lt;int&gt; = ~&lt;int&gt;                                 <span class="hljs-comment"># E.g. `~0b1 == -0b10 == -(0b1+1)`.</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
@@ -536,8 +536,8 @@
 &lt;TD&gt; = 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"># Also: `minutes=0, seconds=0, microseconds=0`.</span>
 </code></pre>
 <ul>
-<li><strong>Times and datetimes that have defined timezone are called aware and ones that don't, naive. If 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 for one hour.</strong></li>
+<li><strong>Times and datetimes that have defined timezone are called aware and ones that don't, naive. 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 (&lt; 86 400) and microseconds (&lt; 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 all seconds.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'&lt;D/DT&gt;.weekday()'</span></code> to get the day of the week as an integer, with Monday being 0.</strong></li>
 </ul>
@@ -548,8 +548,8 @@
 <ul>
 <li><strong>To extract time use <code class="python hljs"><span class="hljs-string">'&lt;DTn&gt;.time()'</span></code>, <code class="python hljs"><span class="hljs-string">'&lt;DTa&gt;.time()'</span></code> or <code class="python hljs"><span class="hljs-string">'&lt;DTa&gt;.timetz()'</span></code>.</strong></li>
 </ul>
-<div><h3 id="timezone">Timezone</h3><pre><code class="python language-python apache hljs">&lt;tzinfo&gt; = timezone.utc                     <span class="hljs-comment"># London without daylight saving time (DST).</span>
-&lt;tzinfo&gt; = timezone(&lt;timedelta&gt;)            <span class="hljs-comment"># Timezone with fixed offset from UTC.</span>
+<div><h3 id="timezones">Timezones</h3><pre><code class="python language-python apache hljs">&lt;tzinfo&gt; = timezone.utc                     <span class="hljs-comment"># Coordinated universal time (UK without DST).</span>
+&lt;tzinfo&gt; = timezone(&lt;timedelta&gt;)            <span class="hljs-comment"># Timezone with fixed offset from universal time.</span>
 &lt;tzinfo&gt; = dateutil.tz.tzlocal()            <span class="hljs-comment"># Local timezone with dynamic offset from UTC.</span>
 &lt;tzinfo&gt; = zoneinfo.ZoneInfo(<span class="hljs-string">'&lt;iana_key&gt;'</span>)  <span class="hljs-comment"># 'Continent/City_Name' zone with dynamic offset.</span>
 &lt;DTa&gt;    = &lt;DT&gt;.astimezone([&lt;tzinfo&gt;])      <span class="hljs-comment"># Converts DT to the passed or local fixed zone.</span>
@@ -573,7 +573,7 @@
 </ul>
 <div><h3 id="decode">Decode</h3><pre><code class="python language-python hljs">&lt;str&gt;    = &lt;D/T/DT&gt;.isoformat(sep=<span class="hljs-string">'T'</span>)      <span class="hljs-comment"># Also `timespec='auto/hours/minutes/seconds/…'`.</span>
 &lt;str&gt;    = &lt;D/T/DT&gt;.strftime(<span class="hljs-string">'&lt;format&gt;'</span>)    <span class="hljs-comment"># Custom string representation of the object.</span>
-&lt;int&gt;    = &lt;D/DT&gt;.toordinal()               <span class="hljs-comment"># Days since Gregorian NYE 1, ignoring time and tz.</span>
+&lt;int&gt;    = &lt;D/DT&gt;.toordinal()               <span class="hljs-comment"># Days since NYE 1, ignoring time and timezone.</span>
 &lt;float&gt;  = &lt;DTn&gt;.timestamp()                <span class="hljs-comment"># Seconds since the Epoch, from local naive DT.</span>
 &lt;float&gt;  = &lt;DTa&gt;.timestamp()                <span class="hljs-comment"># Seconds since the Epoch, from aware datetime.</span>
 </code></pre></div>
@@ -590,7 +590,7 @@
 <div><h3 id="arithmetics">Arithmetics</h3><pre><code class="python language-python apache hljs">&lt;bool&gt;   = &lt;D/T/DTn&gt; &gt; &lt;D/T/DTn&gt;            <span class="hljs-comment"># Ignores time jumps (fold attribute). Also ==.</span>
 &lt;bool&gt;   = &lt;DTa&gt;     &gt; &lt;DTa&gt;                <span class="hljs-comment"># Ignores time jumps if they share tzinfo object.</span>
 &lt;TD&gt;     = &lt;D/DTn&gt;   - &lt;D/DTn&gt;              <span class="hljs-comment"># Ignores jumps. Convert to UTC for actual delta.</span>
-&lt;TD&gt;     = &lt;DTa&gt;     - &lt;DTa&gt;                <span class="hljs-comment"># Ignores jumps if they share tzinfo object.</span>
+&lt;TD&gt;     = &lt;DTa&gt;     - &lt;DTa&gt;                <span class="hljs-comment"># Ignores jumps if they share the tzinfo object.</span>
 &lt;D/DT&gt;   = &lt;D/DT&gt;    ± &lt;TD&gt;                 <span class="hljs-comment"># Returned datetime can fall into missing hour.</span>
 &lt;TD&gt;     = &lt;TD&gt;      * &lt;float&gt;              <span class="hljs-comment"># Also `&lt;TD&gt; = abs(&lt;TD&gt;)`, `&lt;TD&gt; = &lt;TD&gt; ± &lt;TD&gt;`.</span>
 &lt;float&gt;  = &lt;TD&gt;      / &lt;TD&gt;                 <span class="hljs-comment"># Also `(&lt;int&gt;, &lt;TD&gt;) = divmod(&lt;TD&gt;, &lt;TD&gt;)`.</span>
@@ -676,8 +676,8 @@
 <pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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-number">3</span>)]      <span class="hljs-comment"># `any([0, '', [], None]) == False`</span>
 [<span class="hljs-string">'zero'</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
 </code></pre>
-<div><h3 id="andor">And, Or</h3><pre><code class="python language-python hljs">&lt;obj&gt; = &lt;exp&gt; <span class="hljs-keyword">and</span> &lt;exp&gt; [<span class="hljs-keyword">and</span> ...]                   <span class="hljs-comment"># Returns first false or last operand.</span>
-&lt;obj&gt; = &lt;exp&gt; <span class="hljs-keyword">or</span> &lt;exp&gt; [<span class="hljs-keyword">or</span> ...]                     <span class="hljs-comment"># Returns first true or last operand.</span>
+<div><h3 id="andor">And, Or</h3><pre><code class="python language-python hljs">&lt;obj&gt; = &lt;exp&gt; <span class="hljs-keyword">and</span> &lt;exp&gt; [<span class="hljs-keyword">and</span> ...]                   <span class="hljs-comment"># Returns first false or last object.</span>
+&lt;obj&gt; = &lt;exp&gt; <span class="hljs-keyword">or</span> &lt;exp&gt; [<span class="hljs-keyword">or</span> ...]                     <span class="hljs-comment"># Returns first true or last object.</span>
 </code></pre></div>
 
 <div><h3 id="walrusoperator">Walrus Operator</h3><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>[i <span class="hljs-keyword">for</span> a <span class="hljs-keyword">in</span> <span class="hljs-string">'0123'</span> <span class="hljs-keyword">if</span> (i := int(a)) &gt; <span class="hljs-number">0</span>]        <span class="hljs-comment"># Assigns to variable mid-sentence.</span>
@@ -2938,7 +2938,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>July 20, 2025</aside>
+    <aside>July 23, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From d044e60db21e9611a61aa159a0faacd0da12aa92 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 23 Jul 2025 18:19:54 +0200
Subject: [PATCH 165/186] Dictionary, String, Numbers

---
 README.md  | 6 +++---
 index.html | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index e54bfdd4e..94b156443 100644
--- a/README.md
+++ b/README.md
@@ -104,7 +104,7 @@ value  = <dict>.setdefault(key, default=None)   # Returns and writes default if
 <dict>.update(<dict>)                           # Adds items. Replaces ones with matching keys.
 value = <dict>.pop(key)                         # Removes item or raises KeyError if missing.
 {k for k, v in <dict>.items() if v == value}    # Returns set of keys that point to the value.
-{k: v for k, v in <dict>.items() if k in keys}  # Filters the dictionary by keys.
+{k: v for k, v in <dict>.items() if k in keys}  # Filters the dictionary by specified keys.
 ```
 
 ### Counter
@@ -350,7 +350,7 @@ String
 <bool> = <str>.isnumeric()                   # Checks for [¼½¾…], [零〇一…] and isdigit().
 <bool> = <str>.isalnum()                     # Checks for [a-zA-Z…] and isnumeric().
 <bool> = <str>.isprintable()                 # Checks for [ !#$%…] and isalnum().
-<bool> = <str>.isspace()                     # Checks for [ \t\n\r\f\v\x1c-\x1f\x85\xa0…].
+<bool> = <str>.isspace()                     # Checks for [ \t\n\r\f\v\x1c-\x1f\x85…].
 ```
 
 
@@ -554,7 +554,7 @@ shuffle(<list>)                                # Works on all mutable sequences.
 <int> = <int> & <int>                          # E.g. `0b1100 & 0b1010 == 0b1000`.
 <int> = <int> | <int>                          # E.g. `0b1100 | 0b1010 == 0b1110`.
 <int> = <int> ^ <int>                          # E.g. `0b1100 ^ 0b1010 == 0b0110`.
-<int> = <int> << n_bits                        # E.g. `0b1100 << 4 == 0b1100_0000`.
+<int> = <int> << n_bits                        # E.g. `0b1111 << 4 == 0b11110000`.
 <int> = ~<int>                                 # E.g. `~0b1 == -0b10 == -(0b1+1)`.
 ```
 
diff --git a/index.html b/index.html
index e12914352..1539f57d5 100644
--- a/index.html
+++ b/index.html
@@ -165,7 +165,7 @@
 <pre><code class="python language-python hljs">&lt;dict&gt;.update(&lt;dict&gt;)                           <span class="hljs-comment"># Adds items. Replaces ones with matching keys.</span>
 value = &lt;dict&gt;.pop(key)                         <span class="hljs-comment"># Removes item or raises KeyError if missing.</span>
 {k <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> &lt;dict&gt;.items() <span class="hljs-keyword">if</span> v == value}    <span class="hljs-comment"># Returns set of keys that point to the value.</span>
-{k: v <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> &lt;dict&gt;.items() <span class="hljs-keyword">if</span> k <span class="hljs-keyword">in</span> keys}  <span class="hljs-comment"># Filters the dictionary by keys.</span>
+{k: v <span class="hljs-keyword">for</span> k, v <span class="hljs-keyword">in</span> &lt;dict&gt;.items() <span class="hljs-keyword">if</span> k <span class="hljs-keyword">in</span> keys}  <span class="hljs-comment"># Filters the dictionary by specified keys.</span>
 </code></pre>
 <div><h3 id="counter">Counter</h3><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> Counter
 <span class="hljs-meta">&gt;&gt;&gt; </span>counter = Counter([<span class="hljs-string">'blue'</span>, <span class="hljs-string">'blue'</span>, <span class="hljs-string">'blue'</span>, <span class="hljs-string">'red'</span>, <span class="hljs-string">'red'</span>])
@@ -335,7 +335,7 @@
 &lt;bool&gt; = &lt;str&gt;.isnumeric()                   <span class="hljs-comment"># Checks for [¼½¾…], [零〇一…] and isdigit().</span>
 &lt;bool&gt; = &lt;str&gt;.isalnum()                     <span class="hljs-comment"># Checks for [a-zA-Z…] and isnumeric().</span>
 &lt;bool&gt; = &lt;str&gt;.isprintable()                 <span class="hljs-comment"># Checks for [ !#$%…] and isalnum().</span>
-&lt;bool&gt; = &lt;str&gt;.isspace()                     <span class="hljs-comment"># Checks for [ \t\n\r\f\v\x1c-\x1f\x85\xa0…].</span>
+&lt;bool&gt; = &lt;str&gt;.isspace()                     <span class="hljs-comment"># Checks for [ \t\n\r\f\v\x1c-\x1f\x85…].</span>
 </code></pre></div>
 
 <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
@@ -502,7 +502,7 @@
 <div><h3 id="bitwiseoperators">Bitwise Operators</h3><pre><code class="python language-python hljs">&lt;int&gt; = &lt;int&gt; &amp; &lt;int&gt;                          <span class="hljs-comment"># E.g. `0b1100 &amp; 0b1010 == 0b1000`.</span>
 &lt;int&gt; = &lt;int&gt; | &lt;int&gt;                          <span class="hljs-comment"># E.g. `0b1100 | 0b1010 == 0b1110`.</span>
 &lt;int&gt; = &lt;int&gt; ^ &lt;int&gt;                          <span class="hljs-comment"># E.g. `0b1100 ^ 0b1010 == 0b0110`.</span>
-&lt;int&gt; = &lt;int&gt; &lt;&lt; n_bits                        <span class="hljs-comment"># E.g. `0b1100 &lt;&lt; 4 == 0b1100_0000`.</span>
+&lt;int&gt; = &lt;int&gt; &lt;&lt; n_bits                        <span class="hljs-comment"># E.g. `0b1111 &lt;&lt; 4 == 0b11110000`.</span>
 &lt;int&gt; = ~&lt;int&gt;                                 <span class="hljs-comment"># E.g. `~0b1 == -0b10 == -(0b1+1)`.</span>
 </code></pre></div>
 

From 00f77280e2f39f413e392acb975c9c34e6f8d46a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Fri, 25 Jul 2025 18:15:34 +0200
Subject: [PATCH 166/186] Decorator, Duck types, Enum, Exceptions

---
 README.md           | 61 ++++++++++++++++++++---------------------
 index.html          | 67 ++++++++++++++++++++++-----------------------
 parse.js            | 12 ++++----
 pdf/remove_links.py |  2 +-
 4 files changed, 69 insertions(+), 73 deletions(-)

diff --git a/README.md b/README.md
index 94b156443..fce8d121b 100644
--- a/README.md
+++ b/README.md
@@ -640,9 +640,9 @@ import zoneinfo, dateutil.tz
 
 ### Decode
 ```python
-<str>    = <D/T/DT>.isoformat(sep='T')      # Also `timespec='auto/hours/minutes/seconds/…'`.
+<str>    = <D/T/DT>.isoformat(sep='T')      # Also `timespec='auto/hours/minutes/seconds…'`.
 <str>    = <D/T/DT>.strftime('<format>')    # Custom string representation of the object.
-<int>    = <D/DT>.toordinal()               # Days since NYE 1, ignoring time and timezone.
+<int>    = <D/DT>.toordinal()               # Days since NYE 1. Ignores DT's time and zone.
 <float>  = <DTn>.timestamp()                # Seconds since the Epoch, from local naive DT.
 <float>  = <DTa>.timestamp()                # Seconds since the Epoch, from aware datetime.
 ```
@@ -794,7 +794,7 @@ from functools import reduce
 
 ### Walrus Operator
 ```python
->>> [i for a in '0123' if (i := int(a)) > 0]        # Assigns to variable mid-sentence.
+>>> [i for ch in '0123' if (i := int(ch)) > 0]      # Assigns to variable mid-sentence.
 [1, 2, 3]
 ```
 
@@ -885,8 +885,7 @@ def get_counter():
 
 Decorator
 ---------
-* **A decorator takes a function, adds some functionality and returns it.**
-* **It can be any [callable](#callable), but is usually implemented as a function that returns a [closure](#closure).**
+**A decorator takes a function, adds some functionality and returns it. It can be any [callable](#callable), but is usually implemented as a function that returns a [closure](#closure).**
 
 ```python
 @decorator_name
@@ -1094,7 +1093,7 @@ Duck Types
 **A duck type is an implicit type that prescribes a set of special methods. Any object that has those methods defined is considered a member of that duck type.**
 
 ### Comparable
-* **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`. That means all user-defined objects compare not equal by default, because id() returns object's unique identification number (its memory address).**
+* **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`. That means all user-defined objects compare not equal by default (because id() returns object's memory address that is unique during its lifetime).**
 * **Only the left side object has eq() method called, unless it returns NotImplemented, in which case the right object is consulted. False is returned if both return NotImplemented.**
 * **Ne() automatically works on any object that has eq() defined.**
 
@@ -1199,8 +1198,8 @@ class Counter:
 
 ### Context Manager
 * **With statements only work on objects that have enter() and exit() special methods.**
-* **Enter() should lock the resources and optionally return an object.**
-* **Exit() should release the resources (for example close a file).**
+* **Enter() should lock the resources and optionally return an object (file, lock, etc.).**
+* **Exit() should release the resources (for example close a file, release a lock, etc.).**
 * **Any exception that happens inside the with block is passed to the exit() method.**
 * **The exit() method can suppress the exception by returning a true value.**
 ```python
@@ -1332,8 +1331,8 @@ from enum import Enum, auto
 ```python
 class <enum_name>(Enum):
     <member_name> = auto()              # Increment of the last numeric value or 1.
-    <member_name> = <value>             # Values don't have to be hashable.
-    <member_name> = <el_1>, <el_2>      # Values can be collections (this is a tuple).
+    <member_name> = <value>             # Values don't have to be hashable or unique.
+    <member_name> = <el_1>, <el_2>      # Values can be collections, like this tuple.
 ```
 * **Methods receive the member they were called on as the 'self' argument.**
 * **Accessing a member named after a reserved keyword causes SyntaxError.**
@@ -1342,20 +1341,20 @@ class <enum_name>(Enum):
 <member> = <enum>.<member_name>         # Returns a member. Raises AttributeError.
 <member> = <enum>['<member_name>']      # Returns a member. Raises KeyError.
 <member> = <enum>(<value>)              # Returns a member. Raises ValueError.
-<str>    = <member>.name                # Returns member's name.
-<obj>    = <member>.value               # Returns member's value.
+<str>    = <member>.name                # Returns the member's name.
+<obj>    = <member>.value               # Returns the member's value.
 ```
 
 ```python
-<list>   = list(<enum>)                 # Returns enum's members.
-<list>   = [a.name for a in <enum>]     # Returns enum's member names.
-<list>   = [a.value for a in <enum>]    # Returns enum's member values.
+<list>   = list(<enum>)                 # Returns a list of enum's members.
+<list>   = <enum>._member_names_        # Returns a list of member names.
+<list>   = [m.value for m in <enum>]    # Returns a list of member values.
 ```
 
 ```python
-<enum>   = type(<member>)               # Returns member's enum.
-<iter>   = itertools.cycle(<enum>)      # Returns endless iterator of members.
-<member> = random.choice(list(<enum>))  # Returns a random member.
+<enum>   = type(<member>)               # Returns an enum. Also <memb>.__class__.
+<iter>   = itertools.cycle(<enum>)      # Returns an endless iterator of members.
+<member> = random.choice(list(<enum>))  # Randomly selects one of the members.
 ```
 
 ### Inline
@@ -1397,8 +1396,8 @@ finally:
 ```
 * **Code inside the `'else'` block will only be executed if `'try'` block had no exceptions.**
 * **Code inside the `'finally'` block will always be executed (unless a signal is received).**
-* **All variables that are initialized in executed blocks are also visible in all subsequent blocks, as well as outside the try statement (only function block delimits scope).**
-* **To catch signals use `'signal.signal(signal_number, <func>)'`.**
+* **All variables that are initialized in executed blocks are also visible in all subsequent blocks, as well as outside the try statement (only a function block delimits scope).**
+* **To catch signals use `'signal.signal(signal_number, handler_function)'`.**
 
 ### Catching Exceptions
 ```python
@@ -1407,10 +1406,10 @@ except <exception> as <name>: ...
 except (<exception>, [...]): ...
 except (<exception>, [...]) as <name>: ...
 ```
-* **Also catches subclasses of the exception.**
-* **Use `'traceback.print_exc()'` to print the full error message to stderr.**
-* **Use `'print(<name>)'` to print just the cause of the exception (its arguments).**
-* **Use `'logging.exception(<str>)'` to log the passed message, followed by the full error message of the caught exception. For details see [Logging](#logging).**
+* **Also catches subclasses, e.g. `'IndexError'` is caught by `'except LookupError:'`.**
+* **Use `'traceback.print_exc()'` to print the full error message to standard error stream.**
+* **Use `'print(<name>)'` to print just the cause of the exception (i.e. its arguments).**
+* **Use `'logging.exception(<str>)'` to log the passed message, followed by the full error message of the caught exception. For details about setting up the logger see [Logging](#logging).**
 * **Use `'sys.exc_info()'` to get exception type, object, and traceback of caught exception.**
 
 ### Raising Exceptions
@@ -1433,7 +1432,7 @@ 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      = linecache.getline(filename, <name>.__traceback__.tb_lineno)
+line_str  = linecache.getline(filename, <name>.__traceback__.tb_lineno)
 trace_str = ''.join(traceback.format_tb(<name>.__traceback__))
 error_msg = ''.join(traceback.format_exception(type(<name>), <name>, <name>.__traceback__))
 ```
@@ -1441,25 +1440,25 @@ error_msg = ''.join(traceback.format_exception(type(<name>), <name>, <name>.__tr
 ### Built-in Exceptions
 ```text
 BaseException
- +-- SystemExit                   # Raised by the sys.exit() function.
- +-- KeyboardInterrupt            # Raised when the user hits the interrupt key (ctrl-c).
+ +-- SystemExit                   # Raised by the sys.exit() function (see #Exit for details).
+ +-- KeyboardInterrupt            # Raised when the user hits the interrupt key (control-c).
  +-- Exception                    # User-defined exceptions should be derived from this class.
       +-- ArithmeticError         # Base class for arithmetic errors such as ZeroDivisionError.
       +-- AssertionError          # Raised by `assert <exp>` if expression returns false value.
       +-- AttributeError          # Raised when object doesn't have requested attribute/method.
       +-- EOFError                # Raised by input() when it hits an end-of-file condition.
       +-- LookupError             # Base class for errors when a collection can't find an item.
-      |    +-- IndexError         # Raised when a sequence index is out of range.
+      |    +-- IndexError         # Raised when index of a sequence (list/str) is out of range.
       |    +-- KeyError           # Raised when a dictionary key or set element is missing.
       +-- MemoryError             # Out of memory. May be too late to start deleting variables.
       +-- NameError               # Raised when nonexistent name (variable/func/class) is used.
       |    +-- UnboundLocalError  # Raised when local name is used before it's being defined.
-      +-- OSError                 # Errors such as FileExistsError/TimeoutError (see #Open).
-      |    +-- ConnectionError    # Errors such as BrokenPipeError/ConnectionAbortedError.
+      +-- OSError                 # Errors such as FileExistsError, TimeoutError (see #Open).
+      |    +-- ConnectionError    # Errors such as BrokenPipeError and ConnectionAbortedError.
       +-- RuntimeError            # Raised by errors that don't fall into other categories.
       |    +-- NotImplementedEr…  # Can be raised by abstract methods or by unfinished code.
       |    +-- RecursionError     # Raised if max recursion depth is exceeded (3k by default).
-      +-- StopIteration           # Raised when an empty iterator is passed to next().
+      +-- StopIteration           # Raised when exhausted (empty) iterator is passed to next().
       +-- TypeError               # When an argument of the wrong type is passed to function.
       +-- ValueError              # When argument has the right type but inappropriate value.
 ```
diff --git a/index.html b/index.html
index 1539f57d5..b45943c7e 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>July 23, 2025</aside>
+    <aside>July 25, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -571,9 +571,9 @@
 <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">&lt;str&gt;    = &lt;D/T/DT&gt;.isoformat(sep=<span class="hljs-string">'T'</span>)      <span class="hljs-comment"># Also `timespec='auto/hours/minutes/seconds/…'`.</span>
+<div><h3 id="decode">Decode</h3><pre><code class="python language-python hljs">&lt;str&gt;    = &lt;D/T/DT&gt;.isoformat(sep=<span class="hljs-string">'T'</span>)      <span class="hljs-comment"># Also `timespec='auto/hours/minutes/seconds…'`.</span>
 &lt;str&gt;    = &lt;D/T/DT&gt;.strftime(<span class="hljs-string">'&lt;format&gt;'</span>)    <span class="hljs-comment"># Custom string representation of the object.</span>
-&lt;int&gt;    = &lt;D/DT&gt;.toordinal()               <span class="hljs-comment"># Days since NYE 1, ignoring time and timezone.</span>
+&lt;int&gt;    = &lt;D/DT&gt;.toordinal()               <span class="hljs-comment"># Days since NYE 1. Ignores DT's time and zone.</span>
 &lt;float&gt;  = &lt;DTn&gt;.timestamp()                <span class="hljs-comment"># Seconds since the Epoch, from local naive DT.</span>
 &lt;float&gt;  = &lt;DTa&gt;.timestamp()                <span class="hljs-comment"># Seconds since the Epoch, from aware datetime.</span>
 </code></pre></div>
@@ -680,7 +680,7 @@
 &lt;obj&gt; = &lt;exp&gt; <span class="hljs-keyword">or</span> &lt;exp&gt; [<span class="hljs-keyword">or</span> ...]                     <span class="hljs-comment"># Returns first true or last object.</span>
 </code></pre></div>
 
-<div><h3 id="walrusoperator">Walrus Operator</h3><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>[i <span class="hljs-keyword">for</span> a <span class="hljs-keyword">in</span> <span class="hljs-string">'0123'</span> <span class="hljs-keyword">if</span> (i := int(a)) &gt; <span class="hljs-number">0</span>]        <span class="hljs-comment"># Assigns to variable mid-sentence.</span>
+<div><h3 id="walrusoperator">Walrus Operator</h3><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </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)) &gt; <span class="hljs-number">0</span>]      <span class="hljs-comment"># Assigns to variable mid-sentence.</span>
 [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
 </code></pre></div>
 
@@ -751,10 +751,7 @@
 <span class="hljs-meta">&gt;&gt;&gt; </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><ul>
-<li><strong>A decorator takes a function, adds some functionality and returns it.</strong></li>
-<li><strong>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></li>
-</ul><pre><code class="python language-python hljs"><span class="hljs-meta">@decorator_name</span>
+<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">function_that_gets_passed_to_decorator</span><span class="hljs-params">()</span>:</span>
     ...
 </code></pre></div>
@@ -929,7 +926,7 @@
 </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 has those methods defined 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 unique identification number (its memory address).</strong></li>
+<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 unique during its lifetime).</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. False is returned if both return NotImplemented.</strong></li>
 <li><strong>Ne() 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>
@@ -1030,8 +1027,8 @@
 </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.</strong></li>
-<li><strong>Exit() should release the resources (for example close a file).</strong></li>
+<li><strong>Enter() should lock the resources and optionally return an object (file, lock, etc.).</strong></li>
+<li><strong>Exit() should release the resources (for example close a file, release a lock, etc.).</strong></li>
 <li><strong>Any exception that happens inside the with block is passed to the exit() method.</strong></li>
 <li><strong>The exit() method can suppress the exception by returning a true value.</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>
@@ -1152,8 +1149,8 @@
 
 <pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">enum_name</span>&gt;<span class="hljs-params">(Enum)</span>:</span>
     &lt;member_name&gt; = auto()              <span class="hljs-comment"># Increment of the last numeric value or 1.</span>
-    &lt;member_name&gt; = &lt;value&gt;             <span class="hljs-comment"># Values don't have to be hashable.</span>
-    &lt;member_name&gt; = &lt;el_1&gt;, &lt;el_2&gt;      <span class="hljs-comment"># Values can be collections (this is a tuple).</span>
+    &lt;member_name&gt; = &lt;value&gt;             <span class="hljs-comment"># Values don't have to be hashable or unique.</span>
+    &lt;member_name&gt; = &lt;el_1&gt;, &lt;el_2&gt;      <span class="hljs-comment"># Values can be collections, like this tuple.</span>
 </code></pre>
 <ul>
 <li><strong>Methods receive the member they were called on as the 'self' argument.</strong></li>
@@ -1162,16 +1159,16 @@
 <pre><code class="python language-python hljs">&lt;member&gt; = &lt;enum&gt;.&lt;member_name&gt;         <span class="hljs-comment"># Returns a member. Raises AttributeError.</span>
 &lt;member&gt; = &lt;enum&gt;[<span class="hljs-string">'&lt;member_name&gt;'</span>]      <span class="hljs-comment"># Returns a member. Raises KeyError.</span>
 &lt;member&gt; = &lt;enum&gt;(&lt;value&gt;)              <span class="hljs-comment"># Returns a member. Raises ValueError.</span>
-&lt;str&gt;    = &lt;member&gt;.name                <span class="hljs-comment"># Returns member's name.</span>
-&lt;obj&gt;    = &lt;member&gt;.value               <span class="hljs-comment"># Returns member's value.</span>
+&lt;str&gt;    = &lt;member&gt;.name                <span class="hljs-comment"># Returns the member's name.</span>
+&lt;obj&gt;    = &lt;member&gt;.value               <span class="hljs-comment"># Returns the member's value.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;list&gt;   = list(&lt;enum&gt;)                 <span class="hljs-comment"># Returns enum's members.</span>
-&lt;list&gt;   = [a.name <span class="hljs-keyword">for</span> a <span class="hljs-keyword">in</span> &lt;enum&gt;]     <span class="hljs-comment"># Returns enum's member names.</span>
-&lt;list&gt;   = [a.value <span class="hljs-keyword">for</span> a <span class="hljs-keyword">in</span> &lt;enum&gt;]    <span class="hljs-comment"># Returns enum's member values.</span>
+<pre><code class="python language-python hljs">&lt;list&gt;   = list(&lt;enum&gt;)                 <span class="hljs-comment"># Returns a list of enum's members.</span>
+&lt;list&gt;   = &lt;enum&gt;._member_names_        <span class="hljs-comment"># Returns a list of member names.</span>
+&lt;list&gt;   = [m.value <span class="hljs-keyword">for</span> m <span class="hljs-keyword">in</span> &lt;enum&gt;]    <span class="hljs-comment"># Returns a list of member values.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;enum&gt;   = type(&lt;member&gt;)               <span class="hljs-comment"># Returns member's enum.</span>
-&lt;iter&gt;   = itertools.cycle(&lt;enum&gt;)      <span class="hljs-comment"># Returns endless iterator of members.</span>
-&lt;member&gt; = random.choice(list(&lt;enum&gt;))  <span class="hljs-comment"># Returns a random member.</span>
+<pre><code class="python language-python hljs">&lt;enum&gt;   = type(&lt;member&gt;)               <span class="hljs-comment"># Returns an enum. Also &lt;memb&gt;.__class__.</span>
+&lt;iter&gt;   = itertools.cycle(&lt;enum&gt;)      <span class="hljs-comment"># Returns an endless iterator of members.</span>
+&lt;member&gt; = random.choice(list(&lt;enum&gt;))  <span class="hljs-comment"># Randomly selects one of the members.</span>
 </code></pre>
 <div><h3 id="inline-1">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>])
@@ -1204,8 +1201,8 @@
 <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 function block delimits scope).</strong></li>
-<li><strong>To catch signals use <code class="python hljs"><span class="hljs-string">'signal.signal(signal_number, &lt;func&gt;)'</span></code>.</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 a function block delimits scope).</strong></li>
+<li><strong>To catch signals use <code class="python hljs"><span class="hljs-string">'signal.signal(signal_number, 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> &lt;exception&gt;: ...
 <span class="hljs-keyword">except</span> &lt;exception&gt; <span class="hljs-keyword">as</span> &lt;name&gt;: ...
@@ -1214,10 +1211,10 @@
 </code></pre></div>
 
 <ul>
-<li><strong>Also catches subclasses of the exception.</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 stderr.</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'print(&lt;name&gt;)'</span></code> to print just the cause of the exception (its arguments).</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'logging.exception(&lt;str&gt;)'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">Logging</a>.</strong></li>
+<li><strong>Also catches subclasses, e.g. <code class="python hljs"><span class="hljs-string">'IndexError'</span></code> is caught by <code class="python hljs"><span class="hljs-string">'except LookupError:'</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(&lt;name&gt;)'</span></code> to print just the cause of the exception (i.e. its arguments).</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'logging.exception(&lt;str&gt;)'</span></code> to log the passed message, followed by the full error message of the caught exception. For details about setting up the logger see <a href="#logging">Logging</a>.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'sys.exc_info()'</span></code> to get exception type, object, and traceback of caught exception.</strong></li>
 </ul>
 <div><h3 id="raisingexceptions">Raising Exceptions</h3><pre><code class="python language-python hljs"><span class="hljs-keyword">raise</span> &lt;exception&gt;
@@ -1234,31 +1231,31 @@
 exc_type  = &lt;name&gt;.__class__
 filename  = &lt;name&gt;.__traceback__.tb_frame.f_code.co_filename
 func_name = &lt;name&gt;.__traceback__.tb_frame.f_code.co_name
-line      = linecache.getline(filename, &lt;name&gt;.__traceback__.tb_lineno)
+line_str  = linecache.getline(filename, &lt;name&gt;.__traceback__.tb_lineno)
 trace_str = <span class="hljs-string">''</span>.join(traceback.format_tb(&lt;name&gt;.__traceback__))
 error_msg = <span class="hljs-string">''</span>.join(traceback.format_exception(type(&lt;name&gt;), &lt;name&gt;, &lt;name&gt;.__traceback__))
 </code></pre></div>
 
 <div><h3 id="builtinexceptions">Built-in Exceptions</h3><pre><code class="text language-text">BaseException
- ├── SystemExit                   <span class="hljs-comment"># Raised by the sys.exit() function.</span>
- ├── KeyboardInterrupt            <span class="hljs-comment"># Raised when the user hits the interrupt key (ctrl-c).</span>
+ ├── SystemExit                   <span class="hljs-comment"># Raised by the sys.exit() function (see #Exit for details).</span>
+ ├── KeyboardInterrupt            <span class="hljs-comment"># Raised when the user hits the interrupt key (control-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 &lt;exp&gt;` 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 a sequence index is out of range.</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 key or 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 local name is used before it's being defined.</span>
-      ├── OSError                 <span class="hljs-comment"># Errors such as FileExistsError/TimeoutError (see #Open).</span>
-      │    └── ConnectionError    <span class="hljs-comment"># Errors such as BrokenPipeError/ConnectionAbortedError.</span>
+      ├── OSError                 <span class="hljs-comment"># Errors such as FileExistsError, TimeoutError (see #Open).</span>
+      │    └── ConnectionError    <span class="hljs-comment"># Errors such as BrokenPipeError and ConnectionAbortedError.</span>
       ├── RuntimeError            <span class="hljs-comment"># Raised by errors that don't fall into other categories.</span>
       │    ├── NotImplementedEr…  <span class="hljs-comment"># Can be raised by abstract methods or by 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 an empty iterator is passed to next().</span>
+      ├── StopIteration           <span class="hljs-comment"># Raised when exhausted (empty) iterator is passed to next().</span>
       ├── TypeError               <span class="hljs-comment"># When an argument of the wrong type is passed to function.</span>
       └── ValueError              <span class="hljs-comment"># When argument has the right type but inappropriate value.</span>
 </code></pre></div>
@@ -2938,7 +2935,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>July 23, 2025</aside>
+    <aside>July 25, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 42cf8c6d7..8a19d0928 100755
--- a/parse.js
+++ b/parse.js
@@ -460,25 +460,25 @@ const DIAGRAM_7_A =
 
 const DIAGRAM_7_B =
   "BaseException\n" +
-  " ├── SystemExit                   <span class='hljs-comment'># Raised by the sys.exit() function.</span>\n" +
-  " ├── KeyboardInterrupt            <span class='hljs-comment'># Raised when the user hits the interrupt key (ctrl-c).</span>\n" +
+  " ├── SystemExit                   <span class='hljs-comment'># Raised by the sys.exit() function (see #Exit for details).</span>\n" +
+  " ├── KeyboardInterrupt            <span class='hljs-comment'># Raised when the user hits the interrupt key (control-c).</span>\n" +
   " └── Exception                    <span class='hljs-comment'># User-defined exceptions should be derived from this class.</span>\n" +
   "      ├── ArithmeticError         <span class='hljs-comment'># Base class for arithmetic errors such as ZeroDivisionError.</span>\n" +
   "      ├── AssertionError          <span class='hljs-comment'># Raised by `assert &lt;exp&gt;` if expression returns false value.</span>\n" +
   "      ├── AttributeError          <span class='hljs-comment'># Raised when object doesn't have requested attribute/method.</span>\n" +
   "      ├── EOFError                <span class='hljs-comment'># Raised by input() when it hits an end-of-file condition.</span>\n" +
   "      ├── LookupError             <span class='hljs-comment'># Base class for errors when a collection can't find an item.</span>\n" +
-  "      │    ├── IndexError         <span class='hljs-comment'># Raised when a sequence index is out of range.</span>\n" +
+  "      │    ├── IndexError         <span class='hljs-comment'># Raised when index of a sequence (list/str) is out of range.</span>\n" +
   "      │    └── KeyError           <span class='hljs-comment'># Raised when a dictionary key or set element is missing.</span>\n" +
   "      ├── MemoryError             <span class='hljs-comment'># Out of memory. May be too late to start deleting variables.</span>\n" +
   "      ├── NameError               <span class='hljs-comment'># Raised when nonexistent name (variable/func/class) is used.</span>\n" +
   "      │    └── UnboundLocalError  <span class='hljs-comment'># Raised when local name is used before it's being defined.</span>\n" +
-  "      ├── OSError                 <span class='hljs-comment'># Errors such as FileExistsError/TimeoutError (see #Open).</span>\n" +
-  "      │    └── ConnectionError    <span class='hljs-comment'># Errors such as BrokenPipeError/ConnectionAbortedError.</span>\n" +
+  "      ├── OSError                 <span class='hljs-comment'># Errors such as FileExistsError, TimeoutError (see #Open).</span>\n" +
+  "      │    └── ConnectionError    <span class='hljs-comment'># Errors such as BrokenPipeError and ConnectionAbortedError.</span>\n" +
   "      ├── RuntimeError            <span class='hljs-comment'># Raised by errors that don't fall into other categories.</span>\n" +
   "      │    ├── NotImplementedEr…  <span class='hljs-comment'># Can be raised by abstract methods or by unfinished code.</span>\n" +
   "      │    └── RecursionError     <span class='hljs-comment'># Raised if max recursion depth is exceeded (3k by default).</span>\n" +
-  "      ├── StopIteration           <span class='hljs-comment'># Raised when an empty iterator is passed to next().</span>\n" +
+  "      ├── StopIteration           <span class='hljs-comment'># Raised when exhausted (empty) iterator is passed to next().</span>\n" +
   "      ├── TypeError               <span class='hljs-comment'># When an argument of the wrong type is passed to function.</span>\n" +
   "      └── ValueError              <span class='hljs-comment'># When argument has the right type but inappropriate value.</span>\n";
 
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index 48c167d3b..2fe445937 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -11,7 +11,7 @@
     '<strong>Module <a href="#operator">operator</a> has function itemgetter() that can replace listed <a href="#lambda">lambdas</a>.</strong>': '<strong>Module \'operator\' has function itemgetter() that can replace listed lambdas (p. 31).</strong>',
     '<strong>This text uses the term collection instead of iterable. For rationale see <a href="#collection">Collection</a>.</strong>': '<strong>This text uses the term collection instead of iterable. For rationale see Collection (p. 18).</strong>',
     '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its <a href="#class">repr()</a> method.</strong>': '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its repr() method.</strong>',
-    '<strong>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>': '<strong>It can be any callable, but is usually implemented as a function that returns a closure.</strong>',
+    '<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>': '<strong>A decorator takes a function, adds some functionality and returns it. It can be any callable (p.&nbsp;17), but is usually implemented as a function that returns a closure.</strong>',
     '<strong>Hints are used by type checkers like <a href="https://pypi.org/project/mypy/">mypy</a>, data validation libraries such as <a href="https://pypi.org/project/pydantic/">Pydantic</a> and lately also by <a href="https://pypi.org/project/Cython/">Cython</a> compiler. However, they are not enforced by CPython interpreter.</strong>': '<strong>Hints are used by type checkers like mypy, data validation libraries such as Pydantic and lately also by Cython compiler. However, they are not enforced by CPython interpreter.</strong>',
     '<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>': '<strong>Objects can be made sortable 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>',
     '<strong>For object to be <a href="#hashable">hashable</a>, all attributes must be hashable and \'frozen\' must be True.</strong>': '<strong>For object to be hashable, all attributes must be hashable and \'frozen\' must be True.</strong>',

From b12133f82afd68b1d773ad334a24a1d35c1f8d26 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sat, 26 Jul 2025 07:13:36 +0200
Subject: [PATCH 167/186] Open, Paths, OS Commands

---
 README.md  | 48 ++++++++++++++++++++++++------------------------
 index.html | 52 ++++++++++++++++++++++++++--------------------------
 parse.js   |  2 +-
 3 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/README.md b/README.md
index fce8d121b..d4697f939 100644
--- a/README.md
+++ b/README.md
@@ -1538,7 +1538,7 @@ arguments    = sys.argv[1:]
 ### Argument Parser
 ```python
 from argparse import ArgumentParser, FileType
-p = ArgumentParser(description=<str>)                             # Returns a parser.
+p = ArgumentParser(description=<str>)                             # Returns a parser object.
 p.add_argument('-<short_name>', '--<name>', action='store_true')  # Flag (defaults to False).
 p.add_argument('-<short_name>', '--<name>', type=<type>)          # Option (defaults to None).
 p.add_argument('<name>', type=<type>, nargs=1)                    # Mandatory first argument.
@@ -1582,21 +1582,21 @@ Open
 
 ### File Object
 ```python
-<file>.seek(0)                      # Moves to the start of the file.
+<file>.seek(0)                      # Moves current position to the start of file.
 <file>.seek(offset)                 # Moves 'offset' chars/bytes from the start.
-<file>.seek(0, 2)                   # Moves to the end of the file.
+<file>.seek(0, 2)                   # Moves current position to the end of file.
 <bin_file>.seek(±offset, origin)    # Origin: 0 start, 1 current position, 2 end.
 ```
 
 ```python
-<str/bytes> = <file>.read(size=-1)  # Reads 'size' chars/bytes or until EOF.
+<str/bytes> = <file>.read(size=-1)  # Reads 'size' chars/bytes or until the EOF.
 <str/bytes> = <file>.readline()     # Returns a line or empty string/bytes on EOF.
-<list>      = <file>.readlines()    # Returns a list of remaining lines.
-<str/bytes> = next(<file>)          # Returns a line using buffer. Do not mix.
+<list>      = <file>.readlines()    # Returns remaining lines. Also list(<file>).
+<str/bytes> = next(<file>)          # Uses read-ahead buffer. Don't mix with above.
 ```
 
 ```python
-<file>.write(<str/bytes>)           # Writes a string or bytes object.
+<file>.write(<str/bytes>)           # Writes a str or bytes object to write buffer.
 <file>.writelines(<collection>)     # Writes a coll. of strings or bytes objects.
 <file>.flush()                      # Flushes write buffer. Runs every 4096/8192 B.
 <file>.close()                      # Closes the file after flushing write buffer.
@@ -1638,19 +1638,19 @@ from pathlib import Path
 ```
 
 ```python
-<list> = os.listdir(path='.')       # Returns filenames located at the path.
+<list> = os.listdir(path='.')       # Returns all filenames located at the path.
 <list> = glob.glob('<pattern>')     # Returns paths matching the wildcard pattern.
 ```
 
 ```python
-<bool> = os.path.exists(<path>)     # Same as <Path>.exists().
-<bool> = os.path.isfile(<path>)     # Same as <DirEntry/Path>.is_file().
-<bool> = os.path.isdir(<path>)      # Same as <DirEntry/Path>.is_dir().
+<bool> = os.path.exists(<path>)     # Checks if path exists. Also <Path>.exists().
+<bool> = os.path.isfile(<path>)     # Also <Path>.is_file() and <DirEntry>.is_file().
+<bool> = os.path.isdir(<path>)      # Also <Path>.is_dir() and <DirEntry>.is_dir().
 ```
 
 ```python
-<stat> = os.stat(<path>)            # Same as <DirEntry/Path>.stat().
-<num>  = <stat>.st_mtime/st_size/…  # Modification time, size in bytes, etc.
+<stat> = os.stat(<path>)            # File's status. Also <Path/DirEntry>.stat().
+<num>  = <stat>.st_mtime/st_size/…  # Returns modification time, size in bytes, etc.
 ```
 
 ### DirEntry
@@ -1658,8 +1658,8 @@ from pathlib import Path
 
 ```python
 <iter> = os.scandir(path='.')       # Returns DirEntry objects located at the path.
-<str>  = <DirEntry>.path            # Returns the whole path as a string.
-<str>  = <DirEntry>.name            # Returns final component as a string.
+<str>  = <DirEntry>.path            # Returns the whole path (relative by default).
+<str>  = <DirEntry>.name            # Returns path's final component as a string.
 <file> = open(<DirEntry>)           # Opens the file and returns its file object.
 ```
 
@@ -1671,7 +1671,7 @@ from pathlib import Path
 ```
 
 ```python
-<Path> = Path()                     # Returns relative CWD. Also Path('.').
+<Path> = Path()                     # Returns current working dir. Also Path('.').
 <Path> = Path.cwd()                 # Returns absolute CWD. Also Path().resolve().
 <Path> = Path.home()                # Returns user's home directory (absolute).
 <Path> = Path(__file__).resolve()   # Returns module's path if CWD wasn't changed.
@@ -1679,10 +1679,10 @@ from pathlib import Path
 
 ```python
 <Path> = <Path>.parent              # Returns Path without the final component.
-<str>  = <Path>.name                # Returns final component as a string.
-<str>  = <Path>.suffix              # Returns name's last extension, e.g. '.py'.
+<str>  = <Path>.name                # Returns path's final component as a string.
+<str>  = <Path>.suffix              # Returns name's last extension, e.g. '.gz'.
 <str>  = <Path>.stem                # Returns name without the last extension.
-<tup.> = <Path>.parts               # Returns all components as strings.
+<tup.> = <Path>.parts               # Returns all path's components as strings.
 ```
 
 ```python
@@ -1692,7 +1692,7 @@ from pathlib import Path
 
 ```python
 <str>  = str(<Path>)                # Returns path as string. Also <Path>.as_uri().
-<file> = open(<Path>)               # Also <Path>.read/write_text/bytes(<args>).
+<file> = open(<Path>)               # Also <Path>.read_text/write_bytes(<args>).
 ```
 
 
@@ -1715,15 +1715,15 @@ shutil.copytree(from, to)           # Copies the directory. 'to' must not exist.
 ```
 
 ```python
-os.rename(from, to)                 # Renames/moves the file or directory.
+os.rename(from, to)                 # Renames or moves the file or directory 'from'.
 os.replace(from, to)                # Same, but overwrites file 'to' even on Windows.
 shutil.move(from, to)               # Rename() that moves into 'to' if it's a dir.
 ```
 
 ```python
-os.remove(<path>)                   # Deletes the file.
-os.rmdir(<path>)                    # Deletes the empty directory.
-shutil.rmtree(<path>)               # Deletes the directory.
+os.remove(<path>)                   # Deletes the file. Or `pip3 install send2trash`.
+os.rmdir(<path>)                    # Deletes the empty directory or raises OSError.
+shutil.rmtree(<path>)               # Deletes the directory and all of its contents.
 ```
 * **Paths can be either strings, Path objects, or DirEntry objects.**
 * **Functions report OS related errors by raising OSError or one of its [subclasses](#exceptions-1).**
diff --git a/index.html b/index.html
index b45943c7e..79d6c3388 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>July 25, 2025</aside>
+    <aside>July 26, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1315,7 +1315,7 @@
 </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, FileType
-p = ArgumentParser(description=&lt;str&gt;)                             <span class="hljs-comment"># Returns a parser.</span>
+p = ArgumentParser(description=&lt;str&gt;)                             <span class="hljs-comment"># Returns a parser object.</span>
 p.add_argument(<span class="hljs-string">'-&lt;short_name&gt;'</span>, <span class="hljs-string">'--&lt;name&gt;'</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">'-&lt;short_name&gt;'</span>, <span class="hljs-string">'--&lt;name&gt;'</span>, type=&lt;type&gt;)          <span class="hljs-comment"># Option (defaults to None).</span>
 p.add_argument(<span class="hljs-string">'&lt;name&gt;'</span>, type=&lt;type&gt;, nargs=<span class="hljs-number">1</span>)                    <span class="hljs-comment"># Mandatory first argument.</span>
@@ -1353,9 +1353,9 @@
 <li><strong><code class="python hljs"><span class="hljs-string">'FileExistsError'</span></code> 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> and <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">'OSError'</span></code> is the parent class of all listed exceptions.</strong></li>
-</ul><div><h3 id="fileobject">File Object</h3><pre><code class="python language-python hljs">&lt;file&gt;.seek(<span class="hljs-number">0</span>)                      <span class="hljs-comment"># Moves to the start of the file.</span>
+</ul><div><h3 id="fileobject">File Object</h3><pre><code class="python language-python hljs">&lt;file&gt;.seek(<span class="hljs-number">0</span>)                      <span class="hljs-comment"># Moves current position to the start of file.</span>
 &lt;file&gt;.seek(offset)                 <span class="hljs-comment"># Moves 'offset' chars/bytes from the start.</span>
-&lt;file&gt;.seek(<span class="hljs-number">0</span>, <span class="hljs-number">2</span>)                   <span class="hljs-comment"># Moves to the end of the file.</span>
+&lt;file&gt;.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>
 &lt;bin_file&gt;.seek(±offset, origin)    <span class="hljs-comment"># Origin: 0 start, 1 current position, 2 end.</span>
 </code></pre></div></div></div>
 
@@ -1363,12 +1363,12 @@
 
 
 
-<pre><code class="python language-python hljs">&lt;str/bytes&gt; = &lt;file&gt;.read(size=<span class="hljs-number">-1</span>)  <span class="hljs-comment"># Reads 'size' chars/bytes or until EOF.</span>
+<pre><code class="python language-python hljs">&lt;str/bytes&gt; = &lt;file&gt;.read(size=<span class="hljs-number">-1</span>)  <span class="hljs-comment"># Reads 'size' chars/bytes or until the EOF.</span>
 &lt;str/bytes&gt; = &lt;file&gt;.readline()     <span class="hljs-comment"># Returns a line or empty string/bytes on EOF.</span>
-&lt;list&gt;      = &lt;file&gt;.readlines()    <span class="hljs-comment"># Returns a list of remaining lines.</span>
-&lt;str/bytes&gt; = next(&lt;file&gt;)          <span class="hljs-comment"># Returns a line using buffer. Do not mix.</span>
+&lt;list&gt;      = &lt;file&gt;.readlines()    <span class="hljs-comment"># Returns remaining lines. Also list(&lt;file&gt;).</span>
+&lt;str/bytes&gt; = next(&lt;file&gt;)          <span class="hljs-comment"># Uses read-ahead buffer. Don't mix with above.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;file&gt;.write(&lt;str/bytes&gt;)           <span class="hljs-comment"># Writes a string or bytes object.</span>
+<pre><code class="python language-python hljs">&lt;file&gt;.write(&lt;str/bytes&gt;)           <span class="hljs-comment"># Writes a str or bytes object to write buffer.</span>
 &lt;file&gt;.writelines(&lt;collection&gt;)     <span class="hljs-comment"># Writes a coll. of strings or bytes objects.</span>
 &lt;file&gt;.flush()                      <span class="hljs-comment"># Flushes write buffer. Runs every 4096/8192 B.</span>
 &lt;file&gt;.close()                      <span class="hljs-comment"># Closes the file after flushing write buffer.</span>
@@ -1398,19 +1398,19 @@
 &lt;str&gt;  = os.path.dirname(&lt;path&gt;)    <span class="hljs-comment"># Returns path without the final component.</span>
 &lt;tup.&gt; = os.path.splitext(&lt;path&gt;)   <span class="hljs-comment"># Splits on last period of the final component.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;list&gt; = os.listdir(path=<span class="hljs-string">'.'</span>)       <span class="hljs-comment"># Returns filenames located at the path.</span>
+<pre><code class="python language-python hljs">&lt;list&gt; = os.listdir(path=<span class="hljs-string">'.'</span>)       <span class="hljs-comment"># Returns all filenames located at the path.</span>
 &lt;list&gt; = glob.glob(<span class="hljs-string">'&lt;pattern&gt;'</span>)     <span class="hljs-comment"># Returns paths matching the wildcard pattern.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;bool&gt; = os.path.exists(&lt;path&gt;)     <span class="hljs-comment"># Same as &lt;Path&gt;.exists().</span>
-&lt;bool&gt; = os.path.isfile(&lt;path&gt;)     <span class="hljs-comment"># Same as &lt;DirEntry/Path&gt;.is_file().</span>
-&lt;bool&gt; = os.path.isdir(&lt;path&gt;)      <span class="hljs-comment"># Same as &lt;DirEntry/Path&gt;.is_dir().</span>
+<pre><code class="python language-python hljs">&lt;bool&gt; = os.path.exists(&lt;path&gt;)     <span class="hljs-comment"># Checks if path exists. Also &lt;Path&gt;.exists().</span>
+&lt;bool&gt; = os.path.isfile(&lt;path&gt;)     <span class="hljs-comment"># Also &lt;Path&gt;.is_file() and &lt;DirEntry&gt;.is_file().</span>
+&lt;bool&gt; = os.path.isdir(&lt;path&gt;)      <span class="hljs-comment"># Also &lt;Path&gt;.is_dir() and &lt;DirEntry&gt;.is_dir().</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;stat&gt; = os.stat(&lt;path&gt;)            <span class="hljs-comment"># Same as &lt;DirEntry/Path&gt;.stat().</span>
-&lt;num&gt;  = &lt;stat&gt;.st_mtime/st_size/…  <span class="hljs-comment"># Modification time, size in bytes, etc.</span>
+<pre><code class="python language-python hljs">&lt;stat&gt; = os.stat(&lt;path&gt;)            <span class="hljs-comment"># File's status. Also &lt;Path/DirEntry&gt;.stat().</span>
+&lt;num&gt;  = &lt;stat&gt;.st_mtime/st_size/…  <span class="hljs-comment"># Returns modification time, size in bytes, etc.</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">&lt;iter&gt; = os.scandir(path=<span class="hljs-string">'.'</span>)       <span class="hljs-comment"># Returns DirEntry objects located at the path.</span>
-&lt;str&gt;  = &lt;DirEntry&gt;.path            <span class="hljs-comment"># Returns the whole path as a string.</span>
-&lt;str&gt;  = &lt;DirEntry&gt;.name            <span class="hljs-comment"># Returns final component as a string.</span>
+&lt;str&gt;  = &lt;DirEntry&gt;.path            <span class="hljs-comment"># Returns the whole path (relative by default).</span>
+&lt;str&gt;  = &lt;DirEntry&gt;.name            <span class="hljs-comment"># Returns path's final component as a string.</span>
 &lt;file&gt; = open(&lt;DirEntry&gt;)           <span class="hljs-comment"># Opens the file and returns its file object.</span>
 </code></pre></div>
 
@@ -1420,22 +1420,22 @@
 &lt;Path&gt; = &lt;Path&gt;.resolve()           <span class="hljs-comment"># Returns absolute path with resolved symlinks.</span>
 </code></pre></div>
 
-<pre><code class="python language-python hljs">&lt;Path&gt; = Path()                     <span class="hljs-comment"># Returns relative CWD. Also Path('.').</span>
+<pre><code class="python language-python hljs">&lt;Path&gt; = Path()                     <span class="hljs-comment"># Returns current working dir. Also Path('.').</span>
 &lt;Path&gt; = Path.cwd()                 <span class="hljs-comment"># Returns absolute CWD. Also Path().resolve().</span>
 &lt;Path&gt; = Path.home()                <span class="hljs-comment"># Returns user's home directory (absolute).</span>
 &lt;Path&gt; = Path(__file__).resolve()   <span class="hljs-comment"># Returns module's path if CWD wasn't changed.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;Path&gt; = &lt;Path&gt;.parent              <span class="hljs-comment"># Returns Path without the final component.</span>
-&lt;str&gt;  = &lt;Path&gt;.name                <span class="hljs-comment"># Returns final component as a string.</span>
-&lt;str&gt;  = &lt;Path&gt;.suffix              <span class="hljs-comment"># Returns name's last extension, e.g. '.py'.</span>
+&lt;str&gt;  = &lt;Path&gt;.name                <span class="hljs-comment"># Returns path's final component as a string.</span>
+&lt;str&gt;  = &lt;Path&gt;.suffix              <span class="hljs-comment"># Returns name's last extension, e.g. '.gz'.</span>
 &lt;str&gt;  = &lt;Path&gt;.stem                <span class="hljs-comment"># Returns name without the last extension.</span>
-&lt;tup.&gt; = &lt;Path&gt;.parts               <span class="hljs-comment"># Returns all components as strings.</span>
+&lt;tup.&gt; = &lt;Path&gt;.parts               <span class="hljs-comment"># Returns all path's components as strings.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;iter&gt; = &lt;Path&gt;.iterdir()           <span class="hljs-comment"># Returns directory contents as Path objects.</span>
 &lt;iter&gt; = &lt;Path&gt;.glob(<span class="hljs-string">'&lt;pattern&gt;'</span>)   <span class="hljs-comment"># Returns Paths matching the wildcard pattern.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;str&gt;  = str(&lt;Path&gt;)                <span class="hljs-comment"># Returns path as string. Also &lt;Path&gt;.as_uri().</span>
-&lt;file&gt; = open(&lt;Path&gt;)               <span class="hljs-comment"># Also &lt;Path&gt;.read/write_text/bytes(&lt;args&gt;).</span>
+&lt;file&gt; = open(&lt;Path&gt;)               <span class="hljs-comment"># Also &lt;Path&gt;.read_text/write_bytes(&lt;args&gt;).</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, subprocess
 </code></pre></div>
@@ -1448,13 +1448,13 @@
 shutil.copy2(from, to)              <span class="hljs-comment"># Also copies creation and modification time.</span>
 shutil.copytree(from, to)           <span class="hljs-comment"># Copies the directory. 'to' must not exist.</span>
 </code></pre>
-<pre><code class="python language-python hljs">os.rename(from, to)                 <span class="hljs-comment"># Renames/moves the file or directory.</span>
+<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>
 shutil.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(&lt;path&gt;)                   <span class="hljs-comment"># Deletes the file.</span>
-os.rmdir(&lt;path&gt;)                    <span class="hljs-comment"># Deletes the empty directory.</span>
-shutil.rmtree(&lt;path&gt;)               <span class="hljs-comment"># Deletes the directory.</span>
+<pre><code class="python language-python hljs">os.remove(&lt;path&gt;)                   <span class="hljs-comment"># Deletes the file. Or `pip3 install send2trash`.</span>
+os.rmdir(&lt;path&gt;)                    <span class="hljs-comment"># Deletes the empty directory or raises OSError.</span>
+shutil.rmtree(&lt;path&gt;)               <span class="hljs-comment"># Deletes the directory and all of its contents.</span>
 </code></pre>
 <ul>
 <li><strong>Paths can be either strings, Path objects, or DirEntry objects.</strong></li>
@@ -2935,7 +2935,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>July 25, 2025</aside>
+    <aside>July 26, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 8a19d0928..03d06b4fd 100755
--- a/parse.js
+++ b/parse.js
@@ -95,7 +95,7 @@ const SHUTIL_COPY =
   'shutil.copytree(from, to)           <span class="hljs-comment"># Copies the directory. \'to\' must not exist.</span>\n';
 
 const OS_RENAME =
-  'os.rename(from, to)                 <span class="hljs-comment"># Renames/moves the file or directory.</span>\n' +
+  'os.rename(from, to)                 <span class="hljs-comment"># Renames or moves the file or directory \'from\'.</span>\n' +
   'os.replace(from, to)                <span class="hljs-comment"># Same, but overwrites file \'to\' even on Windows.</span>\n' +
   'shutil.move(from, to)               <span class="hljs-comment"># Rename() that moves into \'to\' if it\'s a dir.</span>\n';
 

From 22b3806e76885c87c587b8eecac74efb6d490057 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 27 Jul 2025 05:12:56 +0200
Subject: [PATCH 168/186] CSV, SQLite, Coroutines

---
 README.md           | 45 +++++++++++++++++++-------------------
 index.html          | 53 +++++++++++++++++++++++----------------------
 pdf/remove_links.py |  5 +++--
 3 files changed, 53 insertions(+), 50 deletions(-)

diff --git a/README.md b/README.md
index d4697f939..b1b9ca2d5 100644
--- a/README.md
+++ b/README.md
@@ -71,7 +71,7 @@ flatter_list     = list(itertools.chain.from_iterable(<list>))
 <el>  = <list>.pop()            # Removes and returns item from the end or at index if passed.
 <list>.insert(<int>, <el>)      # Inserts item at passed index and moves the rest to the right.
 <list>.remove(<el>)             # Removes first occurrence of the item or raises ValueError.
-<list>.clear()                  # Removes all items. Also works on dictionaries and sets.
+<list>.clear()                  # Removes all list's items. Also works on dictionary and set.
 ```
 
 
@@ -1179,7 +1179,7 @@ class Counter:
 
 ### Callable
 * **All functions and classes have a call() method, hence are callable.**
-* **Use `'callable(<obj>)'` or `'isinstance(<obj>, collections.abc.Callable)'` to check if object is callable. Calling an uncallable object raises TypeError.**
+* **Use `'callable(<obj>)'` or `'isinstance(<obj>, collections.abc.Callable)'` to check if object is callable. You can also just call the object and check if it raised TypeError.**
 * **When this cheatsheet uses `'<function>'` as an argument, it means `'<callable>'`.**
 ```python
 class Counter:
@@ -1627,7 +1627,7 @@ from pathlib import Path
 
 ```python
 <str>  = os.getcwd()                # Returns working dir. Starts as shell's $PWD.
-<str>  = os.path.join(<path>, ...)  # Joins two or more pathname components.
+<str>  = os.path.join(<path>, ...)  # Uses os.sep to join strings or Path objects.
 <str>  = os.path.realpath(<path>)   # Resolves symlinks and calls path.abspath().
 ```
 
@@ -1810,24 +1810,25 @@ CSV
 import csv
 ```
 
-### Read
 ```python
-<reader> = csv.reader(<file>)       # Also: `dialect='excel', delimiter=','`.
-<list>   = next(<reader>)           # Returns next row as a list of strings.
-<list>   = list(<reader>)           # Returns a list of remaining rows.
+<file>   = open(<path>, newline='')       # Opens the CSV (text) file for reading.
+<reader> = csv.reader(<file>)             # Also: `dialect='excel', delimiter=','`.
+<list>   = next(<reader>)                 # Returns next row as a list of strings.
+<list>   = list(<reader>)                 # Returns a list of all remaining rows.
 ```
-* **File must be opened with a `'newline=""'` argument, or every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'!**
+* **Without the `'newline=""'` argument, every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'! For details about newline argument see [Open](#open).**
 * **To print the spreadsheet to the console use [Tabulate](#table) library.**
-* **For XML and binary Excel files (xlsx, xlsm and xlsb) use [Pandas](#dataframe-plot-encode-decode) library.**
-* **Reader accepts any iterator or collection of strings, not just files.**
+* **For XML and binary Excel files (xlsx, xlsm and xlsb) use [Pandas](#fileformats) library.**
+* **Reader accepts any iterator (or collection) of strings, not just files.**
 
 ### Write
 ```python
-<writer> = csv.writer(<file>)       # Also: `dialect='excel', delimiter=','`.
-<writer>.writerow(<collection>)     # Encodes objects using `str(<el>)`.
-<writer>.writerows(<coll_of_coll>)  # Appends multiple rows.
+<file>   = open(<path>, 'w', newline='')  # Opens the CSV (text) file for writing.
+<writer> = csv.writer(<file>)             # Also: `dialect='excel', delimiter=','`.
+<writer>.writerow(<collection>)           # Encodes each object using `str(<el>)`.
+<writer>.writerows(<coll_of_coll>)        # Appends multiple rows to the file.
 ```
-* **File must be opened with a `'newline=""'` argument, or '\r' will be added in front of every '\n' on platforms that use '\r\n' line endings!**
+* **If file is opened without the `'newline=""'` argument, '\r' will be added in front of every '\n' on platforms that use '\r\n' line endings (i.e., newlines may get doubled on Windows)!**
 * **Open existing file with `'mode="a"'` to append to it or `'mode="w"'` to overwrite it.**
 
 ### Parameters
@@ -1836,7 +1837,7 @@ import csv
 * **`'lineterminator'` - How writer terminates rows. Reader looks for '\n', '\r' and '\r\n'.**
 * **`'quotechar'` - Character for quoting fields containing delimiters, quotechars, '\n' or '\r'.**
 * **`'escapechar'` - Character for escaping quotechars (not needed if doublequote is True).**
-* **`'doublequote'` - Whether quotechars inside fields are/get doubled or escaped.**
+* **`'doublequote'` - Whether quotechars inside fields are (or get) doubled or escaped.**
 * **`'quoting'` - 0: As necessary, 1: All, 2: All but numbers which are read as floats, 3: None.**
 * **`'skipinitialspace'` - Is space character at the start of the field stripped by the reader.**
 
@@ -1904,18 +1905,18 @@ with <conn>:                                   # Exits the block with commit() o
 ### Placeholders
 ```python
 <conn>.execute('<query>', <list/tuple>)        # Replaces every question mark with an item.
-<conn>.execute('<query>', <dict/namedtuple>)   # Replaces every :<key> with a value.
-<conn>.executemany('<query>', <coll_of_coll>)  # Runs execute() multiple times.
+<conn>.execute('<query>', <dict/namedtuple>)   # Replaces every :<key> with matching value.
+<conn>.executemany('<query>', <coll_of_coll>)  # Runs execute() once for each collection.
 ```
 * **Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).**
+* **SQLite does not restrict columns to any type unless table is declared as strict.**
 
 ### Example
 **Values are not actually saved in this example because `'conn.commit()'` is omitted!**
 ```python
 >>> conn = sqlite3.connect('test.db')
->>> conn.execute('CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height)')
->>> conn.execute('INSERT INTO person VALUES (NULL, ?, ?)', ('Jean-Luc', 187)).lastrowid
-1
+>>> conn.execute('CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height) STRICT')
+>>> conn.execute('INSERT INTO person VALUES (NULL, ?, ?)', ('Jean-Luc', 187))
 >>> conn.execute('SELECT * FROM person').fetchall()
 [(1, 'Jean-Luc', 187)]
 ```
@@ -2317,8 +2318,8 @@ import asyncio as aio
 
 ```python
 <coro> = <async_function>(<args>)          # Creates a coroutine by calling async def function.
-<obj>  = await <coroutine>                 # Starts the coroutine and returns its result.
-<task> = aio.create_task(<coroutine>)      # Schedules the coroutine for execution.
+<obj>  = await <coroutine>                 # Starts the coroutine and waits for its result.
+<task> = aio.create_task(<coroutine>)      # Schedules it for execution. Always keep the task.
 <obj>  = await <task>                      # Returns coroutine's result. Also <task>.cancel().
 ```
 
diff --git a/index.html b/index.html
index 79d6c3388..bf69e5a28 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>July 26, 2025</aside>
+    <aside>July 27, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -144,7 +144,7 @@
 &lt;el&gt;  = &lt;list&gt;.pop()            <span class="hljs-comment"># Removes and returns item from the end or at index if passed.</span>
 &lt;list&gt;.insert(&lt;int&gt;, &lt;el&gt;)      <span class="hljs-comment"># Inserts item at passed index and moves the rest to the right.</span>
 &lt;list&gt;.remove(&lt;el&gt;)             <span class="hljs-comment"># Removes first occurrence of the item or raises ValueError.</span>
-&lt;list&gt;.clear()                  <span class="hljs-comment"># Removes all items. Also works on dictionaries and sets.</span>
+&lt;list&gt;.clear()                  <span class="hljs-comment"># Removes all list's items. Also works on dictionary and set.</span>
 </code></pre>
 <div><h2 id="dictionary"><a href="#dictionary" name="dictionary">#</a>Dictionary</h2><pre><code class="python language-python hljs">&lt;dict&gt; = {key_1: val_1, key_2: val_2, ...}      <span class="hljs-comment"># Use `&lt;dict&gt;[key]` to get or set the value.</span>
 </code></pre></div>
@@ -1008,7 +1008,7 @@
 <li><strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong></li>
 </ul><div><h3 id="callable">Callable</h3><ul>
 <li><strong>All functions and classes have a call() method, hence are callable.</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'callable(&lt;obj&gt;)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(&lt;obj&gt;, collections.abc.Callable)'</span></code> to check if object is callable. Calling an uncallable object raises TypeError.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'callable(&lt;obj&gt;)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(&lt;obj&gt;, collections.abc.Callable)'</span></code> to check if object is callable. You can also just call the object and check if it raised TypeError.</strong></li>
 <li><strong>When this cheatsheet uses <code class="python hljs"><span class="hljs-string">'&lt;function&gt;'</span></code> as an argument, it means <code class="python hljs"><span class="hljs-string">'&lt;callable&gt;'</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>
@@ -1391,7 +1391,7 @@
 </code></pre></div>
 
 <pre><code class="python language-python hljs">&lt;str&gt;  = os.getcwd()                <span class="hljs-comment"># Returns working dir. Starts as shell's $PWD.</span>
-&lt;str&gt;  = os.path.join(&lt;path&gt;, ...)  <span class="hljs-comment"># Joins two or more pathname components.</span>
+&lt;str&gt;  = os.path.join(&lt;path&gt;, ...)  <span class="hljs-comment"># Uses os.sep to join strings or Path objects.</span>
 &lt;str&gt;  = os.path.realpath(&lt;path&gt;)   <span class="hljs-comment"># Resolves symlinks and calls path.abspath().</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;str&gt;  = os.path.basename(&lt;path&gt;)   <span class="hljs-comment"># Returns final component of the path.</span>
@@ -1513,24 +1513,25 @@
 </code></pre></div>
 
 
-<div><h3 id="read">Read</h3><pre><code class="python language-python hljs">&lt;reader&gt; = csv.reader(&lt;file&gt;)       <span class="hljs-comment"># Also: `dialect='excel', delimiter=','`.</span>
-&lt;list&gt;   = next(&lt;reader&gt;)           <span class="hljs-comment"># Returns next row as a list of strings.</span>
-&lt;list&gt;   = list(&lt;reader&gt;)           <span class="hljs-comment"># Returns a list of remaining rows.</span>
-</code></pre></div>
-
+<pre><code class="python language-python hljs">&lt;file&gt;   = open(&lt;path&gt;, newline=<span class="hljs-string">''</span>)       <span class="hljs-comment"># Opens the CSV (text) file for reading.</span>
+&lt;reader&gt; = csv.reader(&lt;file&gt;)             <span class="hljs-comment"># Also: `dialect='excel', delimiter=','`.</span>
+&lt;list&gt;   = next(&lt;reader&gt;)                 <span class="hljs-comment"># Returns next row as a list of strings.</span>
+&lt;list&gt;   = list(&lt;reader&gt;)                 <span class="hljs-comment"># Returns a list of all remaining rows.</span>
+</code></pre>
 <ul>
-<li><strong>File must be opened with a <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, or every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'!</strong></li>
+<li><strong>Without the <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'! For details about newline argument see <a href="#open">Open</a>.</strong></li>
 <li><strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong></li>
-<li><strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#dataframeplotencodedecode">Pandas</a> library.</strong></li>
-<li><strong>Reader accepts any iterator or collection of strings, not just files.</strong></li>
+<li><strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#fileformats">Pandas</a> library.</strong></li>
+<li><strong>Reader accepts any iterator (or collection) of strings, not just files.</strong></li>
 </ul>
-<div><h3 id="write">Write</h3><pre><code class="python language-python hljs">&lt;writer&gt; = csv.writer(&lt;file&gt;)       <span class="hljs-comment"># Also: `dialect='excel', delimiter=','`.</span>
-&lt;writer&gt;.writerow(&lt;collection&gt;)     <span class="hljs-comment"># Encodes objects using `str(&lt;el&gt;)`.</span>
-&lt;writer&gt;.writerows(&lt;coll_of_coll&gt;)  <span class="hljs-comment"># Appends multiple rows.</span>
+<div><h3 id="write">Write</h3><pre><code class="python language-python hljs">&lt;file&gt;   = open(&lt;path&gt;, <span class="hljs-string">'w'</span>, newline=<span class="hljs-string">''</span>)  <span class="hljs-comment"># Opens the CSV (text) file for writing.</span>
+&lt;writer&gt; = csv.writer(&lt;file&gt;)             <span class="hljs-comment"># Also: `dialect='excel', delimiter=','`.</span>
+&lt;writer&gt;.writerow(&lt;collection&gt;)           <span class="hljs-comment"># Encodes each object using `str(&lt;el&gt;)`.</span>
+&lt;writer&gt;.writerows(&lt;coll_of_coll&gt;)        <span class="hljs-comment"># Appends multiple rows to the file.</span>
 </code></pre></div>
 
 <ul>
-<li><strong>File must be opened with a <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, or '\r' will be added in front of every '\n' on platforms that use '\r\n' line endings!</strong></li>
+<li><strong>If file is opened without the <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, '\r' will be added in front of every '\n' on platforms that use '\r\n' line endings (i.e., newlines may get doubled on Windows)!</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="parameters">Parameters</h3><ul>
@@ -1539,7 +1540,7 @@
 <li><strong><code class="python hljs"><span class="hljs-string">'lineterminator'</span></code> - 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 (not needed 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 or escaped.</strong></li>
+<li><strong><code class="python hljs"><span class="hljs-string">'doublequote'</span></code> - Whether quotechars inside fields are (or get) doubled or 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">┏━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┓
@@ -1574,7 +1575,7 @@
 </code></pre></div>
 
 
-<div><h3 id="read-1">Read</h3><pre><code class="python language-python hljs">&lt;cursor&gt; = &lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)           <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span>
+<div><h3 id="read">Read</h3><pre><code class="python language-python hljs">&lt;cursor&gt; = &lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)           <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span>
 &lt;tuple&gt;  = &lt;cursor&gt;.fetchone()                 <span class="hljs-comment"># Returns next row. Also next(&lt;cursor&gt;).</span>
 &lt;list&gt;   = &lt;cursor&gt;.fetchall()                 <span class="hljs-comment"># Returns remaining rows. Also list(&lt;cursor&gt;).</span>
 </code></pre></div>
@@ -1589,17 +1590,17 @@
 </code></pre></div>
 
 <div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)        <span class="hljs-comment"># Replaces every question mark with an item.</span>
-&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces every :&lt;key&gt; with a value.</span>
-&lt;conn&gt;.executemany(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;coll_of_coll&gt;)  <span class="hljs-comment"># Runs execute() multiple times.</span>
+&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces every :&lt;key&gt; with matching value.</span>
+&lt;conn&gt;.executemany(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;coll_of_coll&gt;)  <span class="hljs-comment"># Runs execute() once for each collection.</span>
 </code></pre></div>
 
 <ul>
 <li><strong>Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).</strong></li>
+<li><strong>SQLite does not restrict columns to any type unless table is declared as 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">'conn.commit()'</span></code> is omitted!</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>conn = sqlite3.connect(<span class="hljs-string">'test.db'</span>)
-<span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height)'</span>)
-<span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'INSERT INTO person VALUES (NULL, ?, ?)'</span>, (<span class="hljs-string">'Jean-Luc'</span>, <span class="hljs-number">187</span>)).lastrowid
-<span class="hljs-number">1</span>
+<span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height) STRICT'</span>)
+<span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'INSERT INTO person VALUES (NULL, ?, ?)'</span>, (<span class="hljs-string">'Jean-Luc'</span>, <span class="hljs-number">187</span>))
 <span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'SELECT * 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>
@@ -1910,8 +1911,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 <pre><code class="python language-python hljs">&lt;coro&gt; = &lt;async_function&gt;(&lt;args&gt;)          <span class="hljs-comment"># Creates a coroutine by calling async def function.</span>
-&lt;obj&gt;  = <span class="hljs-keyword">await</span> &lt;coroutine&gt;                 <span class="hljs-comment"># Starts the coroutine and returns its result.</span>
-&lt;task&gt; = aio.create_task(&lt;coroutine&gt;)      <span class="hljs-comment"># Schedules the coroutine for execution.</span>
+&lt;obj&gt;  = <span class="hljs-keyword">await</span> &lt;coroutine&gt;                 <span class="hljs-comment"># Starts the coroutine and waits for its result.</span>
+&lt;task&gt; = aio.create_task(&lt;coroutine&gt;)      <span class="hljs-comment"># Schedules it for execution. Always keep the task.</span>
 &lt;obj&gt;  = <span class="hljs-keyword">await</span> &lt;task&gt;                      <span class="hljs-comment"># Returns coroutine's result. Also &lt;task&gt;.cancel().</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;coro&gt; = aio.gather(&lt;coro/task&gt;, ...)      <span class="hljs-comment"># Schedules coros. Returns list of results on await.</span>
@@ -2935,7 +2936,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>July 26, 2025</aside>
+    <aside>July 27, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index 2fe445937..c731b2413 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -20,10 +20,11 @@
     '<strong>Objects returned by the <a href="#itertools">itertools</a> module, such as count, repeat and cycle.</strong>': '<strong>Objects returned by the itertools module, such as count, repeat and cycle (p. 3).</strong>',
     '<strong>Generators returned by the <a href="#generator">generator functions</a> and <a href="#comprehensions">generator expressions</a>.</strong>': '<strong>Generators returned by the generator functions (p. 4) and generator expressions (p. 11).</strong>',
     '<strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong>': '<strong>File objects returned by the open() function (p. 22), etc.</strong>',
-    '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">Logging</a>.</strong>': '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see Logging (p. 31).</strong>',
+    '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details about setting up the logger see <a href="#logging">Logging</a>.</strong>': '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details about the logger setup see Logging (p. 31).</strong>',
     '<strong>Functions report OS related errors by raising OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong>': '<strong>Functions report OS related errors by raising OSError or one of its subclasses (p. 23).</strong>',
+    '<strong>Without the <code class="python hljs"><span class="hljs-string">\'newline=""\'</span></code> argument, every \'\\r\\n\' sequence that is embedded inside a quoted field will get converted to \'\\n\'! For details about newline argument see <a href="#open">Open</a>.</strong>': '<strong>Without the <code class="python hljs"><span class="hljs-string">\'newline=""\'</span></code> argument, every \'\\r\\n\' sequence that is embedded inside a quoted field will get converted to \'\\n\'! For details about newline arg. see Open (p. 22).</strong>',
     '<strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong>': '<strong>To print the spreadsheet to the console use Tabulate library (p. 34).</strong>',
-    '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#dataframeplotencodedecode">Pandas</a> library.</strong>': '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use Pandas library (p. 46).</strong>',
+    '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#fileformats">Pandas</a> library.</strong>': '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use Pandas library (p. 46).</strong>',
     '<strong>Bools will be stored and returned as ints and dates as <a href="#encode">ISO formatted strings</a>.</strong>': '<strong>Bools will be stored and returned as ints and dates as ISO formatted strings (p. 9).</strong>',
     '<strong>ProcessPoolExecutor provides true parallelism but: everything sent to/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>': '<strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be pickable, 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>',
     '<strong>Install a WSGI 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> for better security.</strong>': '<strong>Install a WSGI server like Waitress and a HTTP server such as Nginx for better security.</strong>',

From 76899d56a2e055601c3bed73cb8664e3602e5fff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 27 Jul 2025 07:57:30 +0200
Subject: [PATCH 169/186] SQLite

---
 README.md  | 6 +++---
 index.html | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index b1b9ca2d5..a266325d5 100644
--- a/README.md
+++ b/README.md
@@ -1915,9 +1915,9 @@ with <conn>:                                   # Exits the block with commit() o
 **Values are not actually saved in this example because `'conn.commit()'` is omitted!**
 ```python
 >>> conn = sqlite3.connect('test.db')
->>> conn.execute('CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height) STRICT')
->>> conn.execute('INSERT INTO person VALUES (NULL, ?, ?)', ('Jean-Luc', 187))
->>> conn.execute('SELECT * FROM person').fetchall()
+>>> conn.execute('CREATE TABLE person (name TEXT, height INTEGER) STRICT')
+>>> conn.execute('INSERT INTO person VALUES (?, ?)', ('Jean-Luc', 187))
+>>> conn.execute('SELECT rowid, * FROM person').fetchall()
 [(1, 'Jean-Luc', 187)]
 ```
 
diff --git a/index.html b/index.html
index bf69e5a28..5564ab052 100644
--- a/index.html
+++ b/index.html
@@ -1599,9 +1599,9 @@
 <li><strong>SQLite does not restrict columns to any type unless table is declared as 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">'conn.commit()'</span></code> is omitted!</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span>conn = sqlite3.connect(<span class="hljs-string">'test.db'</span>)
-<span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height) STRICT'</span>)
-<span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'INSERT INTO person VALUES (NULL, ?, ?)'</span>, (<span class="hljs-string">'Jean-Luc'</span>, <span class="hljs-number">187</span>))
-<span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'SELECT * FROM person'</span>).fetchall()
+<span class="hljs-meta">&gt;&gt;&gt; </span>conn.execute(<span class="hljs-string">'CREATE TABLE person (name TEXT, height INTEGER) STRICT'</span>)
+<span class="hljs-meta">&gt;&gt;&gt; </span>conn.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">&gt;&gt;&gt; </span>conn.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>
 

From 576b9f41b2eef23c212c660b17fdd7190061436e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Mon, 28 Jul 2025 00:09:04 +0200
Subject: [PATCH 170/186] Imports, Duck types, Print, Open

---
 README.md           | 16 ++++++++--------
 index.html          | 20 ++++++++++----------
 pdf/remove_links.py |  2 +-
 3 files changed, 19 insertions(+), 19 deletions(-)

diff --git a/README.md b/README.md
index a266325d5..a88f0d99d 100644
--- a/README.md
+++ b/README.md
@@ -823,9 +823,9 @@ import <module>            # Imports a built-in or '<module>.py'.
 import <package>           # Imports a built-in or '<package>/__init__.py'.
 import <package>.<module>  # Imports a built-in or '<package>/<module>.py'.
 ```
-* **Package is a collection of modules, but it can also define its own objects.**
+* **Package is a collection of modules, but it can also define its own objects, classes, etc.**
 * **On a filesystem this corresponds to a directory of Python files with an optional init script.**
-* **Running `'import <package>'` does not automatically provide access to the package's modules unless they are explicitly imported in its init script.**
+* **Running `'import <package>'` does not automatically provide access to the package's modules unless they are explicitly imported in the `'<package>/__init__.py'` script.**
 * **Directory of the file that is passed to python command serves as a root of local imports.**
 * **For relative imports use `'from .[…][<pkg/module>[.…]] import <obj>'`.**
 
@@ -1178,7 +1178,7 @@ class Counter:
 * **File objects returned by the [open()](#open) function, etc.**
 
 ### Callable
-* **All functions and classes have a call() method, hence are callable.**
+* **All functions and classes have a call() method that is executed when they are called.**
 * **Use `'callable(<obj>)'` or `'isinstance(<obj>, collections.abc.Callable)'` to check if object is callable. You can also just call the object and check if it raised TypeError.**
 * **When this cheatsheet uses `'<function>'` as an argument, it means `'<callable>'`.**
 ```python
@@ -1396,7 +1396,7 @@ finally:
 ```
 * **Code inside the `'else'` block will only be executed if `'try'` block had no exceptions.**
 * **Code inside the `'finally'` block will always be executed (unless a signal is received).**
-* **All variables that are initialized in executed blocks are also visible in all subsequent blocks, as well as outside the try statement (only a function block delimits scope).**
+* **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).**
 * **To catch signals use `'signal.signal(signal_number, handler_function)'`.**
 
 ### Catching Exceptions
@@ -1505,7 +1505,7 @@ Print
 ```python
 print(<el_1>, ..., sep=' ', end='\n', file=sys.stdout, flush=False)
 ```
-* **Use `'file=sys.stderr'` for messages about errors.**
+* **Use `'file=sys.stderr'` for messages about errors so they can be processed separately.**
 * **Stdout and stderr streams hold output in a buffer until they receive a string containing '\n' or '\r', buffer reaches 4096 characters, `'flush=True'` is used, or program exits.**
 
 ### Pretty Print
@@ -1549,7 +1549,7 @@ args  = p.parse_args()                                            # Exits on par
 ```
 
 * **Use `'help=<str>'` to set argument description that will be displayed in help message.**
-* **Use `'default=<obj>'` to set option's or optional argument's default value.**
+* **Use `'default=<obj>'` to override None as option's or optional argument's default value.**
 * **Use `'type=FileType(<mode>)'` for files. Accepts 'encoding', but 'newline' is None.**
 
 
@@ -1560,7 +1560,7 @@ Open
 ```python
 <file> = open(<path>, mode='r', encoding=None, newline=None)
 ```
-* **`'encoding=None'` means that the default encoding is used, which is platform dependent. Best practice is to use `'encoding="utf-8"'` whenever possible.**
+* **`'encoding=None'` means that the default encoding is used, which is platform dependent. Best practice is to use `'encoding="utf-8"'` until it becomes the default (Python 3.15).**
 * **`'newline=None'` means all different end of line combinations are converted to '\n' on read, while on write all '\n' characters are converted to system's default line separator.**
 * **`'newline=""'` means no conversions take place, but input is still broken into chunks by readline() and readlines() on every '\n', '\r' and '\r\n'.**
 
@@ -1817,7 +1817,7 @@ import csv
 <list>   = list(<reader>)                 # Returns a list of all remaining rows.
 ```
 * **Without the `'newline=""'` argument, every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'! For details about newline argument see [Open](#open).**
-* **To print the spreadsheet to the console use [Tabulate](#table) library.**
+* **To print the spreadsheet to the console use [Tabulate](#table) or PrettyTable library.**
 * **For XML and binary Excel files (xlsx, xlsm and xlsb) use [Pandas](#fileformats) library.**
 * **Reader accepts any iterator (or collection) of strings, not just files.**
 
diff --git a/index.html b/index.html
index 5564ab052..810fb1320 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>July 27, 2025</aside>
+    <aside>July 28, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -704,9 +704,9 @@
 
 
 <ul>
-<li><strong>Package is a collection of modules, but it can also define its own objects.</strong></li>
+<li><strong>Package is a collection of modules, but it can also define its own objects, classes, etc.</strong></li>
 <li><strong>On a filesystem this corresponds to a directory of Python files with an optional init script.</strong></li>
-<li><strong>Running <code class="python hljs"><span class="hljs-string">'import &lt;package&gt;'</span></code> does not automatically provide access to the package's modules unless they are explicitly imported in its init script.</strong></li>
+<li><strong>Running <code class="python hljs"><span class="hljs-string">'import &lt;package&gt;'</span></code> does not automatically provide access to the package's modules unless they are explicitly imported in the <code class="python hljs"><span class="hljs-string">'&lt;package&gt;/__init__.py'</span></code> script.</strong></li>
 <li><strong>Directory of the file that is passed to python command serves as a root of local imports.</strong></li>
 <li><strong>For relative imports use <code class="python hljs"><span class="hljs-string">'from .[…][&lt;pkg/module&gt;[.…]] import &lt;obj&gt;'</span></code>.</strong></li>
 </ul>
@@ -1007,7 +1007,7 @@
 <li><strong>Generators returned by the <a href="#generator">generator functions</a> and <a href="#comprehensions">generator expressions</a>.</strong></li>
 <li><strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong></li>
 </ul><div><h3 id="callable">Callable</h3><ul>
-<li><strong>All functions and classes have a call() method, hence are callable.</strong></li>
+<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(&lt;obj&gt;)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(&lt;obj&gt;, collections.abc.Callable)'</span></code> to check if object is callable. You can also just call the object and check if it raised TypeError.</strong></li>
 <li><strong>When this cheatsheet uses <code class="python hljs"><span class="hljs-string">'&lt;function&gt;'</span></code> as an argument, it means <code class="python hljs"><span class="hljs-string">'&lt;callable&gt;'</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>
@@ -1201,7 +1201,7 @@
 <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 a function block delimits scope).</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, 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> &lt;exception&gt;: ...
@@ -1290,7 +1290,7 @@
 </code></pre></div>
 
 <ul>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'file=sys.stderr'</span></code> for messages about errors.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'file=sys.stderr'</span></code> for messages about errors so they can be processed separately.</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 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
@@ -1327,7 +1327,7 @@
 
 <ul>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'help=&lt;str&gt;'</span></code> to set argument description that will be displayed in help message.</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'default=&lt;obj&gt;'</span></code> to set option's or optional argument's default value.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'default=&lt;obj&gt;'</span></code> to override None as option's or optional argument's default value.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'type=FileType(&lt;mode&gt;)'</span></code> for files. Accepts 'encoding', but 'newline' is None.</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">&lt;file&gt; = open(&lt;path&gt;, mode=<span class="hljs-string">'r'</span>, encoding=<span class="hljs-keyword">None</span>, newline=<span class="hljs-keyword">None</span>)
@@ -1335,7 +1335,7 @@
 
 
 <ul>
-<li><strong><code class="python hljs"><span class="hljs-string">'encoding=None'</span></code> means that the 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> whenever possible.</strong></li>
+<li><strong><code class="python hljs"><span class="hljs-string">'encoding=None'</span></code> means that the 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 all different end of line combinations are converted to '\n' on read, while on write all '\n' characters are converted to system's default line 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() and readlines() on every '\n', '\r' and '\r\n'.</strong></li>
 </ul>
@@ -1520,7 +1520,7 @@
 </code></pre>
 <ul>
 <li><strong>Without the <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'! For details about newline argument see <a href="#open">Open</a>.</strong></li>
-<li><strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong></li>
+<li><strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> or PrettyTable library.</strong></li>
 <li><strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#fileformats">Pandas</a> library.</strong></li>
 <li><strong>Reader accepts any iterator (or collection) of strings, not just files.</strong></li>
 </ul>
@@ -2936,7 +2936,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>July 27, 2025</aside>
+    <aside>July 28, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index c731b2413..b372a0711 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -23,7 +23,7 @@
     '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details about setting up the logger see <a href="#logging">Logging</a>.</strong>': '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(&lt;str&gt;)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details about the logger setup see Logging (p. 31).</strong>',
     '<strong>Functions report OS related errors by raising OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong>': '<strong>Functions report OS related errors by raising OSError or one of its subclasses (p. 23).</strong>',
     '<strong>Without the <code class="python hljs"><span class="hljs-string">\'newline=""\'</span></code> argument, every \'\\r\\n\' sequence that is embedded inside a quoted field will get converted to \'\\n\'! For details about newline argument see <a href="#open">Open</a>.</strong>': '<strong>Without the <code class="python hljs"><span class="hljs-string">\'newline=""\'</span></code> argument, every \'\\r\\n\' sequence that is embedded inside a quoted field will get converted to \'\\n\'! For details about newline arg. see Open (p. 22).</strong>',
-    '<strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong>': '<strong>To print the spreadsheet to the console use Tabulate library (p. 34).</strong>',
+    '<strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> or PrettyTable library.</strong>': '<strong>To print the spreadsheet to the console use Tabulate or PrettyTable library (p. 34).</strong>',
     '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#fileformats">Pandas</a> library.</strong>': '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use Pandas library (p. 46).</strong>',
     '<strong>Bools will be stored and returned as ints and dates as <a href="#encode">ISO formatted strings</a>.</strong>': '<strong>Bools will be stored and returned as ints and dates as ISO formatted strings (p. 9).</strong>',
     '<strong>ProcessPoolExecutor provides true parallelism but: everything sent to/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>': '<strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be pickable, 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>',

From 6a22233b1fbb49f8e3572e6bbe8f320545a0532c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 29 Jul 2025 04:04:07 +0200
Subject: [PATCH 171/186] Duck types, Array, Mview, Deque, Operator, Match,
 Logging

---
 README.md  | 74 +++++++++++++++++++++++++--------------------------
 index.html | 78 ++++++++++++++++++++++++++----------------------------
 parse.js   |  6 ++---
 3 files changed, 77 insertions(+), 81 deletions(-)

diff --git a/README.md b/README.md
index a88f0d99d..7ef74534b 100644
--- a/README.md
+++ b/README.md
@@ -1262,8 +1262,7 @@ class MyCollection:
 ```
 
 ### Sequence
-* **Only required methods are getitem() and len().**
-* **Getitem() should return an item at the passed index or raise IndexError.**
+* **Only required methods are getitem() and len(). Getitem() should return the item at the passed index or raise IndexError (this excludes dictionaries because they accept keys).**
 * **Iter() and contains() automatically work on any object that has getitem() defined.**
 * **Reversed() automatically works on any object that has getitem() and len() defined. It returns reversed iterator of object's items.**
 ```python
@@ -1287,8 +1286,8 @@ class MySequence:
 * **Passing ABC Iterable to isinstance() or issubclass() only checks whether object/class has special method iter(), while ABC Collection checks for iter(), contains() and len().**
 
 ### ABC Sequence
-* **It's a richer interface than the basic sequence.**
-* **Extending it generates iter(), contains(), reversed(), index() and count().**
+* **It's a richer interface than the basic sequence that also just requires getitem() and len().**
+* **Extending it generates iter(), contains(), reversed(), index() and count() special methods.**
 * **Unlike `'abc.Iterable'` and `'abc.Collection'`, it is not a duck type. That is why `'issubclass(MySequence, abc.Sequence)'` would return False even if MySequence had all the methods defined. It however recognizes list, tuple, range, str, bytes, bytearray, array, memoryview and deque, since they are registered as Sequence's virtual subclasses.**
 ```python
 from collections import abc
@@ -1885,7 +1884,7 @@ import sqlite3
 ### Read
 ```python
 <cursor> = <conn>.execute('<query>')           # Can raise a subclass of sqlite3.Error.
-<tuple>  = <cursor>.fetchone()                 # Returns next row. Also next(<cursor>).
+<tuple>  = <cursor>.fetchone()                 # Returns the next row. Also next(<cursor>).
 <list>   = <cursor>.fetchall()                 # Returns remaining rows. Also list(<cursor>).
 ```
 
@@ -1905,7 +1904,7 @@ with <conn>:                                   # Exits the block with commit() o
 ### Placeholders
 ```python
 <conn>.execute('<query>', <list/tuple>)        # Replaces every question mark with an item.
-<conn>.execute('<query>', <dict/namedtuple>)   # Replaces every :<key> with matching value.
+<conn>.execute('<query>', <dict/namedtuple>)   # Replaces every :<key> with a matching value.
 <conn>.executemany('<query>', <coll_of_coll>)  # Runs execute() once for each collection.
 ```
 * **Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).**
@@ -2029,21 +2028,21 @@ b'\x00\x01\x00\x02\x00\x00\x00\x03'
 
 Array
 -----
-**List that can only hold numbers of a predefined 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 with byteswap() method.**
+**List that can only hold numbers of a predefined 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 with byteswap() method.**
 
 ```python
 from array import array
 ```
 
 ```python
-<array> = array('<typecode>', <coll_of_nums>)  # Creates array from collection of numbers.
-<array> = array('<typecode>', <bytes>)         # Writes passed bytes to array's memory.
+<array> = array('<typecode>', <coll_of_nums>)  # Creates an array from collection of numbers.
+<array> = array('<typecode>', <bytes>)         # Writes passed bytes to the array's memory.
 <array> = array('<typecode>', <array>)         # Treats passed array as a sequence of numbers.
-<array>.fromfile(<file>, n_items)              # Appends file's contents to array's memory.
+<array>.fromfile(<file>, n_items)              # Appends file contents to the array's memory.
 ```
 
 ```python
-<bytes> = bytes(<array>)                       # Returns a copy of array's memory.
+<bytes> = bytes(<array>)                       # Returns a copy of array's memory as bytes.
 <file>.write(<array>)                          # Writes array's memory to the binary file.
 ```
 
@@ -2054,7 +2053,7 @@ Memory View
 
 ```python
 <mview> = memoryview(<bytes/bytearray/array>)  # Immutable if bytes is passed, else mutable.
-<obj>   = <mview>[index]                       # Returns int/float. Bytes if format is 'c'.
+<obj>   = <mview>[index]                       # Returns ints/floats. Bytes if format is 'c'.
 <mview> = <mview>[<slice>]                     # Returns memoryview with rearranged elements.
 <mview> = <mview>.cast('<typecode>')           # Only works between B/b/c and other types.
 <mview>.release()                              # Releases memory buffer of the base object.
@@ -2069,7 +2068,7 @@ Memory View
 
 ```python
 <list>  = list(<mview>)                        # Returns a list of ints, floats or bytes.
-<str>   = str(<mview>, 'utf-8')                # Treats memoryview as a bytes object.
+<str>   = str(<mview>, 'utf-8')                # Treats passed memoryview as a bytes object.
 <str>   = <mview>.hex()                        # Returns hex pairs. Accepts `sep=<str>`.
 ```
 
@@ -2085,15 +2084,15 @@ from collections import deque
 ```python
 <deque> = deque(<collection>)                  # Use `maxlen=<int>` to set size limit.
 <deque>.appendleft(<el>)                       # Opposite element is dropped if full.
-<deque>.extendleft(<collection>)               # Passed collection gets reversed.
-<deque>.rotate(n=1)                            # Last element becomes first.
+<deque>.extendleft(<collection>)               # Appends elements in reversed order.
+<deque>.rotate(n=1)                            # Last element becomes the first one.
 <el> = <deque>.popleft()                       # Raises IndexError if deque is empty.
 ```
 
 
 Operator
 --------
-**Module of functions that provide the functionality of operators. Functions are grouped by operator precedence, from least to most binding. Functions and operators in lines 1, 3 and 5 are also ordered by precedence within a group.**
+**Module of functions that provide the functionality of operators. Functions are grouped by operator precedence, from least to most binding. Functions and operators in first, third and fifth line are also ordered by precedence within a group.**
 ```python
 import operator as op
 ```
@@ -2101,11 +2100,11 @@ import operator as op
 ```python
 <bool> = op.not_(<obj>)                                        # or, and, not (or/and missing)
 <bool> = op.eq/ne/lt/ge/is_/is_not/contains(<obj>, <obj>)      # ==, !=, <, >=, is, is not, in
-<obj>  = op.or_/xor/and_(<int/set>, <int/set>)                 # |, ^, &
-<int>  = op.lshift/rshift(<int>, <int>)                        # <<, >>
-<obj>  = op.add/sub/mul/truediv/floordiv/mod(<obj>, <obj>)     # +, -, *, /, //, %
-<num>  = op.neg/invert(<num>)                                  # -, ~
-<num>  = op.pow(<num>, <num>)                                  # **
+<obj>  = op.or_/xor/and_(<int/set>, <int/set>)                 # |, ^, & (sorted by precedence)
+<int>  = op.lshift/rshift(<int>, <int>)                        # <<, >> (i.e. <int> << n_bits)
+<obj>  = op.add/sub/mul/truediv/floordiv/mod(<obj>, <obj>)     # +, -, *, /, //, % (two groups)
+<num>  = op.neg/invert(<num>)                                  # -, ~ (negate and bitwise not)
+<num>  = op.pow(<num>, <num>)                                  # ** (pow() accepts 3 arguments)
 <func> = op.itemgetter/attrgetter/methodcaller(<obj> [, ...])  # [index/key], .name, .name([…])
 ```
 
@@ -2137,16 +2136,15 @@ match <object/expression>:
 <wildcard_patt> = _                                # Matches any object. Useful in last case.
 <capture_patt>  = <name>                           # Matches any object and binds it to name.
 <as_pattern>    = <pattern> as <name>              # Binds match to name. Also <type>(<name>).
-<or_pattern>    = <pattern> | <pattern> [| ...]    # Matches any of the patterns.
-<sequence_patt> = [<pattern>, ...]                 # Matches sequence with matching items.
-<mapping_patt>  = {<value_pattern>: <patt>, ...}   # Matches dictionary with matching items.
-<class_pattern> = <type>(<attr_name>=<patt>, ...)  # Matches object with matching attributes.
+<or_pattern>    = <pattern> | <pattern> [| ...]    # Matches if any of listed patterns match.
+<sequence_patt> = [<pattern>, ...]                 # Matches a sequence. All items must match.
+<mapping_patt>  = {<value_pattern>: <patt>, ...}   # Matches a dict that has matching items.
+<class_pattern> = <type>(<attr_name>=<patt>, ...)  # Matches an object if attributes match.
 ```
-* **Sequence pattern can also be written as a tuple, i.e. `'(<patt_1>, [...])'`.**
+* **Sequence pattern can also be written as a tuple, i.e. `'(<pattern_1>, [...])'`.**
 * **Use `'*<name>'` and `'**<name>'` in sequence/mapping patterns to bind remaining items.**
 * **Sequence pattern must match all items of the collection, while mapping pattern does not.**
 * **Patterns can be surrounded with brackets to override precedence (`'|'` > `'as'` > `','`).**
-* **Built-in types allow a single positional pattern that is matched against the entire object.**
 * **All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement.**
 
 ### Example
@@ -2169,9 +2167,9 @@ import logging as log
 
 ```python
 log.basicConfig(filename=<path>, level='DEBUG')   # Configures the root logger (see Setup).
-log.debug/info/warning/error/critical(<str>)      # Sends message to the root logger.
-<Logger> = log.getLogger(__name__)                # Returns logger named after the module.
-<Logger>.<level>(<str>)                           # Sends message to the logger.
+log.debug/info/warning/error/critical(<str>)      # Sends passed message to the root logger.
+<Logger> = log.getLogger(__name__)                # Returns a logger named after the module.
+<Logger>.<level>(<str>)                           # Sends the message. Same levels as above.
 <Logger>.exception(<str>)                         # Error() that appends caught exception.
 ```
 
@@ -2186,11 +2184,11 @@ log.basicConfig(
 ```
 
 ```python
-<Formatter> = log.Formatter('<format>')           # Creates a Formatter.
-<Handler> = log.FileHandler(<path>, mode='a')     # Creates a Handler. Also `encoding=None`.
-<Handler>.setFormatter(<Formatter>)               # Adds Formatter to the Handler.
-<Handler>.setLevel(<int/str>)                     # Processes all messages by default.
-<Logger>.addHandler(<Handler>)                    # Adds Handler to the Logger.
+<Formatter> = log.Formatter('<format>')           # Formats messages according to format str.
+<Handler> = log.FileHandler(<path>, mode='a')     # Creates a handler. Also `encoding=None`.
+<Handler>.setFormatter(<Formatter>)               # Assigns the formatter to the handler.
+<Handler>.setLevel(<int/str>)                     # It will process all messages by default.
+<Logger>.addHandler(<Handler>)                    # Appends handler to logger's 'handlers'.
 <Logger>.setLevel(<int/str>)                      # What is sent to its/ancestors' handlers.
 <Logger>.propagate = <bool>                       # Cuts off ancestors' handlers if False.
 ```
@@ -2333,9 +2331,9 @@ import asyncio as aio
 ```python
 import asyncio, collections, curses, curses.textpad, enum, random
 
-P = collections.namedtuple('P', 'x y')     # Position
-D = enum.Enum('D', 'n e s w')              # Direction
-W, H = 15, 7                               # Width, Height
+P = collections.namedtuple('P', 'x y')     # Position (x and y coordinates).
+D = enum.Enum('D', 'n e s w')              # Direction (north, east, etc.).
+W, H = 15, 7                               # Width and height constants.
 
 def main(screen):
     curses.curs_set(0)                     # Makes cursor invisible.
diff --git a/index.html b/index.html
index 810fb1320..89831db5b 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>July 28, 2025</aside>
+    <aside>July 29, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1085,8 +1085,7 @@
 
 
 <div><h3 id="sequence">Sequence</h3><ul>
-<li><strong>Only required methods are getitem() and len().</strong></li>
-<li><strong>Getitem() should return an item at the passed index or raise IndexError.</strong></li>
+<li><strong>Only required methods are getitem() and len(). Getitem() should return the item at the passed index or raise IndexError (this excludes dictionaries because they accept keys).</strong></li>
 <li><strong>Iter() and contains() automatically work on any object that has getitem() defined.</strong></li>
 <li><strong>Reversed() automatically works on any object that has getitem() and len() 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>
@@ -1114,8 +1113,8 @@
 
 
 <div><h3 id="abcsequence">ABC Sequence</h3><ul>
-<li><strong>It's a richer interface than the basic sequence.</strong></li>
-<li><strong>Extending it generates iter(), contains(), reversed(), index() and count().</strong></li>
+<li><strong>It's a richer interface than the basic sequence that also just requires getitem() and len().</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 <code class="python hljs"><span class="hljs-string">'issubclass(MySequence, abc.Sequence)'</span></code> would return False even if MySequence had all the methods defined. It however recognizes list, tuple, range, str, 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
 
@@ -1576,7 +1575,7 @@
 
 
 <div><h3 id="read">Read</h3><pre><code class="python language-python hljs">&lt;cursor&gt; = &lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>)           <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span>
-&lt;tuple&gt;  = &lt;cursor&gt;.fetchone()                 <span class="hljs-comment"># Returns next row. Also next(&lt;cursor&gt;).</span>
+&lt;tuple&gt;  = &lt;cursor&gt;.fetchone()                 <span class="hljs-comment"># Returns the next row. Also next(&lt;cursor&gt;).</span>
 &lt;list&gt;   = &lt;cursor&gt;.fetchall()                 <span class="hljs-comment"># Returns remaining rows. Also list(&lt;cursor&gt;).</span>
 </code></pre></div>
 
@@ -1590,7 +1589,7 @@
 </code></pre></div>
 
 <div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs">&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;list/tuple&gt;)        <span class="hljs-comment"># Replaces every question mark with an item.</span>
-&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces every :&lt;key&gt; with matching value.</span>
+&lt;conn&gt;.execute(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;dict/namedtuple&gt;)   <span class="hljs-comment"># Replaces every :&lt;key&gt; with a matching value.</span>
 &lt;conn&gt;.executemany(<span class="hljs-string">'&lt;query&gt;'</span>, &lt;coll_of_coll&gt;)  <span class="hljs-comment"># Runs execute() once for each collection.</span>
 </code></pre></div>
 
@@ -1693,20 +1692,20 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<div><h2 id="array"><a href="#array" name="array">#</a>Array</h2><p><strong>List that can only hold numbers of a predefined 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 with 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
+<div><h2 id="array"><a href="#array" name="array">#</a>Array</h2><p><strong>List that can only hold numbers of a predefined 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 with 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">&lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;coll_of_nums&gt;)  <span class="hljs-comment"># Creates array from collection of numbers.</span>
-&lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;bytes&gt;)         <span class="hljs-comment"># Writes passed bytes to array's memory.</span>
+<pre><code class="python language-python hljs">&lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;coll_of_nums&gt;)  <span class="hljs-comment"># Creates an array from collection of numbers.</span>
+&lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;bytes&gt;)         <span class="hljs-comment"># Writes passed bytes to the array's memory.</span>
 &lt;array&gt; = array(<span class="hljs-string">'&lt;typecode&gt;'</span>, &lt;array&gt;)         <span class="hljs-comment"># Treats passed array as a sequence of numbers.</span>
-&lt;array&gt;.fromfile(&lt;file&gt;, n_items)              <span class="hljs-comment"># Appends file's contents to array's memory.</span>
+&lt;array&gt;.fromfile(&lt;file&gt;, n_items)              <span class="hljs-comment"># Appends file contents to the array's memory.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;bytes&gt; = bytes(&lt;array&gt;)                       <span class="hljs-comment"># Returns a copy of array's memory.</span>
+<pre><code class="python language-python hljs">&lt;bytes&gt; = bytes(&lt;array&gt;)                       <span class="hljs-comment"># Returns a copy of array's memory as bytes.</span>
 &lt;file&gt;.write(&lt;array&gt;)                          <span class="hljs-comment"># Writes array's memory to the 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">&lt;mview&gt; = memoryview(&lt;bytes/bytearray/array&gt;)  <span class="hljs-comment"># Immutable if bytes is passed, else mutable.</span>
-&lt;obj&gt;   = &lt;mview&gt;[index]                       <span class="hljs-comment"># Returns int/float. Bytes if format is 'c'.</span>
+&lt;obj&gt;   = &lt;mview&gt;[index]                       <span class="hljs-comment"># Returns ints/floats. Bytes if format is 'c'.</span>
 &lt;mview&gt; = &lt;mview&gt;[&lt;slice&gt;]                     <span class="hljs-comment"># Returns memoryview with rearranged elements.</span>
 &lt;mview&gt; = &lt;mview&gt;.cast(<span class="hljs-string">'&lt;typecode&gt;'</span>)           <span class="hljs-comment"># Only works between B/b/c and other types.</span>
 &lt;mview&gt;.release()                              <span class="hljs-comment"># Releases memory buffer of the base object.</span>
@@ -1719,7 +1718,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;file&gt;.write(&lt;mview&gt;)                          <span class="hljs-comment"># Writes `bytes(&lt;mview&gt;)` to the binary file.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;list&gt;  = list(&lt;mview&gt;)                        <span class="hljs-comment"># Returns a list of ints, floats or bytes.</span>
-&lt;str&gt;   = str(&lt;mview&gt;, <span class="hljs-string">'utf-8'</span>)                <span class="hljs-comment"># Treats memoryview as a bytes object.</span>
+&lt;str&gt;   = str(&lt;mview&gt;, <span class="hljs-string">'utf-8'</span>)                <span class="hljs-comment"># Treats passed memoryview as a bytes object.</span>
 &lt;str&gt;   = &lt;mview&gt;.hex()                        <span class="hljs-comment"># Returns hex pairs. Accepts `sep=&lt;str&gt;`.</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
@@ -1728,21 +1727,21 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <pre><code class="python language-python hljs">&lt;deque&gt; = deque(&lt;collection&gt;)                  <span class="hljs-comment"># Use `maxlen=&lt;int&gt;` to set size limit.</span>
 &lt;deque&gt;.appendleft(&lt;el&gt;)                       <span class="hljs-comment"># Opposite element is dropped if full.</span>
-&lt;deque&gt;.extendleft(&lt;collection&gt;)               <span class="hljs-comment"># Passed collection gets reversed.</span>
-&lt;deque&gt;.rotate(n=<span class="hljs-number">1</span>)                            <span class="hljs-comment"># Last element becomes first.</span>
+&lt;deque&gt;.extendleft(&lt;collection&gt;)               <span class="hljs-comment"># Appends elements in reversed order.</span>
+&lt;deque&gt;.rotate(n=<span class="hljs-number">1</span>)                            <span class="hljs-comment"># Last element becomes the first one.</span>
 &lt;el&gt; = &lt;deque&gt;.popleft()                       <span class="hljs-comment"># Raises IndexError if deque is empty.</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 and operators in lines 1, 3 and 5 are also ordered by precedence within a group.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> operator <span class="hljs-keyword">as</span> op
+<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 and operators in first, third and fifth line are also ordered by precedence within a group.</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">&lt;bool&gt; = op.not_(&lt;obj&gt;)                                        <span class="hljs-comment"># or, and, not (or/and missing)</span>
 &lt;bool&gt; = op.eq/ne/lt/ge/is_/is_not/contains(&lt;obj&gt;, &lt;obj&gt;)      <span class="hljs-comment"># ==, !=, &lt;, &gt;=, is, is not, in</span>
-&lt;obj&gt;  = op.or_/xor/and_(&lt;int/set&gt;, &lt;int/set&gt;)                 <span class="hljs-comment"># |, ^, &amp;</span>
-&lt;int&gt;  = op.lshift/rshift(&lt;int&gt;, &lt;int&gt;)                        <span class="hljs-comment"># &lt;&lt;, &gt;&gt;</span>
-&lt;obj&gt;  = op.add/sub/mul/truediv/floordiv/mod(&lt;obj&gt;, &lt;obj&gt;)     <span class="hljs-comment"># +, -, *, /, //, %</span>
-&lt;num&gt;  = op.neg/invert(&lt;num&gt;)                                  <span class="hljs-comment"># -, ~</span>
-&lt;num&gt;  = op.pow(&lt;num&gt;, &lt;num&gt;)                                  <span class="hljs-comment"># **</span>
+&lt;obj&gt;  = op.or_/xor/and_(&lt;int/set&gt;, &lt;int/set&gt;)                 <span class="hljs-comment"># |, ^, &amp; (sorted by precedence)</span>
+&lt;int&gt;  = op.lshift/rshift(&lt;int&gt;, &lt;int&gt;)                        <span class="hljs-comment"># &lt;&lt;, &gt;&gt; (i.e. &lt;int&gt; &lt;&lt; n_bits)</span>
+&lt;obj&gt;  = op.add/sub/mul/truediv/floordiv/mod(&lt;obj&gt;, &lt;obj&gt;)     <span class="hljs-comment"># +, -, *, /, //, % (two groups)</span>
+&lt;num&gt;  = op.neg/invert(&lt;num&gt;)                                  <span class="hljs-comment"># -, ~ (negate and bitwise not)</span>
+&lt;num&gt;  = op.pow(&lt;num&gt;, &lt;num&gt;)                                  <span class="hljs-comment"># ** (pow() accepts 3 arguments)</span>
 &lt;func&gt; = op.itemgetter/attrgetter/methodcaller(&lt;obj&gt; [, ...])  <span class="hljs-comment"># [index/key], .name, .name([…])</span>
 </code></pre>
 <pre><code class="python language-python hljs">elementwise_sum  = map(op.add, list_a, list_b)
@@ -1766,18 +1765,17 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 &lt;wildcard_patt&gt; = _                                <span class="hljs-comment"># Matches any object. Useful in last case.</span>
 &lt;capture_patt&gt;  = &lt;name&gt;                           <span class="hljs-comment"># Matches any object and binds it to name.</span>
 &lt;as_pattern&gt;    = &lt;pattern&gt; <span class="hljs-keyword">as</span> &lt;name&gt;              <span class="hljs-comment"># Binds match to name. Also &lt;type&gt;(&lt;name&gt;).</span>
-&lt;or_pattern&gt;    = &lt;pattern&gt; | &lt;pattern&gt; [| ...]    <span class="hljs-comment"># Matches any of the patterns.</span>
-&lt;sequence_patt&gt; = [&lt;pattern&gt;, ...]                 <span class="hljs-comment"># Matches sequence with matching items.</span>
-&lt;mapping_patt&gt;  = {&lt;value_pattern&gt;: &lt;patt&gt;, ...}   <span class="hljs-comment"># Matches dictionary with matching items.</span>
-&lt;class_pattern&gt; = &lt;type&gt;(&lt;attr_name&gt;=&lt;patt&gt;, ...)  <span class="hljs-comment"># Matches object with matching attributes.</span>
+&lt;or_pattern&gt;    = &lt;pattern&gt; | &lt;pattern&gt; [| ...]    <span class="hljs-comment"># Matches if any of listed patterns match.</span>
+&lt;sequence_patt&gt; = [&lt;pattern&gt;, ...]                 <span class="hljs-comment"># Matches a sequence. All items must match.</span>
+&lt;mapping_patt&gt;  = {&lt;value_pattern&gt;: &lt;patt&gt;, ...}   <span class="hljs-comment"># Matches a dict that has matching items.</span>
+&lt;class_pattern&gt; = &lt;type&gt;(&lt;attr_name&gt;=&lt;patt&gt;, ...)  <span class="hljs-comment"># Matches an object if attributes match.</span>
 </code></pre></div>
 
 <ul>
-<li><strong>Sequence pattern can also be written as a tuple, i.e. <code class="python hljs"><span class="hljs-string">'(&lt;patt_1&gt;, [...])'</span></code>.</strong></li>
+<li><strong>Sequence pattern can also be written as a tuple, i.e. <code class="python hljs"><span class="hljs-string">'(&lt;pattern_1&gt;, [...])'</span></code>.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'*&lt;name&gt;'</span></code> and <code class="python hljs"><span class="hljs-string">'**&lt;name&gt;'</span></code> in sequence/mapping patterns to bind remaining items.</strong></li>
 <li><strong>Sequence pattern must match all items of the collection, while mapping pattern does not.</strong></li>
 <li><strong>Patterns can be surrounded with brackets to override precedence (<code class="python hljs"><span class="hljs-string">'|'</span></code> &gt; <code class="python hljs"><span class="hljs-string">'as'</span></code> &gt; <code class="python hljs"><span class="hljs-string">','</span></code>).</strong></li>
-<li><strong>Built-in types allow a single positional pattern that is matched against the entire object.</strong></li>
 <li><strong>All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement.</strong></li>
 </ul>
 <div><h3 id="example-2">Example</h3><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path
@@ -1793,9 +1791,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 <pre><code class="python language-python hljs">log.basicConfig(filename=&lt;path&gt;, level=<span class="hljs-string">'DEBUG'</span>)   <span class="hljs-comment"># Configures the root logger (see Setup).</span>
-log.debug/info/warning/error/critical(&lt;str&gt;)      <span class="hljs-comment"># Sends message to the root logger.</span>
-&lt;Logger&gt; = log.getLogger(__name__)                <span class="hljs-comment"># Returns logger named after the module.</span>
-&lt;Logger&gt;.&lt;level&gt;(&lt;str&gt;)                           <span class="hljs-comment"># Sends message to the logger.</span>
+log.debug/info/warning/error/critical(&lt;str&gt;)      <span class="hljs-comment"># Sends passed message to the root logger.</span>
+&lt;Logger&gt; = log.getLogger(__name__)                <span class="hljs-comment"># Returns a logger named after the module.</span>
+&lt;Logger&gt;.&lt;level&gt;(&lt;str&gt;)                           <span class="hljs-comment"># Sends the message. Same levels as above.</span>
 &lt;Logger&gt;.exception(&lt;str&gt;)                         <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(
@@ -1806,11 +1804,11 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 )
 </code></pre></div>
 
-<pre><code class="python language-python hljs">&lt;Formatter&gt; = log.Formatter(<span class="hljs-string">'&lt;format&gt;'</span>)           <span class="hljs-comment"># Creates a Formatter.</span>
-&lt;Handler&gt; = log.FileHandler(&lt;path&gt;, mode=<span class="hljs-string">'a'</span>)     <span class="hljs-comment"># Creates a Handler. Also `encoding=None`.</span>
-&lt;Handler&gt;.setFormatter(&lt;Formatter&gt;)               <span class="hljs-comment"># Adds Formatter to the Handler.</span>
-&lt;Handler&gt;.setLevel(&lt;int/str&gt;)                     <span class="hljs-comment"># Processes all messages by default.</span>
-&lt;Logger&gt;.addHandler(&lt;Handler&gt;)                    <span class="hljs-comment"># Adds Handler to the Logger.</span>
+<pre><code class="python language-python hljs">&lt;Formatter&gt; = log.Formatter(<span class="hljs-string">'&lt;format&gt;'</span>)           <span class="hljs-comment"># Formats messages according to format str.</span>
+&lt;Handler&gt; = log.FileHandler(&lt;path&gt;, mode=<span class="hljs-string">'a'</span>)     <span class="hljs-comment"># Creates a handler. Also `encoding=None`.</span>
+&lt;Handler&gt;.setFormatter(&lt;Formatter&gt;)               <span class="hljs-comment"># Assigns the formatter to the handler.</span>
+&lt;Handler&gt;.setLevel(&lt;int/str&gt;)                     <span class="hljs-comment"># It will process all messages by default.</span>
+&lt;Logger&gt;.addHandler(&lt;Handler&gt;)                    <span class="hljs-comment"># Appends handler to logger's 'handlers'.</span>
 &lt;Logger&gt;.setLevel(&lt;int/str&gt;)                      <span class="hljs-comment"># What is sent to its/ancestors' handlers.</span>
 &lt;Logger&gt;.propagate = &lt;bool&gt;                       <span class="hljs-comment"># Cuts off ancestors' handlers if False.</span>
 </code></pre>
@@ -1921,9 +1919,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </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, collections, curses, curses.textpad, enum, random
 
-P = collections.namedtuple(<span class="hljs-string">'P'</span>, <span class="hljs-string">'x y'</span>)     <span class="hljs-comment"># Position</span>
-D = enum.Enum(<span class="hljs-string">'D'</span>, <span class="hljs-string">'n e s w'</span>)              <span class="hljs-comment"># Direction</span>
-W, H = <span class="hljs-number">15</span>, <span class="hljs-number">7</span>                               <span class="hljs-comment"># Width, Height</span>
+P = collections.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 constants.</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 cursor invisible.</span>
@@ -2936,7 +2934,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>July 28, 2025</aside>
+    <aside>July 29, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/parse.js b/parse.js
index 03d06b4fd..668b799e9 100755
--- a/parse.js
+++ b/parse.js
@@ -120,9 +120,9 @@ const MATCH_EXAMPLE =
 const COROUTINES =
   '<span class="hljs-keyword">import</span> asyncio, collections, curses, curses.textpad, enum, random\n' +
   '\n' +
-  'P = collections.namedtuple(<span class="hljs-string">\'P\'</span>, <span class="hljs-string">\'x y\'</span>)     <span class="hljs-comment"># Position</span>\n' +
-  'D = enum.Enum(<span class="hljs-string">\'D\'</span>, <span class="hljs-string">\'n e s w\'</span>)              <span class="hljs-comment"># Direction</span>\n' +
-  'W, H = <span class="hljs-number">15</span>, <span class="hljs-number">7</span>                               <span class="hljs-comment"># Width, Height</span>\n' +
+  'P = collections.namedtuple(<span class="hljs-string">\'P\'</span>, <span class="hljs-string">\'x y\'</span>)     <span class="hljs-comment"># Position (x and y coordinates).</span>\n' +
+  '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>\n' +
+  'W, H = <span class="hljs-number">15</span>, <span class="hljs-number">7</span>                               <span class="hljs-comment"># Width and height constants.</span>\n' +
   '\n' +
   '<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">(screen)</span>:</span>\n' +
   '    curses.curs_set(<span class="hljs-number">0</span>)                     <span class="hljs-comment"># Makes cursor invisible.</span>\n' +

From 41c9e9f20abdb64f1b95391d0ae300c3088c2b3d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 29 Jul 2025 04:09:11 +0200
Subject: [PATCH 172/186] Iterable duck types

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 7ef74534b..21e85fb4c 100644
--- a/README.md
+++ b/README.md
@@ -1286,7 +1286,7 @@ class MySequence:
 * **Passing ABC Iterable to isinstance() or issubclass() only checks whether object/class has special method iter(), while ABC Collection checks for iter(), contains() and len().**
 
 ### ABC Sequence
-* **It's a richer interface than the basic sequence that also just requires getitem() and len().**
+* **It's a richer interface than the basic sequence that also requires just getitem() and len().**
 * **Extending it generates iter(), contains(), reversed(), index() and count() special methods.**
 * **Unlike `'abc.Iterable'` and `'abc.Collection'`, it is not a duck type. That is why `'issubclass(MySequence, abc.Sequence)'` would return False even if MySequence had all the methods defined. It however recognizes list, tuple, range, str, bytes, bytearray, array, memoryview and deque, since they are registered as Sequence's virtual subclasses.**
 ```python
diff --git a/index.html b/index.html
index 89831db5b..731f6878b 100644
--- a/index.html
+++ b/index.html
@@ -1113,7 +1113,7 @@
 
 
 <div><h3 id="abcsequence">ABC Sequence</h3><ul>
-<li><strong>It's a richer interface than the basic sequence that also just requires getitem() and len().</strong></li>
+<li><strong>It's a richer interface than the basic sequence that also requires just getitem() and len().</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 <code class="python hljs"><span class="hljs-string">'issubclass(MySequence, abc.Sequence)'</span></code> would return False even if MySequence had all the methods defined. It however recognizes list, tuple, range, str, 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

From 6e3e2a7dcec19f4787aa1ab877ad39ed345446f9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 29 Jul 2025 06:08:42 +0200
Subject: [PATCH 173/186] Enum

---
 README.md  | 2 +-
 index.html | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 21e85fb4c..f4ff541b1 100644
--- a/README.md
+++ b/README.md
@@ -1331,7 +1331,7 @@ from enum import Enum, auto
 class <enum_name>(Enum):
     <member_name> = auto()              # Increment of the last numeric value or 1.
     <member_name> = <value>             # Values don't have to be hashable or unique.
-    <member_name> = <el_1>, <el_2>      # Values can be collections, like this tuple.
+    <member_name> = <el_1>, <el_2>      # Values can be collections. This is a tuple.
 ```
 * **Methods receive the member they were called on as the 'self' argument.**
 * **Accessing a member named after a reserved keyword causes SyntaxError.**
diff --git a/index.html b/index.html
index 731f6878b..a859f7eae 100644
--- a/index.html
+++ b/index.html
@@ -1149,7 +1149,7 @@
 <pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> &lt;<span class="hljs-title">enum_name</span>&gt;<span class="hljs-params">(Enum)</span>:</span>
     &lt;member_name&gt; = auto()              <span class="hljs-comment"># Increment of the last numeric value or 1.</span>
     &lt;member_name&gt; = &lt;value&gt;             <span class="hljs-comment"># Values don't have to be hashable or unique.</span>
-    &lt;member_name&gt; = &lt;el_1&gt;, &lt;el_2&gt;      <span class="hljs-comment"># Values can be collections, like this tuple.</span>
+    &lt;member_name&gt; = &lt;el_1&gt;, &lt;el_2&gt;      <span class="hljs-comment"># Values can be collections. This is a tuple.</span>
 </code></pre>
 <ul>
 <li><strong>Methods receive the member they were called on as the 'self' argument.</strong></li>

From b45b945599ceb42a1c9f14c23c55e82ae2d63dfd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 29 Jul 2025 17:02:36 +0200
Subject: [PATCH 174/186] Duck types, Open, Paths

---
 README.md  | 6 +++---
 index.html | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index f4ff541b1..bd119244b 100644
--- a/README.md
+++ b/README.md
@@ -1093,7 +1093,7 @@ Duck Types
 **A duck type is an implicit type that prescribes a set of special methods. Any object that has those methods defined is considered a member of that duck type.**
 
 ### Comparable
-* **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`. That means all user-defined objects compare not equal by default (because id() returns object's memory address that is unique during its lifetime).**
+* **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`. That means all user-defined objects compare not equal by default (because id() returns object's memory address that is guaranteed to be unique).**
 * **Only the left side object has eq() method called, unless it returns NotImplemented, in which case the right object is consulted. False is returned if both return NotImplemented.**
 * **Ne() automatically works on any object that has eq() defined.**
 
@@ -1591,7 +1591,7 @@ Open
 <str/bytes> = <file>.read(size=-1)  # Reads 'size' chars/bytes or until the EOF.
 <str/bytes> = <file>.readline()     # Returns a line or empty string/bytes on EOF.
 <list>      = <file>.readlines()    # Returns remaining lines. Also list(<file>).
-<str/bytes> = next(<file>)          # Uses read-ahead buffer. Don't mix with above.
+<str/bytes> = next(<file>)          # Returns a line using a read-ahead buffer.
 ```
 
 ```python
@@ -1657,7 +1657,7 @@ from pathlib import Path
 
 ```python
 <iter> = os.scandir(path='.')       # Returns DirEntry objects located at the path.
-<str>  = <DirEntry>.path            # Returns the whole path (relative by default).
+<str>  = <DirEntry>.path            # Returns object's path (relative by default).
 <str>  = <DirEntry>.name            # Returns path's final component as a string.
 <file> = open(<DirEntry>)           # Opens the file and returns its file object.
 ```
diff --git a/index.html b/index.html
index a859f7eae..57f81c261 100644
--- a/index.html
+++ b/index.html
@@ -926,7 +926,7 @@
 </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 has those methods defined 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 unique during its lifetime).</strong></li>
+<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. False is returned if both return NotImplemented.</strong></li>
 <li><strong>Ne() 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>
@@ -1365,7 +1365,7 @@
 <pre><code class="python language-python hljs">&lt;str/bytes&gt; = &lt;file&gt;.read(size=<span class="hljs-number">-1</span>)  <span class="hljs-comment"># Reads 'size' chars/bytes or until the EOF.</span>
 &lt;str/bytes&gt; = &lt;file&gt;.readline()     <span class="hljs-comment"># Returns a line or empty string/bytes on EOF.</span>
 &lt;list&gt;      = &lt;file&gt;.readlines()    <span class="hljs-comment"># Returns remaining lines. Also list(&lt;file&gt;).</span>
-&lt;str/bytes&gt; = next(&lt;file&gt;)          <span class="hljs-comment"># Uses read-ahead buffer. Don't mix with above.</span>
+&lt;str/bytes&gt; = next(&lt;file&gt;)          <span class="hljs-comment"># Returns a line using a read-ahead buffer.</span>
 </code></pre>
 <pre><code class="python language-python hljs">&lt;file&gt;.write(&lt;str/bytes&gt;)           <span class="hljs-comment"># Writes a str or bytes object to write buffer.</span>
 &lt;file&gt;.writelines(&lt;collection&gt;)     <span class="hljs-comment"># Writes a coll. of strings or bytes objects.</span>
@@ -1408,7 +1408,7 @@
 &lt;num&gt;  = &lt;stat&gt;.st_mtime/st_size/…  <span class="hljs-comment"># Returns modification time, size in bytes, etc.</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">&lt;iter&gt; = os.scandir(path=<span class="hljs-string">'.'</span>)       <span class="hljs-comment"># Returns DirEntry objects located at the path.</span>
-&lt;str&gt;  = &lt;DirEntry&gt;.path            <span class="hljs-comment"># Returns the whole path (relative by default).</span>
+&lt;str&gt;  = &lt;DirEntry&gt;.path            <span class="hljs-comment"># Returns object's path (relative by default).</span>
 &lt;str&gt;  = &lt;DirEntry&gt;.name            <span class="hljs-comment"># Returns path's final component as a string.</span>
 &lt;file&gt; = open(&lt;DirEntry&gt;)           <span class="hljs-comment"># Opens the file and returns its file object.</span>
 </code></pre></div>

From 566f27e2aebb98d400a8f3d529da73811c38754f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Tue, 29 Jul 2025 19:29:04 +0200
Subject: [PATCH 175/186] Imports, Iterable duck types

---
 README.md  | 4 ++--
 index.html | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/README.md b/README.md
index bd119244b..c3a79f6ab 100644
--- a/README.md
+++ b/README.md
@@ -823,7 +823,7 @@ import <module>            # Imports a built-in or '<module>.py'.
 import <package>           # Imports a built-in or '<package>/__init__.py'.
 import <package>.<module>  # Imports a built-in or '<package>/<module>.py'.
 ```
-* **Package is a collection of modules, but it can also define its own objects, classes, etc.**
+* **Package is a collection of modules, but it can also define its own functions, classes, etc.**
 * **On a filesystem this corresponds to a directory of Python files with an optional init script.**
 * **Running `'import <package>'` does not automatically provide access to the package's modules unless they are explicitly imported in the `'<package>/__init__.py'` script.**
 * **Directory of the file that is passed to python command serves as a root of local imports.**
@@ -1262,7 +1262,7 @@ class MyCollection:
 ```
 
 ### Sequence
-* **Only required methods are getitem() and len(). Getitem() should return the item at the passed index or raise IndexError (this excludes dictionaries because they accept keys).**
+* **Only required methods are getitem() and len(). Getitem() should return the item at the passed index or raise IndexError (it may also support negative indices and/or slices).**
 * **Iter() and contains() automatically work on any object that has getitem() defined.**
 * **Reversed() automatically works on any object that has getitem() and len() defined. It returns reversed iterator of object's items.**
 ```python
diff --git a/index.html b/index.html
index 57f81c261..6a9521e7c 100644
--- a/index.html
+++ b/index.html
@@ -704,7 +704,7 @@
 
 
 <ul>
-<li><strong>Package is a collection of modules, but it can also define its own objects, classes, etc.</strong></li>
+<li><strong>Package is a collection of modules, but it can also define its own functions, classes, etc.</strong></li>
 <li><strong>On a filesystem this corresponds to a directory of Python files with an optional init script.</strong></li>
 <li><strong>Running <code class="python hljs"><span class="hljs-string">'import &lt;package&gt;'</span></code> does not automatically provide access to the package's modules unless they are explicitly imported in the <code class="python hljs"><span class="hljs-string">'&lt;package&gt;/__init__.py'</span></code> script.</strong></li>
 <li><strong>Directory of the file that is passed to python command serves as a root of local imports.</strong></li>
@@ -1085,7 +1085,7 @@
 
 
 <div><h3 id="sequence">Sequence</h3><ul>
-<li><strong>Only required methods are getitem() and len(). Getitem() should return the item at the passed index or raise IndexError (this excludes dictionaries because they accept keys).</strong></li>
+<li><strong>Only required methods are getitem() and len(). Getitem() should return the 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 that has getitem() defined.</strong></li>
 <li><strong>Reversed() automatically works on any object that has getitem() and len() 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>

From 87dbc203f39248d9e7a7561dfb7c5c79215bda87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 30 Jul 2025 16:40:21 +0200
Subject: [PATCH 176/186] Class, Duck types, Paths, CSV, Deque

---
 README.md           | 20 ++++++++++----------
 index.html          | 24 ++++++++++++------------
 pdf/remove_links.py |  3 +--
 3 files changed, 23 insertions(+), 24 deletions(-)

diff --git a/README.md b/README.md
index c3a79f6ab..79c8ead0e 100644
--- a/README.md
+++ b/README.md
@@ -971,7 +971,7 @@ class MyClass:
 >>> obj.a, str(obj), repr(obj)
 (1, '1', 'MyClass(1)')
 ```
-* **Methods whose names start and end with two underscores are called special methods. They are executed when object is passed to a built-in function or used as an operand, for example, `'print(a)'` calls `'a.__str__()'` and `'a + b'` calls `'a.__add__(b)'`.**
+* **Methods whose names start and end with two underscores are called special methods. They are executed when object is passed to a built-in function or used as an operand,<br>for example, `'print(a)'` calls `'a.__str__()'` and `'a + b'` calls `'a.__add__(b)'`.**
 * **Methods decorated with `'@staticmethod'` receive neither 'self' nor 'cls' argument.**
 * **Return value of str() special method should be readable and of repr() unambiguous. If only repr() is defined, it will also be used for str().**
 
@@ -1042,7 +1042,7 @@ class <class_name>:
 ```
 * **Objects can be made [sortable](#sortable) with `'order=True'` and immutable with `'frozen=True'`.**
 * **For object to be [hashable](#hashable), all attributes must be hashable and 'frozen' must be True.**
-* **Function field() is needed because `'<attr_name>: list = []'` would make a list that is shared among all instances. Its 'default_factory' argument can be any [callable](#callable).**
+* **Function field() is needed because `'<attr_name>: list = []'` would make a list that is shared among all instances. Its 'default_factory' argument accepts any callable object.**
 * **For attributes of arbitrary type use `'typing.Any'`.**
 
 ```python
@@ -1094,7 +1094,7 @@ Duck Types
 
 ### Comparable
 * **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`. That means all user-defined objects compare not equal by default (because id() returns object's memory address that is guaranteed to be unique).**
-* **Only the left side object has eq() method called, unless it returns NotImplemented, in which case the right object is consulted. False is returned if both return NotImplemented.**
+* **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.**
 * **Ne() automatically works on any object that has eq() defined.**
 
 ```python
@@ -1172,7 +1172,7 @@ class Counter:
 ```
 
 #### Python has many different iterator objects:
-* **Sequence iterators returned by the [iter()](#iterator) function, such as list\_iterator and set\_iterator.**
+* **Sequence iterators returned by the [iter()](#iterator) function, such as list\_iterator, etc.**
 * **Objects returned by the [itertools](#itertools) module, such as count, repeat and cycle.**
 * **Generators returned by the [generator functions](#generator) and [generator expressions](#comprehensions).**
 * **File objects returned by the [open()](#open) function, etc.**
@@ -1407,7 +1407,7 @@ except (<exception>, [...]) as <name>: ...
 ```
 * **Also catches subclasses, e.g. `'IndexError'` is caught by `'except LookupError:'`.**
 * **Use `'traceback.print_exc()'` to print the full error message to standard error stream.**
-* **Use `'print(<name>)'` to print just the cause of the exception (i.e. its arguments).**
+* **Use `'print(<name>)'` to print just the cause of the exception (that is, its arguments).**
 * **Use `'logging.exception(<str>)'` to log the passed message, followed by the full error message of the caught exception. For details about setting up the logger see [Logging](#logging).**
 * **Use `'sys.exc_info()'` to get exception type, object, and traceback of caught exception.**
 
@@ -1549,7 +1549,7 @@ args  = p.parse_args()                                            # Exits on par
 
 * **Use `'help=<str>'` to set argument description that will be displayed in help message.**
 * **Use `'default=<obj>'` to override None as option's or optional argument's default value.**
-* **Use `'type=FileType(<mode>)'` for files. Accepts 'encoding', but 'newline' is None.**
+* **Use `'type=FileType(<mode>)'` for files. It accepts 'encoding', but 'newline' is None.**
 
 
 Open
@@ -1657,7 +1657,7 @@ from pathlib import Path
 
 ```python
 <iter> = os.scandir(path='.')       # Returns DirEntry objects located at the path.
-<str>  = <DirEntry>.path            # Returns object's path (relative by default).
+<str>  = <DirEntry>.path            # Is absolute if 'path' argument was absolute.
 <str>  = <DirEntry>.name            # Returns path's final component as a string.
 <file> = open(<DirEntry>)           # Opens the file and returns its file object.
 ```
@@ -1836,7 +1836,7 @@ import csv
 * **`'lineterminator'` - How writer terminates rows. Reader looks for '\n', '\r' and '\r\n'.**
 * **`'quotechar'` - Character for quoting fields containing delimiters, quotechars, '\n' or '\r'.**
 * **`'escapechar'` - Character for escaping quotechars (not needed if doublequote is True).**
-* **`'doublequote'` - Whether quotechars inside fields are (or get) doubled or escaped.**
+* **`'doublequote'` - Whether quotechars inside fields are/get doubled instead of escaped.**
 * **`'quoting'` - 0: As necessary, 1: All, 2: All but numbers which are read as floats, 3: None.**
 * **`'skipinitialspace'` - Is space character at the start of the field stripped by the reader.**
 
@@ -2028,7 +2028,7 @@ b'\x00\x01\x00\x02\x00\x00\x00\x03'
 
 Array
 -----
-**List that can only hold numbers of a predefined 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 with byteswap() method.**
+**List that can only hold numbers of a predefined 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 with byteswap() method.**
 
 ```python
 from array import array
@@ -2084,7 +2084,7 @@ from collections import deque
 ```python
 <deque> = deque(<collection>)                  # Use `maxlen=<int>` to set size limit.
 <deque>.appendleft(<el>)                       # Opposite element is dropped if full.
-<deque>.extendleft(<collection>)               # Appends elements in reversed order.
+<deque>.extendleft(<collection>)               # Prepends reversed coll. to the deque.
 <deque>.rotate(n=1)                            # Last element becomes the first one.
 <el> = <deque>.popleft()                       # Raises IndexError if deque is empty.
 ```
diff --git a/index.html b/index.html
index 6a9521e7c..fbb3516c5 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>July 29, 2025</aside>
+    <aside>July 30, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -827,7 +827,7 @@
 (<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. 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>Methods whose names start and end with two underscores are called special methods. They are executed when object is passed to a built-in function or used as an operand,<br>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>Methods decorated with <code class="python hljs"><span class="hljs-string">'@staticmethod'</span></code> receive neither 'self' nor 'cls' argument.</strong></li>
 <li><strong>Return value of str() special method should be readable and of repr() unambiguous. If only repr() is defined, it will also be used for str().</strong></li>
 </ul>
@@ -891,7 +891,7 @@
 <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 'frozen' must be True.</strong></li>
-<li><strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">'&lt;attr_name&gt;: list = []'</span></code> would make a list that is shared among all instances. Its 'default_factory' argument can be any <a href="#callable">callable</a>.</strong></li>
+<li><strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">'&lt;attr_name&gt;: list = []'</span></code> would make a list that is shared among all instances. Its 'default_factory' argument accepts any callable object.</strong></li>
 <li><strong>For attributes of arbitrary type use <code class="python hljs"><span class="hljs-string">'typing.Any'</span></code>.</strong></li>
 </ul>
 <pre><code class="python language-python hljs">P = make_dataclass(<span class="hljs-string">'P'</span>, [<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>])
@@ -927,7 +927,7 @@
 
 <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 has those methods defined 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. False is returned if both return NotImplemented.</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>Ne() 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>
@@ -1002,7 +1002,7 @@
 (<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 and set_iterator.</strong></li>
+<li><strong>Sequence iterators returned by the <a href="#iterator">iter()</a> function, such as list_iterator, etc.</strong></li>
 <li><strong>Objects returned by the <a href="#itertools">itertools</a> module, such as count, repeat and cycle.</strong></li>
 <li><strong>Generators returned by the <a href="#generator">generator functions</a> and <a href="#comprehensions">generator expressions</a>.</strong></li>
 <li><strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong></li>
@@ -1212,7 +1212,7 @@
 <ul>
 <li><strong>Also catches subclasses, e.g. <code class="python hljs"><span class="hljs-string">'IndexError'</span></code> is caught by <code class="python hljs"><span class="hljs-string">'except LookupError:'</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(&lt;name&gt;)'</span></code> to print just the cause of the exception (i.e. its arguments).</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'print(&lt;name&gt;)'</span></code> to print just the cause of the exception (that is, its arguments).</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'logging.exception(&lt;str&gt;)'</span></code> to log the passed message, followed by the full error message of the caught exception. For details about setting up the logger see <a href="#logging">Logging</a>.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'sys.exc_info()'</span></code> to get exception type, object, and traceback of caught exception.</strong></li>
 </ul>
@@ -1327,7 +1327,7 @@
 <ul>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'help=&lt;str&gt;'</span></code> to set argument description that will be displayed in help message.</strong></li>
 <li><strong>Use <code class="python hljs"><span class="hljs-string">'default=&lt;obj&gt;'</span></code> to override None as option's or optional argument's default value.</strong></li>
-<li><strong>Use <code class="python hljs"><span class="hljs-string">'type=FileType(&lt;mode&gt;)'</span></code> for files. Accepts 'encoding', but 'newline' is None.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'type=FileType(&lt;mode&gt;)'</span></code> for files. It accepts 'encoding', but 'newline' is None.</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">&lt;file&gt; = open(&lt;path&gt;, mode=<span class="hljs-string">'r'</span>, encoding=<span class="hljs-keyword">None</span>, newline=<span class="hljs-keyword">None</span>)
 </code></pre></div>
@@ -1408,7 +1408,7 @@
 &lt;num&gt;  = &lt;stat&gt;.st_mtime/st_size/…  <span class="hljs-comment"># Returns modification time, size in bytes, etc.</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">&lt;iter&gt; = os.scandir(path=<span class="hljs-string">'.'</span>)       <span class="hljs-comment"># Returns DirEntry objects located at the path.</span>
-&lt;str&gt;  = &lt;DirEntry&gt;.path            <span class="hljs-comment"># Returns object's path (relative by default).</span>
+&lt;str&gt;  = &lt;DirEntry&gt;.path            <span class="hljs-comment"># Is absolute if 'path' argument was absolute.</span>
 &lt;str&gt;  = &lt;DirEntry&gt;.name            <span class="hljs-comment"># Returns path's final component as a string.</span>
 &lt;file&gt; = open(&lt;DirEntry&gt;)           <span class="hljs-comment"># Opens the file and returns its file object.</span>
 </code></pre></div>
@@ -1539,7 +1539,7 @@
 <li><strong><code class="python hljs"><span class="hljs-string">'lineterminator'</span></code> - 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 (not needed if doublequote is True).</strong></li>
-<li><strong><code class="python hljs"><span class="hljs-string">'doublequote'</span></code> - Whether quotechars inside fields are (or get) doubled or escaped.</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">┏━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┓
@@ -1692,7 +1692,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<div><h2 id="array"><a href="#array" name="array">#</a>Array</h2><p><strong>List that can only hold numbers of a predefined 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 with 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
+<div><h2 id="array"><a href="#array" name="array">#</a>Array</h2><p><strong>List that can only hold numbers of a predefined 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 with 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>
 
 
@@ -1727,7 +1727,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 <pre><code class="python language-python hljs">&lt;deque&gt; = deque(&lt;collection&gt;)                  <span class="hljs-comment"># Use `maxlen=&lt;int&gt;` to set size limit.</span>
 &lt;deque&gt;.appendleft(&lt;el&gt;)                       <span class="hljs-comment"># Opposite element is dropped if full.</span>
-&lt;deque&gt;.extendleft(&lt;collection&gt;)               <span class="hljs-comment"># Appends elements in reversed order.</span>
+&lt;deque&gt;.extendleft(&lt;collection&gt;)               <span class="hljs-comment"># Prepends reversed coll. to the deque.</span>
 &lt;deque&gt;.rotate(n=<span class="hljs-number">1</span>)                            <span class="hljs-comment"># Last element becomes the first one.</span>
 &lt;el&gt; = &lt;deque&gt;.popleft()                       <span class="hljs-comment"># Raises IndexError if deque is empty.</span>
 </code></pre>
@@ -2934,7 +2934,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>July 29, 2025</aside>
+    <aside>July 30, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index b372a0711..d3455eede 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -15,8 +15,7 @@
     '<strong>Hints are used by type checkers like <a href="https://pypi.org/project/mypy/">mypy</a>, data validation libraries such as <a href="https://pypi.org/project/pydantic/">Pydantic</a> and lately also by <a href="https://pypi.org/project/Cython/">Cython</a> compiler. However, they are not enforced by CPython interpreter.</strong>': '<strong>Hints are used by type checkers like mypy, data validation libraries such as Pydantic and lately also by Cython compiler. However, they are not enforced by CPython interpreter.</strong>',
     '<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>': '<strong>Objects can be made sortable 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>',
     '<strong>For object to be <a href="#hashable">hashable</a>, all attributes must be hashable and \'frozen\' must be True.</strong>': '<strong>For object to be hashable, all attributes must be hashable and \'frozen\' must be True.</strong>',
-    '<strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">\'&lt;attr_name&gt;: list = []\'</span></code> would make a list that is shared among all instances. Its \'default_factory\' argument can be any <a href="#callable">callable</a>.</strong>': '<strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">\'&lt;attr_name&gt;: list = []\'</span></code> would make a list that is shared among all instances. Its \'default_factory\' argument can be any callable (p. 17).</strong>',
-    '<strong>Sequence iterators returned by the <a href="#iterator">iter()</a> function, such as list_iterator and set_iterator.</strong>': '<strong>Sequence iterators returned by the iter() function, such as list_iterator and set_iterator.</strong>',
+    '<strong>Sequence iterators returned by the <a href="#iterator">iter()</a> function, such as list_iterator, etc.</strong>': '<strong>Sequence iterators returned by the iter() function, such as list_iterator and set_iterator.</strong>',
     '<strong>Objects returned by the <a href="#itertools">itertools</a> module, such as count, repeat and cycle.</strong>': '<strong>Objects returned by the itertools module, such as count, repeat and cycle (p. 3).</strong>',
     '<strong>Generators returned by the <a href="#generator">generator functions</a> and <a href="#comprehensions">generator expressions</a>.</strong>': '<strong>Generators returned by the generator functions (p. 4) and generator expressions (p. 11).</strong>',
     '<strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong>': '<strong>File objects returned by the open() function (p. 22), etc.</strong>',

From fb82911313dd297d70d2482805c59e7e3b099ab9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 30 Jul 2025 17:36:47 +0200
Subject: [PATCH 177/186] Regex, Class, Coroutines

---
 README.md           | 8 ++++----
 index.html          | 8 ++++----
 parse.js            | 2 +-
 pdf/remove_links.py | 1 +
 4 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/README.md b/README.md
index 79c8ead0e..4d774ecea 100644
--- a/README.md
+++ b/README.md
@@ -370,7 +370,7 @@ import re
 
 * **Raw string literals do not interpret escape sequences, thus enabling us to use regex-specific escape sequences that cause SyntaxWarning in normal string literals (since 3.12).**
 * **Argument 'new' of re.sub() can be a function that accepts Match object and returns a str.**
-* **Argument `'flags=re.IGNORECASE'` can be used with all listed regex functions.**
+* **Argument `'flags=re.IGNORECASE'` can be used with all functions that are listed above.**
 * **Argument `'flags=re.MULTILINE'` makes `'^'` and `'$'` match the start/end of each line.**
 * **Argument `'flags=re.DOTALL'` makes `'.'` also accept the `'\n'` (besides all other chars).**
 * **`'re.compile(<regex>)'` returns a Pattern object with methods sub(), findall(), etc.**
@@ -971,7 +971,7 @@ class MyClass:
 >>> obj.a, str(obj), repr(obj)
 (1, '1', 'MyClass(1)')
 ```
-* **Methods whose names start and end with two underscores are called special methods. They are executed when object is passed to a built-in function or used as an operand,<br>for example, `'print(a)'` calls `'a.__str__()'` and `'a + b'` calls `'a.__add__(b)'`.**
+* **Methods whose names start and end with two underscores are called special methods. They are executed when object is passed to a built-in function or used as an operand, for&nbsp;example, `'print(a)'` calls `'a.__str__()'` and `'a + b'` calls `'a.__add__(b)'`.**
 * **Methods decorated with `'@staticmethod'` receive neither 'self' nor 'cls' argument.**
 * **Return value of str() special method should be readable and of repr() unambiguous. If only repr() is defined, it will also be used for str().**
 
@@ -1042,7 +1042,7 @@ class <class_name>:
 ```
 * **Objects can be made [sortable](#sortable) with `'order=True'` and immutable with `'frozen=True'`.**
 * **For object to be [hashable](#hashable), all attributes must be hashable and 'frozen' must be True.**
-* **Function field() is needed because `'<attr_name>: list = []'` would make a list that is shared among all instances. Its 'default_factory' argument accepts any callable object.**
+* **Function field() is needed because `'<attr_name>: list = []'` would make a list that is shared among all instances. Its 'default_factory' argument accepts any [callable](#callable) object.**
 * **For attributes of arbitrary type use `'typing.Any'`.**
 
 ```python
@@ -2336,7 +2336,7 @@ D = enum.Enum('D', 'n e s w')              # Direction (north, east, etc.).
 W, H = 15, 7                               # Width and height constants.
 
 def main(screen):
-    curses.curs_set(0)                     # Makes cursor invisible.
+    curses.curs_set(0)                     # Makes the cursor invisible.
     screen.nodelay(True)                   # Makes getch() non-blocking.
     asyncio.run(main_coroutine(screen))    # Starts running asyncio code.
 
diff --git a/index.html b/index.html
index fbb3516c5..b1270ecab 100644
--- a/index.html
+++ b/index.html
@@ -351,7 +351,7 @@
 <ul>
 <li><strong>Raw string literals do not interpret escape sequences, thus enabling us to use regex-specific escape sequences that cause SyntaxWarning in normal string literals (since 3.12).</strong></li>
 <li><strong>Argument 'new' of re.sub() can be a function that accepts Match object and returns a str.</strong></li>
-<li><strong>Argument <code class="python hljs"><span class="hljs-string">'flags=re.IGNORECASE'</span></code> can be used with all listed regex functions.</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(&lt;regex&gt;)'</span></code> returns a Pattern object with methods sub(), findall(), etc.</strong></li>
@@ -827,7 +827,7 @@
 (<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. They are executed when object is passed to a built-in function or used as an operand,<br>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>Methods whose names start and end with two underscores are called special methods. They are executed when object is passed to a built-in function or used as an operand, for&nbsp;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>Methods decorated with <code class="python hljs"><span class="hljs-string">'@staticmethod'</span></code> receive neither 'self' nor 'cls' argument.</strong></li>
 <li><strong>Return value of str() special method should be readable and of repr() unambiguous. If only repr() is defined, it will also be used for str().</strong></li>
 </ul>
@@ -891,7 +891,7 @@
 <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 'frozen' must be True.</strong></li>
-<li><strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">'&lt;attr_name&gt;: list = []'</span></code> would make a list that is shared among all instances. Its 'default_factory' argument accepts any callable object.</strong></li>
+<li><strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">'&lt;attr_name&gt;: 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 of arbitrary type use <code class="python hljs"><span class="hljs-string">'typing.Any'</span></code>.</strong></li>
 </ul>
 <pre><code class="python language-python hljs">P = make_dataclass(<span class="hljs-string">'P'</span>, [<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>])
@@ -1924,7 +1924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 W, H = <span class="hljs-number">15</span>, <span class="hljs-number">7</span>                               <span class="hljs-comment"># Width and height constants.</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 cursor invisible.</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>
     asyncio.run(main_coroutine(screen))    <span class="hljs-comment"># Starts running asyncio code.</span>
 
diff --git a/parse.js b/parse.js
index 668b799e9..7a7d19c92 100755
--- a/parse.js
+++ b/parse.js
@@ -125,7 +125,7 @@ const COROUTINES =
   'W, H = <span class="hljs-number">15</span>, <span class="hljs-number">7</span>                               <span class="hljs-comment"># Width and height constants.</span>\n' +
   '\n' +
   '<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">(screen)</span>:</span>\n' +
-  '    curses.curs_set(<span class="hljs-number">0</span>)                     <span class="hljs-comment"># Makes cursor invisible.</span>\n' +
+  '    curses.curs_set(<span class="hljs-number">0</span>)                     <span class="hljs-comment"># Makes the cursor invisible.</span>\n' +
   '    screen.nodelay(<span class="hljs-keyword">True</span>)                   <span class="hljs-comment"># Makes getch() non-blocking.</span>\n' +
   '    asyncio.run(main_coroutine(screen))    <span class="hljs-comment"># Starts running asyncio code.</span>\n' +
   '\n' +
diff --git a/pdf/remove_links.py b/pdf/remove_links.py
index d3455eede..5b8941bc6 100755
--- a/pdf/remove_links.py
+++ b/pdf/remove_links.py
@@ -15,6 +15,7 @@
     '<strong>Hints are used by type checkers like <a href="https://pypi.org/project/mypy/">mypy</a>, data validation libraries such as <a href="https://pypi.org/project/pydantic/">Pydantic</a> and lately also by <a href="https://pypi.org/project/Cython/">Cython</a> compiler. However, they are not enforced by CPython interpreter.</strong>': '<strong>Hints are used by type checkers like mypy, data validation libraries such as Pydantic and lately also by Cython compiler. However, they are not enforced by CPython interpreter.</strong>',
     '<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>': '<strong>Objects can be made sortable 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>',
     '<strong>For object to be <a href="#hashable">hashable</a>, all attributes must be hashable and \'frozen\' must be True.</strong>': '<strong>For object to be hashable, all attributes must be hashable and \'frozen\' must be True.</strong>',
+    '<strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">\'&lt;attr_name&gt;: 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>': '<strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">\'&lt;attr_name&gt;: list = []\'</span></code> would make a list that is shared among all instances. Its \'default_factory\' argument accepts any callable object.</strong>',
     '<strong>Sequence iterators returned by the <a href="#iterator">iter()</a> function, such as list_iterator, etc.</strong>': '<strong>Sequence iterators returned by the iter() function, such as list_iterator and set_iterator.</strong>',
     '<strong>Objects returned by the <a href="#itertools">itertools</a> module, such as count, repeat and cycle.</strong>': '<strong>Objects returned by the itertools module, such as count, repeat and cycle (p. 3).</strong>',
     '<strong>Generators returned by the <a href="#generator">generator functions</a> and <a href="#comprehensions">generator expressions</a>.</strong>': '<strong>Generators returned by the generator functions (p. 4) and generator expressions (p. 11).</strong>',

From 39ca9bc81f96a26b58d0225cc16517dd40d7f4da Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Wed, 30 Jul 2025 20:20:28 +0200
Subject: [PATCH 178/186] Match statement, Threading

---
 README.md  | 10 +++++-----
 index.html | 10 +++++-----
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/README.md b/README.md
index 4d774ecea..afb2e1524 100644
--- a/README.md
+++ b/README.md
@@ -1247,7 +1247,7 @@ True
 
 ### Collection
 * **Only required methods are iter() and len(). Len() should return the number of items.**
-* **This cheatsheet actually means `'<iterable>'` when it uses `'<collection>'`.**
+* **This cheatsheet actually means `'<iterable>'` when it uses the `'<collection>'`.**
 * **I chose not to use the name 'iterable' because it sounds scarier and more vague than 'collection'. The main drawback of this decision is that the reader could think a certain function doesn't accept iterators when it does, since iterators are the only built-in objects that are iterable but are not collections.**
 ```python
 class MyCollection:
@@ -2141,11 +2141,11 @@ match <object/expression>:
 <mapping_patt>  = {<value_pattern>: <patt>, ...}   # Matches a dict that has matching items.
 <class_pattern> = <type>(<attr_name>=<patt>, ...)  # Matches an object if attributes match.
 ```
-* **Sequence pattern can also be written as a tuple, i.e. `'(<pattern_1>, [...])'`.**
+* **Sequence pattern can also be written as a tuple, either with or without the brackets.**
 * **Use `'*<name>'` and `'**<name>'` in sequence/mapping patterns to bind remaining items.**
 * **Sequence pattern must match all items of the collection, while mapping pattern does not.**
-* **Patterns can be surrounded with brackets to override precedence (`'|'` > `'as'` > `','`).**
-* **All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement.**
+* **Patterns can be surrounded with brackets to override their precedence: `'|'` > `'as'` > `','`. For example, `'[1, 2]'` gets caught by the `'case 1 | 0, 2 as x if x == 2'` clause.**
+* **All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement (only the function block delimits scope).**
 
 ### Example
 ```python
@@ -2300,7 +2300,7 @@ with <lock>:                                   # Enters the block by calling acq
 <iter> = as_completed(<coll_of_Futures>)       # `next(<iter>)` returns next completed Future.
 ```
 * **Map() and as\_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called/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 threads are done.**
-* **Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.**
+* **Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns an exception object or None.**
 * **ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be [pickable](#pickle), queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via `'if __name__ == "__main__": ...'`.**
 
 
diff --git a/index.html b/index.html
index b1270ecab..3728ebc5a 100644
--- a/index.html
+++ b/index.html
@@ -1070,7 +1070,7 @@
 </code></pre>
 <div><h3 id="collection">Collection</h3><ul>
 <li><strong>Only required methods are iter() and len(). Len() should return the number of items.</strong></li>
-<li><strong>This cheatsheet actually means <code class="python hljs"><span class="hljs-string">'&lt;iterable&gt;'</span></code> when it uses <code class="python hljs"><span class="hljs-string">'&lt;collection&gt;'</span></code>.</strong></li>
+<li><strong>This cheatsheet actually means <code class="python hljs"><span class="hljs-string">'&lt;iterable&gt;'</span></code> when it uses the <code class="python hljs"><span class="hljs-string">'&lt;collection&gt;'</span></code>.</strong></li>
 <li><strong>I chose not to use the name 'iterable' because it sounds scarier and more vague than 'collection'. The main drawback of this decision is that the reader could think a certain function doesn't accept iterators when it 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>
@@ -1772,11 +1772,11 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 <ul>
-<li><strong>Sequence pattern can also be written as a tuple, i.e. <code class="python hljs"><span class="hljs-string">'(&lt;pattern_1&gt;, [...])'</span></code>.</strong></li>
+<li><strong>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">'*&lt;name&gt;'</span></code> and <code class="python hljs"><span class="hljs-string">'**&lt;name&gt;'</span></code> in sequence/mapping patterns to bind remaining items.</strong></li>
 <li><strong>Sequence pattern must match all items of the collection, while mapping pattern does not.</strong></li>
-<li><strong>Patterns can be surrounded with brackets to override precedence (<code class="python hljs"><span class="hljs-string">'|'</span></code> &gt; <code class="python hljs"><span class="hljs-string">'as'</span></code> &gt; <code class="python hljs"><span class="hljs-string">','</span></code>).</strong></li>
-<li><strong>All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement.</strong></li>
+<li><strong>Patterns can be surrounded with brackets to override their precedence: <code class="python hljs"><span class="hljs-string">'|'</span></code> &gt; <code class="python hljs"><span class="hljs-string">'as'</span></code> &gt; <code class="python hljs"><span class="hljs-string">','</span></code>. For example, <code class="python hljs"><span class="hljs-string">'[1, 2]'</span></code> gets caught by the <code class="python hljs"><span class="hljs-string">'case 1 | 0, 2 as x if x == 2'</span></code> clause.</strong></li>
+<li><strong>All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement (only the function block delimits scope).</strong></li>
 </ul>
 <div><h3 id="example-2">Example</h3><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path
 <span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">match</span> Path(<span class="hljs-string">'/home/gto/python-cheatsheet/README.md'</span>):
@@ -1897,7 +1897,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre>
 <ul>
 <li><strong>Map() and as_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called/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 threads are done.</strong></li>
-<li><strong>Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.</strong></li>
+<li><strong>Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns an exception object or None.</strong></li>
 <li><strong>ProcessPoolExecutor provides true parallelism but: everything sent to/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="coroutines"><a href="#coroutines" name="coroutines">#</a>Coroutines</h2><ul>

From fc2c3f7b1f076b640b7200c44d1fbb7ce0b618c3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 31 Jul 2025 00:16:50 +0200
Subject: [PATCH 179/186] Match statement, Introspection

---
 README.md  |  6 +++---
 index.html | 10 +++++-----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index afb2e1524..33cf27c40 100644
--- a/README.md
+++ b/README.md
@@ -2144,7 +2144,7 @@ match <object/expression>:
 * **Sequence pattern can also be written as a tuple, either with or without the brackets.**
 * **Use `'*<name>'` and `'**<name>'` in sequence/mapping patterns to bind remaining items.**
 * **Sequence pattern must match all items of the collection, while mapping pattern does not.**
-* **Patterns can be surrounded with brackets to override their precedence: `'|'` > `'as'` > `','`. For example, `'[1, 2]'` gets caught by the `'case 1 | 0, 2 as x if x == 2'` clause.**
+* **Patterns can be surrounded with brackets to override their precedence: `'|'` > `'as'` > `','`. For example, `'[1, 2]'` gets caught by the `'case 1|2, 2|3 as x if x == 2:'` clause.**
 * **All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement (only the function block delimits scope).**
 
 ### Example
@@ -2226,13 +2226,13 @@ Introspection
 <list> = dir(<obj>)                 # Returns names of object's attributes (including methods).
 <dict> = vars(<obj>)                # Returns dict of writable attributes. Also <obj>.__dict__.
 <bool> = hasattr(<obj>, '<name>')   # Checks if object possesses attribute with passed name.
-value  = getattr(<obj>, '<name>')   # Returns object's attribute or raises AttributeError.
+value  = getattr(<obj>, '<name>')   # Returns the object's attribute or raises AttributeError.
 setattr(<obj>, '<name>', value)     # Sets attribute. Only works on objects with __dict__ attr.
 delattr(<obj>, '<name>')            # Deletes attribute from __dict__. Also `del <obj>.<name>`.
 ```
 
 ```python
-<Sig>  = inspect.signature(<func>)  # Returns a Signature object of the passed function.
+<Sig>  = inspect.signature(<func>)  # Returns Signature object of the passed function or class.
 <dict> = <Sig>.parameters           # Returns dict of Parameters. Also <Sig>.return_annotation.
 <memb> = <Param>.kind               # Returns ParameterKind member (Parameter.KEYWORD_ONLY, …).
 <type> = <Param>.annotation         # Returns Parameter.empty if missing. Also <Param>.default.
diff --git a/index.html b/index.html
index 3728ebc5a..7ffe92e91 100644
--- a/index.html
+++ b/index.html
@@ -56,7 +56,7 @@
 
 <body>
   <header>
-    <aside>July 30, 2025</aside>
+    <aside>July 31, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
@@ -1775,7 +1775,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>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">'*&lt;name&gt;'</span></code> and <code class="python hljs"><span class="hljs-string">'**&lt;name&gt;'</span></code> in sequence/mapping patterns to bind remaining items.</strong></li>
 <li><strong>Sequence pattern must match all items of the collection, while mapping pattern does not.</strong></li>
-<li><strong>Patterns can be surrounded with brackets to override their precedence: <code class="python hljs"><span class="hljs-string">'|'</span></code> &gt; <code class="python hljs"><span class="hljs-string">'as'</span></code> &gt; <code class="python hljs"><span class="hljs-string">','</span></code>. For example, <code class="python hljs"><span class="hljs-string">'[1, 2]'</span></code> gets caught by the <code class="python hljs"><span class="hljs-string">'case 1 | 0, 2 as x if x == 2'</span></code> clause.</strong></li>
+<li><strong>Patterns can be surrounded with brackets to override their precedence: <code class="python hljs"><span class="hljs-string">'|'</span></code> &gt; <code class="python hljs"><span class="hljs-string">'as'</span></code> &gt; <code class="python hljs"><span class="hljs-string">','</span></code>. For example, <code class="python hljs"><span class="hljs-string">'[1, 2]'</span></code> gets caught by the <code class="python hljs"><span class="hljs-string">'case 1|2, 2|3 as x if x == 2:'</span></code> clause.</strong></li>
 <li><strong>All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement (only the function block delimits scope).</strong></li>
 </ul>
 <div><h3 id="example-2">Example</h3><pre><code class="python language-python hljs"><span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path
@@ -1840,11 +1840,11 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <pre><code class="python language-python hljs">&lt;list&gt; = dir(&lt;obj&gt;)                 <span class="hljs-comment"># Returns names of object's attributes (including methods).</span>
 &lt;dict&gt; = vars(&lt;obj&gt;)                <span class="hljs-comment"># Returns dict of writable attributes. Also &lt;obj&gt;.__dict__.</span>
 &lt;bool&gt; = hasattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>)   <span class="hljs-comment"># Checks if object possesses attribute with passed name.</span>
-value  = getattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>)   <span class="hljs-comment"># Returns object's attribute or raises AttributeError.</span>
+value  = getattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>)   <span class="hljs-comment"># Returns the object's attribute or raises AttributeError.</span>
 setattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>, value)     <span class="hljs-comment"># Sets attribute. Only works on objects with __dict__ attr.</span>
 delattr(&lt;obj&gt;, <span class="hljs-string">'&lt;name&gt;'</span>)            <span class="hljs-comment"># Deletes attribute from __dict__. Also `del &lt;obj&gt;.&lt;name&gt;`.</span>
 </code></pre>
-<pre><code class="python language-python hljs">&lt;Sig&gt;  = inspect.signature(&lt;func&gt;)  <span class="hljs-comment"># Returns a Signature object of the passed function.</span>
+<pre><code class="python language-python hljs">&lt;Sig&gt;  = inspect.signature(&lt;func&gt;)  <span class="hljs-comment"># Returns Signature object of the passed function or class.</span>
 &lt;dict&gt; = &lt;Sig&gt;.parameters           <span class="hljs-comment"># Returns dict of Parameters. Also &lt;Sig&gt;.return_annotation.</span>
 &lt;memb&gt; = &lt;Param&gt;.kind               <span class="hljs-comment"># Returns ParameterKind member (Parameter.KEYWORD_ONLY, …).</span>
 &lt;type&gt; = &lt;Param&gt;.annotation         <span class="hljs-comment"># Returns Parameter.empty if missing. Also &lt;Param&gt;.default.</span>
@@ -2934,7 +2934,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
  
 
   <footer>
-    <aside>July 30, 2025</aside>
+    <aside>July 31, 2025</aside>
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </footer>
 

From df39e345a0ec08a080ca6b42d399be80664bc7d3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 31 Jul 2025 06:02:45 +0200
Subject: [PATCH 180/186] Match, Logging

---
 README.md  | 12 ++++++------
 index.html | 12 ++++++------
 2 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/README.md b/README.md
index 33cf27c40..7a75c8ada 100644
--- a/README.md
+++ b/README.md
@@ -2144,8 +2144,8 @@ match <object/expression>:
 * **Sequence pattern can also be written as a tuple, either with or without the brackets.**
 * **Use `'*<name>'` and `'**<name>'` in sequence/mapping patterns to bind remaining items.**
 * **Sequence pattern must match all items of the collection, while mapping pattern does not.**
-* **Patterns can be surrounded with brackets to override their precedence: `'|'` > `'as'` > `','`. For example, `'[1, 2]'` gets caught by the `'case 1|2, 2|3 as x if x == 2:'` clause.**
-* **All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement (only the function block delimits scope).**
+* **Patterns can be surrounded with brackets to override their precedence: `'|'` > `'as'` > `','`. For example, `'[1, 2]'` is matched by the `'case 1|2, 2|3 as x if x == 2:'` block.**
+* **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).**
 
 ### Example
 ```python
@@ -2185,10 +2185,10 @@ log.basicConfig(
 
 ```python
 <Formatter> = log.Formatter('<format>')           # Formats messages according to format str.
-<Handler> = log.FileHandler(<path>, mode='a')     # Creates a handler. Also `encoding=None`.
-<Handler>.setFormatter(<Formatter>)               # Assigns the formatter to the handler.
-<Handler>.setLevel(<int/str>)                     # It will process all messages by default.
-<Logger>.addHandler(<Handler>)                    # Appends handler to logger's 'handlers'.
+<Handler> = log.FileHandler(<path>, mode='a')     # Appends to file. Also `encoding=None`.
+<Handler>.setFormatter(<Formatter>)               # Only outputs bare messages by default.
+<Handler>.setLevel(<int/str>)                     # Prints or saves every message by default.
+<Logger>.addHandler(<Handler>)                    # Logger can have more than one handler.
 <Logger>.setLevel(<int/str>)                      # What is sent to its/ancestors' handlers.
 <Logger>.propagate = <bool>                       # Cuts off ancestors' handlers if False.
 ```
diff --git a/index.html b/index.html
index 7ffe92e91..2a501cb02 100644
--- a/index.html
+++ b/index.html
@@ -1775,8 +1775,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 <li><strong>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">'*&lt;name&gt;'</span></code> and <code class="python hljs"><span class="hljs-string">'**&lt;name&gt;'</span></code> in sequence/mapping patterns to bind remaining items.</strong></li>
 <li><strong>Sequence pattern must match all items of the collection, while mapping pattern does not.</strong></li>
-<li><strong>Patterns can be surrounded with brackets to override their precedence: <code class="python hljs"><span class="hljs-string">'|'</span></code> &gt; <code class="python hljs"><span class="hljs-string">'as'</span></code> &gt; <code class="python hljs"><span class="hljs-string">','</span></code>. For example, <code class="python hljs"><span class="hljs-string">'[1, 2]'</span></code> gets caught by the <code class="python hljs"><span class="hljs-string">'case 1|2, 2|3 as x if x == 2:'</span></code> clause.</strong></li>
-<li><strong>All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement (only the function block delimits scope).</strong></li>
+<li><strong>Patterns can be surrounded with brackets to override their precedence: <code class="python hljs"><span class="hljs-string">'|'</span></code> &gt; <code class="python hljs"><span class="hljs-string">'as'</span></code> &gt; <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 the <code class="python hljs"><span class="hljs-string">'case 1|2, 2|3 as x if x == 2:'</span></code> block.</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"><span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path
 <span class="hljs-meta">&gt;&gt;&gt; </span><span class="hljs-keyword">match</span> Path(<span class="hljs-string">'/home/gto/python-cheatsheet/README.md'</span>):
@@ -1805,10 +1805,10 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 </code></pre></div>
 
 <pre><code class="python language-python hljs">&lt;Formatter&gt; = log.Formatter(<span class="hljs-string">'&lt;format&gt;'</span>)           <span class="hljs-comment"># Formats messages according to format str.</span>
-&lt;Handler&gt; = log.FileHandler(&lt;path&gt;, mode=<span class="hljs-string">'a'</span>)     <span class="hljs-comment"># Creates a handler. Also `encoding=None`.</span>
-&lt;Handler&gt;.setFormatter(&lt;Formatter&gt;)               <span class="hljs-comment"># Assigns the formatter to the handler.</span>
-&lt;Handler&gt;.setLevel(&lt;int/str&gt;)                     <span class="hljs-comment"># It will process all messages by default.</span>
-&lt;Logger&gt;.addHandler(&lt;Handler&gt;)                    <span class="hljs-comment"># Appends handler to logger's 'handlers'.</span>
+&lt;Handler&gt; = log.FileHandler(&lt;path&gt;, mode=<span class="hljs-string">'a'</span>)     <span class="hljs-comment"># Appends to file. Also `encoding=None`.</span>
+&lt;Handler&gt;.setFormatter(&lt;Formatter&gt;)               <span class="hljs-comment"># Only outputs bare messages by default.</span>
+&lt;Handler&gt;.setLevel(&lt;int/str&gt;)                     <span class="hljs-comment"># Prints or saves every message by default.</span>
+&lt;Logger&gt;.addHandler(&lt;Handler&gt;)                    <span class="hljs-comment"># Logger can have more than one handler.</span>
 &lt;Logger&gt;.setLevel(&lt;int/str&gt;)                      <span class="hljs-comment"># What is sent to its/ancestors' handlers.</span>
 &lt;Logger&gt;.propagate = &lt;bool&gt;                       <span class="hljs-comment"># Cuts off ancestors' handlers if False.</span>
 </code></pre>

From db4d8b804837eabfdb0089472edfa811377965c5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 31 Jul 2025 07:02:13 +0200
Subject: [PATCH 181/186] Array

---
 README.md  | 2 +-
 index.html | 7 +++----
 2 files changed, 4 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index 7a75c8ada..8fc0f4c71 100644
--- a/README.md
+++ b/README.md
@@ -2028,7 +2028,7 @@ b'\x00\x01\x00\x02\x00\x00\x00\x03'
 
 Array
 -----
-**List that can only hold numbers of a predefined 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 with byteswap() method.**
+**List that can only hold numbers of a predefined 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/every element can be reversed (by calling the byteswap() method).**
 
 ```python
 from array import array
diff --git a/index.html b/index.html
index 2a501cb02..cc83fd59b 100644
--- a/index.html
+++ b/index.html
@@ -60,7 +60,8 @@
     <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>.
+   <div class="pagebreak"></div>
+<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"></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.
@@ -593,7 +594,6 @@
 &lt;TD&gt;     = &lt;DTa&gt;     - &lt;DTa&gt;                <span class="hljs-comment"># Ignores jumps if they share the tzinfo object.</span>
 &lt;D/DT&gt;   = &lt;D/DT&gt;    ± &lt;TD&gt;                 <span class="hljs-comment"># Returned datetime can fall into missing hour.</span>
 &lt;TD&gt;     = &lt;TD&gt;      * &lt;float&gt;              <span class="hljs-comment"># Also `&lt;TD&gt; = abs(&lt;TD&gt;)`, `&lt;TD&gt; = &lt;TD&gt; ± &lt;TD&gt;`.</span>
-&lt;float&gt;  = &lt;TD&gt;      / &lt;TD&gt;                 <span class="hljs-comment"># Also `(&lt;int&gt;, &lt;TD&gt;) = divmod(&lt;TD&gt;, &lt;TD&gt;)`.</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> &lt;<span class="hljs-title">func_name</span>&gt;<span class="hljs-params">(&lt;nondefault_args&gt;)</span>:</span> ...                  <span class="hljs-comment"># E.g. `def func(x, y): ...`.</span>
@@ -1692,7 +1692,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<div><h2 id="array"><a href="#array" name="array">#</a>Array</h2><p><strong>List that can only hold numbers of a predefined 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 with 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
+<div><h2 id="array"><a href="#array" name="array">#</a>Array</h2><p><strong>List that can only hold numbers of a predefined 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/every 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>
 
 
@@ -1970,7 +1970,6 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     curses.wrapper(main)
 </code></pre></div>
 
-<p><br></p>
 <div><h1 id="libraries">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">&gt;&gt;&gt; </span><span class="hljs-keyword">import</span> tqdm, time
 <span class="hljs-meta">&gt;&gt;&gt; </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>):

From e70aa5ce3bafbc453982f5ec5605ba116cc240a0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 31 Jul 2025 07:05:23 +0200
Subject: [PATCH 182/186] Array

---
 index.html | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/index.html b/index.html
index cc83fd59b..d5fdd15d8 100644
--- a/index.html
+++ b/index.html
@@ -60,8 +60,7 @@
     <a href="https://gto76.github.io" rel="author">Jure Šorn</a>
   </header>
 
-   <div class="pagebreak"></div>
-<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>.
+   <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"></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.
@@ -594,6 +593,7 @@
 &lt;TD&gt;     = &lt;DTa&gt;     - &lt;DTa&gt;                <span class="hljs-comment"># Ignores jumps if they share the tzinfo object.</span>
 &lt;D/DT&gt;   = &lt;D/DT&gt;    ± &lt;TD&gt;                 <span class="hljs-comment"># Returned datetime can fall into missing hour.</span>
 &lt;TD&gt;     = &lt;TD&gt;      * &lt;float&gt;              <span class="hljs-comment"># Also `&lt;TD&gt; = abs(&lt;TD&gt;)`, `&lt;TD&gt; = &lt;TD&gt; ± &lt;TD&gt;`.</span>
+&lt;float&gt;  = &lt;TD&gt;      / &lt;TD&gt;                 <span class="hljs-comment"># Also `(&lt;int&gt;, &lt;TD&gt;) = divmod(&lt;TD&gt;, &lt;TD&gt;)`.</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> &lt;<span class="hljs-title">func_name</span>&gt;<span class="hljs-params">(&lt;nondefault_args&gt;)</span>:</span> ...                  <span class="hljs-comment"># E.g. `def func(x, y): ...`.</span>
@@ -1970,6 +1970,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     curses.wrapper(main)
 </code></pre></div>
 
+<p><br></p>
 <div><h1 id="libraries">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">&gt;&gt;&gt; </span><span class="hljs-keyword">import</span> tqdm, time
 <span class="hljs-meta">&gt;&gt;&gt; </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>):

From 1f032eec8df302c75fc32e176ae9095a945f45ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 31 Jul 2025 09:17:48 +0200
Subject: [PATCH 183/186] =?UTF-8?q?Added=20capital=20=C3=9F=20glyph?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../9f94dc20bb2a09c15241d3a880b7ad01-ss2.woff  | Bin 0 -> 478168 bytes
 web/style.css                                  |   8 +++++++-
 web/style_dark3.css                            |   8 +++++++-
 3 files changed, 14 insertions(+), 2 deletions(-)
 create mode 100644 web/OnlineWebFonts_COM_cb7eb796ae7de7195a34c485cacebad1/@font-face/9f94dc20bb2a09c15241d3a880b7ad01-ss2.woff

diff --git a/web/OnlineWebFonts_COM_cb7eb796ae7de7195a34c485cacebad1/@font-face/9f94dc20bb2a09c15241d3a880b7ad01-ss2.woff b/web/OnlineWebFonts_COM_cb7eb796ae7de7195a34c485cacebad1/@font-face/9f94dc20bb2a09c15241d3a880b7ad01-ss2.woff
new file mode 100644
index 0000000000000000000000000000000000000000..a60995641ed6cdb3bf049137f92c59278f1491a1
GIT binary patch
diff --git a/web/style.css b/web/style.css
index 87e0fb4a6..1d3f07860 100644
--- a/web/style.css
+++ b/web/style.css
@@ -129,7 +129,7 @@ a:not(:hover) {
 pre,
 code,
 textarea {
-  font-family: "Menlo", "Menlo Web", monospace;
+  font-family: "Menlo", "Menlo Web", "Menlo Web ss", monospace;
 }
 
 code {
@@ -277,6 +277,12 @@ ul {
   font-weight: bold;
 }
 
+@font-face {font-family: "Menlo web ss";
+  src: url("OnlineWebFonts_COM_cb7eb796ae7de7195a34c485cacebad1\\@font-face\\9f94dc20bb2a09c15241d3a880b7ad01-ss2.woff") format("woff");
+  font-weight: normal;
+}
+
+
 .join,
 .link,
 .node rect {
diff --git a/web/style_dark3.css b/web/style_dark3.css
index 2f74cc560..3b39fdbf7 100644
--- a/web/style_dark3.css
+++ b/web/style_dark3.css
@@ -129,7 +129,7 @@ a:not(:hover) {
 pre,
 code,
 textarea {
-  font-family: "Menlo", "Menlo Web", monospace;
+  font-family: "Menlo", "Menlo Web", "Menlo Web ss", monospace;
 }
 
 code {
@@ -281,6 +281,12 @@ ul {
   font-weight: bold;
 }
 
+@font-face {font-family: "Menlo web ss";
+  src: url("OnlineWebFonts_COM_cb7eb796ae7de7195a34c485cacebad1\\@font-face\\9f94dc20bb2a09c15241d3a880b7ad01-ss2.woff") format("woff");
+  font-weight: normal;
+}
+
+
 .join,
 .link,
 .node rect {

From c8085b7742e55fadcdcbb90926d8e1c3b609d87f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 31 Jul 2025 15:52:32 +0200
Subject: [PATCH 184/186] Duck types, Array

---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index 8fc0f4c71..693d24cf4 100644
--- a/README.md
+++ b/README.md
@@ -1179,7 +1179,7 @@ class Counter:
 
 ### Callable
 * **All functions and classes have a call() method that is executed when they are called.**
-* **Use `'callable(<obj>)'` or `'isinstance(<obj>, collections.abc.Callable)'` to check if object is callable. You can also just call the object and check if it raised TypeError.**
+* **Use `'callable(<obj>)'` or `'isinstance(<obj>, collections.abc.Callable)'` to check if object is callable. You can also call the object and check if it raised TypeError.**
 * **When this cheatsheet uses `'<function>'` as an argument, it means `'<callable>'`.**
 ```python
 class Counter:
@@ -2028,7 +2028,7 @@ b'\x00\x01\x00\x02\x00\x00\x00\x03'
 
 Array
 -----
-**List that can only hold numbers of a predefined 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/every element can be reversed (by calling the byteswap() method).**
+**List that can only hold numbers of a predefined 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).**
 
 ```python
 from array import array

From ba7feba5010aad8faa9e5727b6ddb21be13fbf67 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 31 Jul 2025 15:56:29 +0200
Subject: [PATCH 185/186] Duck types, Array

---
 index.html | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/index.html b/index.html
index d5fdd15d8..e9a6c51dd 100644
--- a/index.html
+++ b/index.html
@@ -1008,7 +1008,7 @@
 <li><strong>File objects returned by the <a href="#open">open()</a> function, 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(&lt;obj&gt;)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(&lt;obj&gt;, collections.abc.Callable)'</span></code> to check if object is callable. You can also just call the object and check if it raised TypeError.</strong></li>
+<li><strong>Use <code class="python hljs"><span class="hljs-string">'callable(&lt;obj&gt;)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(&lt;obj&gt;, collections.abc.Callable)'</span></code> to check if object is callable. You can also call the object and check if it raised TypeError.</strong></li>
 <li><strong>When this cheatsheet uses <code class="python hljs"><span class="hljs-string">'&lt;function&gt;'</span></code> as an argument, it means <code class="python hljs"><span class="hljs-string">'&lt;callable&gt;'</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>
@@ -1692,7 +1692,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
 
 
 
-<div><h2 id="array"><a href="#array" name="array">#</a>Array</h2><p><strong>List that can only hold numbers of a predefined 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/every 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
+<div><h2 id="array"><a href="#array" name="array">#</a>Array</h2><p><strong>List that can only hold numbers of a predefined 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>
 
 

From e4a3870f792db973913a0be6f61208bc326be63d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Thu, 31 Jul 2025 20:22:31 +0200
Subject: [PATCH 186/186] Plotly

---
 README.md  | 8 ++++----
 index.html | 8 ++++----
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/README.md b/README.md
index 693d24cf4..f50b62380 100644
--- a/README.md
+++ b/README.md
@@ -3453,17 +3453,17 @@ def main():
     display_data(df)
 
 def get_covid_cases():
-    url = 'https://covid.ourworldindata.org/data/owid-covid-data.csv'
+    url = 'https://catalog.ourworldindata.org/garden/covid/latest/compact/compact.csv'
     df = pd.read_csv(url, parse_dates=['date'])
-    df = df[df.location == 'World']
+    df = df[df.country == 'World']
     s = df.set_index('date').total_cases
     return s.rename('Total Cases')
 
 def get_tickers():
     with selenium.webdriver.Chrome() as driver:
+        driver.implicitly_wait(10)
         symbols = {'Bitcoin': 'BTC-USD', 'Gold': 'GC=F', 'Dow Jones': '%5EDJI'}
-        for name, symbol in symbols.items():
-            yield get_ticker(driver, name, symbol)
+        return [get_ticker(driver, name, symbol) for name, symbol in symbols.items()]
 
 def get_ticker(driver, name, symbol):
     url = f'https://finance.yahoo.com/quote/{symbol}/history/'
diff --git a/index.html b/index.html
index e9a6c51dd..924e5366a 100644
--- a/index.html
+++ b/index.html
@@ -2817,17 +2817,17 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment
     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://covid.ourworldindata.org/data/owid-covid-data.csv'</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.location == <span class="hljs-string">'World'</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">for</span> name, symbol <span class="hljs-keyword">in</span> symbols.items():
-            <span class="hljs-keyword">yield</span> get_ticker(driver, name, symbol)
+        <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>
