diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index ada944a53..000000000
--- a/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-.idea
-.Rhistory
diff --git a/README.md b/README.md
index 43ecee136..202b25f7e 100644
--- a/README.md
+++ b/README.md
@@ -1,785 +1,3588 @@
Comprehensive Python Cheatsheet
===============================
+[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).
+

+
+Contents
+--------
+** ** **1. Collections:** ** ** **[`List`](#list)**__,__ **[`Dictionary`](#dictionary)**__,__ **[`Set`](#set)**__,__ **[`Tuple`](#tuple)**__,__ **[`Range`](#range)**__,__ **[`Enumerate`](#enumerate)**__,__ **[`Iterator`](#iterator)**__,__ **[`Generator`](#generator)**__.__
+** ** **2. Types:** ** ** **[`Type`](#type)**__,__ **[`String`](#string)**__,__ **[`Regular_Exp`](#regex)**__,__ **[`Format`](#format)**__,__ **[`Numbers`](#numbers-1)**__,__ **[`Combinatorics`](#combinatorics)**__,__ **[`Datetime`](#datetime)**__.__
+** ** **3. Syntax:** ** ** **[`Function`](#function)**__,__ **[`Inline`](#inline)**__,__ **[`Import`](#imports)**__,__ **[`Decorator`](#decorator)**__,__ **[`Class`](#class)**__,__ **[`Duck_Type`](#duck-types)**__,__ **[`Enum`](#enum)**__,__ **[`Except`](#exceptions)**__.__
+** ** **4. System:** ** ** **[`Exit`](#exit)**__,__ **[`Print`](#print)**__,__ **[`Input`](#input)**__,__ **[`Command_Line_Arguments`](#command-line-arguments)**__,__ **[`Open`](#open)**__,__ **[`Path`](#paths)**__,__ **[`OS_Commands`](#os-commands)**__.__
+** ** **5. Data:** ** ** **[`JSON`](#json)**__,__ **[`Pickle`](#pickle)**__,__ **[`CSV`](#csv)**__,__ **[`SQLite`](#sqlite)**__,__ **[`Bytes`](#bytes)**__,__ **[`Struct`](#struct)**__,__ **[`Array`](#array)**__,__ **[`Memory_View`](#memory-view)**__,__ **[`Deque`](#deque)**__.__
+** ** **6. Advanced:** ** ** **[`Operator`](#operator)**__,__ **[`Match_Stmt`](#match-statement)**__,__ **[`Logging`](#logging)**__,__ **[`Introspection`](#introspection)**__,__ **[`Threading`](#threading)**__,__ **[`Coroutines`](#coroutines)**__.__
+** ** **7. Libraries:** ** ** **[`Progress_Bar`](#progress-bar)**__,__ **[`Plot`](#plot)**__,__ **[`Table`](#table)**__,__ **[`Console_App`](#console-app)**__,__ **[`GUI`](#gui-app)**__,__ **[`Scraping`](#scraping)**__,__ **[`Web`](#web-app)**__,__ **[`Profile`](#profiling)**__.__
+** ** **8. Multimedia:** ** ** **[`NumPy`](#numpy)**__,__ **[`Image`](#image)**__,__ **[`Animation`](#animation)**__,__ **[`Audio`](#audio)**__,__ **[`Synthesizer`](#synthesizer)**__,__ **[`Pygame`](#pygame)**__,__ **[`Pandas`](#pandas)**__,__ **[`Plotly`](#plotly)**__.__
+
+
Main
----
```python
-if __name__ == '__main__':
- main()
+if __name__ == '__main__': # Skips indented lines of code if file was imported.
+ main() # Executes user-defined `def main(): ...` function.
```
List
----
```python
-[from_inclusive : to_exclusive : step_size]
-.extend()
-.sort()
-.reverse()
+ = [, , ...] # Creates a new list object. Also list().
+```
+
+```python
+ = [index] # First index is 0, last -1. Also `[i] = `.
+ = [] # Also [from_inclusive : to_exclusive : ±step].
+```
+
+```python
+.append() # Appends element to the end. Also ` += []`.
+.extend() # Appends multiple elements. Also ` += `.
+```
+
+```python
+.sort(reverse=False) # Sorts the elements of the list in ascending order.
+.reverse() # Reverses the order of elements. Takes linear time.
+ = sorted() # Returns a new sorted list. Accepts `reverse=True`.
+ = reversed() # Returns reversed iterator. Also list().
+```
+
+```python
+ = max() # Returns the largest element. Also min(, ...).
+ = sum() # Returns a sum of elements. Also math.prod().
+```
+
+```python
+elementwise_sum = [sum(pair) for pair in zip(list_a, list_b)]
+sorted_by_second = sorted(, key=lambda el: el[1])
+sorted_by_both = sorted(, key=lambda el: (el[1], el[0]))
+flatter_list = list(itertools.chain.from_iterable())
```
+* **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).**
```python
-sum()
-sorted_by_second = sorted(, key=lambda tup: tup[1])
-flattened_list = [item for sublist in for item in sublist]
+ = len() # Returns number of items. Doesn't accept iterators.
+ = .count() # Counts occurrences. Also `if in : ...`.
+ = .index() # Returns index of first occ. or raises ValueError.
+ = .pop() # Removes item from the end (or at index if passed).
+.insert(, ) # Inserts item at index and shifts remaining items.
+.remove() # Removes the first occurrence or raises ValueError.
+.clear() # Removes all items. Also provided by dict and set.
```
+
Dictionary
----------
```python
-.items()
-.get(key, default)
-.setdefault(key, default)
-.update()
+ = {key_1: val_1, key_2: val_2, ...} # Use `[key]` to get or assign the value.
+```
+
+```python
+ = .keys() # A collection of keys that reflects changes.
+ = .values() # A collection of values that reflects changes.
+ = .items() # Coll. of key-value tuples that reflects chgs.
+```
+
+```python
+value = .get(key, default=None) # Returns argument default if key is missing.
+value = .setdefault(key, default=None) # Returns and writes default if key is missing.
+ = collections.defaultdict() # Dict with automatic default value `()`.
+ = collections.defaultdict(lambda: 1) # Dictionary with automatic default value 1.
```
```python
-collections.defaultdict() # Creates a dictionary with default values.
-dict(zip(keys, values)) # Initiates a dict from two lists.
-{k: v for k, v in .iteritems() if k in } # Filters a dict by keys.
+ = dict() # Creates a dict from coll. of key-value pairs.
+ = dict(zip(keys, values)) # Creates a dictionary from two collections.
+ = dict.fromkeys(keys [, value]) # Creates a dictionary from collection of keys.
+```
+
+```python
+.update() # Adds items. Replaces ones with matching keys.
+value = .pop(key) # Removes item or raises KeyError if missing.
+{k for k, v in .items() if v == value} # Returns set of keys that point to the value.
+{k: v for k, v in .items() if k in keys} # Returns a dict of items with specified keys.
```
### Counter
```python
>>> from collections import Counter
->>> z = ['blue', 'red', 'blue', 'yellow', 'blue', 'red']
->>> Counter(z)
-Counter({'blue': 3, 'red': 2, 'yellow': 1})
+>>> counter = Counter(['blue', 'blue', 'blue', 'red', 'red'])
+>>> counter['yellow'] += 1
+>>> print(counter.most_common())
+[('blue', 3), ('red', 2), ('yellow', 1)]
```
+
Set
---
```python
- = set()
-.add()
-.update()
-.union()
-.intersection()
-.difference()
-frozenset() # Is hashable and can be used as a key in dictionary.
+ = {, , ...} # Coll. of unique items. Also set(), set().
```
-### Frozenset
-#### Is hashable and can be used as a key in dictionary:
```python
- = frozenset()
+.add() # Adds item to the set. Same as ` |= {}`.
+.update( [, ...]) # Adds items to the set. Same as ` |= `.
```
+```python
+ = .union() # Returns a set of all items. Also | .
+ = .intersection() # Returns all shared items. Also & .
+ = .difference() # Returns set's unique items. Also - .
+ = .symmetric_difference() # Returns non-shared items. Also ^ .
+ = .issuperset() # Returns False if collection has unique items.
+ = .issubset() # Is collection a superset? Also <= .
+```
+
+```python
+ = .pop() # Removes and returns an item or raises KeyError.
+.remove() # Removes the item or raises KeyError if missing.
+.discard() # Same as remove() but it doesn't raise an error.
+```
+
+### Frozen Set
+* **Is immutable and hashable.**
+* **That means it can be used as a key in a dictionary or as an item in a set.**
+```python
+ = frozenset()
+```
+
+
+Tuple
+-----
+**Tuple is an immutable and hashable list.**
+```python
+ = () # Returns an empty tuple. Also tuple(), tuple().
+ = (,) # Returns a tuple with single element. Same as `,`.
+ = (, [, ...]) # Returns a tuple. Same as `, [, ...]`.
+```
+
+### Named Tuple
+**Tuple's subclass with named elements.**
+```python
+>>> from collections import namedtuple
+>>> Point = namedtuple('Point', 'x y')
+>>> p = Point(1, y=2)
+>>> print(p)
+Point(x=1, y=2)
+>>> p.x, p[1]
+(1, 2)
+```
+
+
Range
-----
+**Immutable and hashable sequence of integers.**
```python
-range(to_exclusive)
-range(from_inclusive, to_exclusive)
-range(from_inclusive, to_exclusive, step_size)
-range(from_inclusive, to_exclusive, -step_size)
+ = range(stop) # I.e. range(to_exclusive). Integers from 0 to `stop-1`.
+ = range(start, stop) # I.e. range(from_inc, to_exc). From start to `stop-1`.
+ = range(start, stop, ±step) # I.e. range(from_inclusive, to_exclusive, ±step_size).
```
-Enumerate
----------
```python
-for i, in enumerate( [, i_start])
+>>> [i for i in range(3)]
+[0, 1, 2]
```
-Named Tuple
------------
+
+Enumerate
+---------
```python
->>> TestResults = collections.namedtuple('TestResults', ['filed', 'attempted'])
->>> a = TestResults(1, attempted=2)
-TestResults(filed=1, attempted=2)
->>> a.filed
-1
->>> getattr(a, 'attempted')
-2
+for i, el in enumerate(, start=0): # Returns next element and its index on each pass.
+ ...
```
+
Iterator
--------
-#### Skips first element:
+**Potentially endless stream of elements.**
+
```python
-next()
-for element in :
- ...
+ = iter() # Calling iter() returns unmodified iterator.
+ = iter(, to_exclusive) # A sequence of return values until 'to_exclusive'.
+ = next( [, default]) # Raises StopIteration or returns 'default' on end.
+ = list() # Returns a list of iterator's remaining elements.
```
-#### Reads input until it reaches an empty line:
+### Itertools
```python
-for line in iter(input, ''):
- ...
+import itertools as it
```
-#### Same, but prints a message every time:
```python
-from functools import partial
-for line in iter(partial(input, 'Please enter value'), ''):
- ...
+ = it.count(start=0, step=1) # Returns updated value endlessly. Accepts floats.
+ = it.repeat( [, times]) # Returns passed element endlessly or 'times' times.
+ = it.cycle() # Repeats the passed sequence of elements endlessly.
+```
+
+```python
+ = it.chain(, [, ...]) # Empties collections in order (only figuratively).
+ = it.chain.from_iterable() # Empties collections inside a collection in order.
+```
+
+```python
+ = it.islice(, stop) # Only returns (i.e. yields) first 'stop' elements.
+ = it.islice(, start, stop) # Also accepts `+step`. Start and stop can be None.
```
Generator
---------
+* **Any function that contains a yield statement returns a generator.**
+* **Generators and iterators are interchangeable.**
+
```python
-def step(start, step):
+def count(start, step):
while True:
yield start
start += step
```
+
```python
-stepper = step(10, 2)
-next(stepper) # 10 (, 12, 14, ...)
+>>> counter = count(10, 2)
+>>> next(counter), next(counter), next(counter)
+(10, 12, 14)
```
Type
----
+* **Everything in Python is an object.**
+* **Every object has a certain type.**
+* **Type and class are synonymous.**
+
```python
-type() # //...
+ = type() # Returns object's type. Same as `.__class__`.
+ = isinstance(, ) # Same result as `issubclass(type(), )`.
```
+
```python
-import numbers
-isinstance(, numbers.Number)
+>>> type('a'), 'a'.__class__, str
+(, , )
```
-
-String
-------
+#### Some types do not have built-in names, so they must be imported:
```python
-str.replace(text, old, new)
-.isnumeric()
-.split()
-.strip()
-.join()
+from types import FunctionType, MethodType, LambdaType, GeneratorType, ModuleType
```
-### Print
+### Abstract Base Classes
+**Each abstract base class specifies a set of virtual subclasses. These classes are then recognized by isinstance() and issubclass() as subclasses of the ABC, although they are really not. ABC can also manually decide whether or not a specific class is its virtual subclass, usually based on which methods the class has implemented. For instance, Iterable ABC looks for method iter(), while Collection ABC looks for iter(), contains() and len().**
+
```python
-print( [, , end='', sep='', file=])
+>>> from collections.abc import Iterable, Collection, Sequence
+>>> isinstance([1, 2, 3], Iterable)
+True
```
-### Regex
-```python
-import re
-re.sub(, new, text)
-re.search(, text)
+```text
++------------------+------------+------------+------------+
+| | Iterable | Collection | Sequence |
++------------------+------------+------------+------------+
+| list, range, str | yes | yes | yes |
+| dict, set | yes | yes | |
+| iter | yes | | |
++------------------+------------+------------+------------+
```
-### Format
```python
-'{}'.format( [, , ...])
+>>> from numbers import Number, Complex, Real, Rational, Integral
+>>> isinstance(123, Number)
+True
```
+```text
++--------------------+-----------+-----------+----------+----------+----------+
+| | Number | Complex | Real | Rational | Integral |
++--------------------+-----------+-----------+----------+----------+----------+
+| int | yes | yes | yes | yes | yes |
+| fractions.Fraction | yes | yes | yes | yes | |
+| float | yes | yes | yes | | |
+| complex | yes | yes | | | |
+| decimal.Decimal | yes | | | | |
++--------------------+-----------+-----------+----------+----------+----------+
+```
+
+
+String
+------
+**Immutable sequence of characters.**
```python
-{:min_width} # ' '
-{:>min_width} # ' '
-{:^min_width} # ' '
-{:_min_width} # '____'
-{:.max_width} # ''
+ = 'abc' # Also "abc". Interprets \n, \t, \x00-\xff, etc.
```
+
```python
-{:max_widht.min_width} # ' '
-{:max_width.no_of_decimalsf} # ' 3.14'
+ = .strip() # Strips all whitespace characters from both ends.
+ = .strip('') # Strips passed characters. Also lstrip/rstrip().
```
```python
->>> person = {'name': 'Jean-Luc', 'height': 187.1}
->>> '{p[height]:.0f}'.format(p=person)
-'187'
+ = .split() # Splits it on one or more whitespace characters.
+ = .split(sep=None, maxsplit=-1) # Splits on 'sep' string at most 'maxsplit' times.
+ = .splitlines(keepends=False) # On [\n\r\f\v\x1c-\x1e\x85\u2028\u2029] and \r\n.
+ = .join() # Joins items by using the string as a separator.
```
-### Text Wrap
```python
-import textwrap
-textwrap.wrap(text, width)
+ = in # Returns True if string contains the substring.
+ = .startswith() # Pass tuple of strings to give multiple options.
+ = .find() # Returns start index of the first match or -1.
```
+```python
+ = .lower() # Lowers the case. Also upper/capitalize/title().
+ =