From ddfd08a10c651449a66484f4cc3dc7ba641cdef7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jure=20=C5=A0orn?= <sornjure@gmail.com>
Date: Sun, 27 Jan 2019 08:47:06 +0100
Subject: [PATCH] Argparse and corrections

---
 README.md | 258 +++++++++++++++++++++++++++++++++---------------------
 1 file changed, 160 insertions(+), 98 deletions(-)

diff --git a/README.md b/README.md
index 90631ba..5a08795 100644
--- a/README.md
+++ b/README.md
@@ -101,12 +101,12 @@ Set
 ```
 
 ```python
-<set>  = <set>.union(<collection>)                 # Or: <set> | <set>
-<set>  = <set>.intersection(<collection>)          # Or: <set> & <set>
-<set>  = <set>.difference(<collection>)            # Or: <set> - <set>
-<set>  = <set>.symmetric_difference(<collection>)  # Or: <set> ^ <set>
-<bool> = <set>.issubset(<collection>)              # Or: <set> < <set>
-<bool> = <set>.issuperset(<collection>)            # Or: <set> > <set>
+<set>  = <set>.union(<coll.>)                 # Or: <set> | <set>
+<set>  = <set>.intersection(<coll.>)          # Or: <set> & <set>
+<set>  = <set>.difference(<coll.>)            # Or: <set> - <set>
+<set>  = <set>.symmetric_difference(<coll.>)  # Or: <set> ^ <set>
+<bool> = <set>.issubset(<coll.>)              # Or: <set> <= <set>
+<bool> = <set>.issuperset(<coll.>)            # Or: <set> >= <set>
 ```
 
 ### Frozenset
@@ -158,6 +158,11 @@ Point(x=1, y=2)
 
 Iterator
 --------
+```python
+<iter> = iter(<collection>)
+<iter> = iter(<function>, to_exclusive)
+```
+
 #### Skips first element:
 ```python
 next(<iter>)
@@ -184,10 +189,10 @@ Generator
 **Convenient way to implement the iterator protocol.**
 
 ```python
-def step(start, step):
+def step(start, step_size):
     while True:
         yield start
-        start += step
+        start += step_size
 ```
 
 ```python
@@ -205,8 +210,11 @@ Type
 
 ```python
 from numbers import Number, Integral, Real, Rational, Complex
-is_number   = isinstance(<el>, Number)
-is_function = callable(<el>)
+<bool> = isinstance(<el>, Number)
+```
+
+```python
+<bool> = callable(<el>)
 ```
 
 
@@ -219,7 +227,7 @@ String
 
 ```python
 <list> = <str>.split()                       # Splits on any whitespace character.
-<list> = <str>.split(sep=None, maxsplit=-1)  # Splits on 'sep' at most 'maxsplit' times.
+<list> = <str>.split(sep=None, maxsplit=-1)  # Splits on 'sep' str at most 'maxsplit' times.
 <str>  = <str>.join(<list>)                  # Joins elements using string as separator.
 ```
 
@@ -265,12 +273,12 @@ Regex
 -----
 ```python
 import re
-<str>   = re.sub(<regex>, new, text, count=0)  # Substitutes all occurrences.
-<list>  = re.findall(<regex>, text)
-<list>  = re.split(<regex>, text, maxsplit=0)  # Use brackets in regex to keep the matches.
-<Match> = re.search(<regex>, text)             # Searches for first occurrence of pattern.
-<Match> = re.match(<regex>, text)              # Searches only at the beginning of the text.
-<Match_iter> = re.finditer(<regex>, text)      # Searches for all occurrences of pattern.
+<str>     = re.sub(<regex>, new, text, count=0)  # Substitutes all occurrences.
+<list>    = re.findall(<regex>, text)            # Returns all occurrences.
+<list>    = re.split(<regex>, text, maxsplit=0)  # Use brackets in regex to keep the matches.
+<Match>   = re.search(<regex>, text)             # Searches for first occurrence of pattern.
+<Match>   = re.match(<regex>, text)              # Searches only at the beginning of the text.
+<Matches> = re.finditer(<regex>, text)           # Searches for all occurrences of pattern.
 ```
 
 * **Parameter `'flags=re.IGNORECASE'` can be used with all functions.**
@@ -323,7 +331,7 @@ Format
 ### String Options
 **"!r" uses object's repr() method, instead of format(), to get a string:** 
 ```python
-{'abcde'!r}      # "'abcde'"
+{'abcde'!r:<10}  # "'abcde'   "
 ```
 
 ```python
@@ -338,11 +346,11 @@ Format
 ```
 
 ```python
-{123456:10,}     # '   123,456'
-{123456:10_}     # '   123_456'
-{123456:+10}     # '   +123456'
+{ 123456:10,}    # '   123,456'
+{ 123456:10_}    # '   123_456'
+{ 123456:+10}    # '   +123456'
 {-123456:=10}    # '-   123456'
-{123456: }       # ' 123456'
+{ 123456: }      # ' 123456'
 {-123456: }      # '-123456'
 ```
 
@@ -368,9 +376,9 @@ Numbers
 -------
 ### Basic Functions
 ```python
-pow(x, y)   # Or: x ** y
-abs(<num>)
-round(<num> [, ndigits])
+<num>  = pow(<num>, <num>)   # Or: <num> ** <num>
+<real> = abs(<num>)
+<real> = round(<real> [, ndigits])
 ```
 
 ### Constants
@@ -386,9 +394,7 @@ from math import cos, acos, sin, asin, tan, atan, degrees, radians
 ### Logarithm
 ```python
 from math import log, log10, log2
-log(x [, base])  # Base e, if not specified.
-log10(x)         # Base 10.
-log2(x)          # Base 2.
+<float> = log(<real> [, base])  # Base e, if not specified.
 ```
 
 ### Infinity, nan
@@ -426,6 +432,7 @@ now.strftime('%Y%m%d%H%M%S')   # '20180315002834'
 Arguments
 ---------
 **"*" is the splat operator, that takes a list as input, and expands it into actual positional arguments in the function call.**
+
 ```python
 args   = (1, 2)
 kwargs = {'x': 3, 'y': 4, 'z': 5}
@@ -473,7 +480,7 @@ lambda <argument_1>, <argument_2>: <return_value>
 ### Comprehension
 ```python
 <list> = [i+1 for i in range(10)]         # [1, 2, ..., 10]
-<set>  = {i for i in range(10) if i > 5}  # {6, 7, ..., 9}
+<set>  = {i for i in range(10) if i > 5}  # {6, 7, 8, 9}
 <dict> = {i: i*2 for i in range(10)}      # {0: 0, 1: 2, ..., 9: 18}
 <iter> = (i+5 for i in range(10))         # (5, 6, ..., 14)
 ```
@@ -500,7 +507,8 @@ from functools import reduce
 
 ### Any, All
 ```python
-<bool> = any(el[1] for el in <collection>)
+<bool> = any(<collection>)                  # False if empty.
+<bool> = all(el[1] for el in <collection>)  # True if empty.
 ```
 
 ### If - Else
@@ -587,10 +595,11 @@ Class
 class <name>:
     def __init__(self, a):
         self.a = a
+    def __repr__(self):
+        class_name = type(self).__name__
+        return f'{class_name}({self.a:!r})'
     def __str__(self):
         return str(self.a)
-    def __repr__(self):
-        return str({'a': self.a})  # Or: return f'{self.__dict__}'
 
     @classmethod
     def get_class_name(cls):
@@ -640,11 +649,11 @@ class <enum_name>(Enum):
 ```
 
 ```python
-<member>  = <enum>.<member_name>
-<member>  = <enum>['<member_name>']
-<member>  = <enum>(<value>)
-<name>    = <member>.name
-<value>   = <member>.value
+<member> = <enum>.<member_name>
+<member> = <enum>['<member_name>']
+<member> = <enum>(<value>)
+name     = <member>.name
+value    = <member>.value
 ```
 
 ```python
@@ -725,6 +734,8 @@ b'.\n..\nfile1.txt\nfile2.txt\n'
 ```
 
 ### Input
+**Reads a line from user input or pipe if present. The trailing newline gets stripped.**
+
 ```python
 filename = input('Enter a file name: ')
 ```
@@ -740,9 +751,10 @@ while True:
 
 ### Recursion Limit
 ```python
+>>> import sys
 >>> sys.getrecursionlimit()
 1000
->>> sys.setrecursionlimit(10000)
+>>> sys.setrecursionlimit(5000)
 ```
 
 JSON
@@ -783,6 +795,8 @@ SQLite
 ```python
 import sqlite3
 db = sqlite3.connect(<filename>)
+...
+db.close()
 ```
 
 ### Read
@@ -791,7 +805,6 @@ cursor = db.execute(<query>)
 if cursor:
     <tuple> = cursor.fetchone()  # First row.
     <list>  = cursor.fetchall()  # Remaining rows.
-db.close()
 ```
 
 ### Write
@@ -845,21 +858,27 @@ KeyboardInterrupt
 
 Bytes
 -----
-**Bytes objects are immutable sequences of single bytes.**
+**Bytes object is immutable sequence of single bytes. Mutable version is called bytearray. **
+
+```python
+<int>   = <bytes>[<index>]
+<bytes> = <bytes>[<slice>]
+<bytes> = b''.join(<coll_of_bytes>)
+```
 
 ### Encode
 ```python
-<Bytes> = b'<str>'
-<Bytes> = <str>.encode(encoding='utf-8')
-<Bytes> = <int>.to_bytes(<length>, byteorder='big|little', signed=False)
-<Bytes> = bytes.fromhex(<hex>)
+<bytes> = b'<str>'
+<bytes> = <str>.encode(encoding='utf-8')
+<bytes> = <int>.to_bytes(<length>, byteorder='big|little', signed=False)
+<bytes> = bytes.fromhex(<hex>)
 ```
 
 ### Decode
 ```python
-<str> = <Bytes>.decode('utf-8') 
-<int> = int.from_bytes(<Bytes>, byteorder='big|little', signed=False)
-<hex> = <Bytes>.hex()
+<str> = <bytes>.decode('utf-8') 
+<int> = int.from_bytes(<bytes>, byteorder='big|little', signed=False)
+<hex> = <bytes>.hex()
 ```
 
 ### Read Bytes from File
@@ -871,50 +890,53 @@ def read_bytes(filename):
 
 ### Write Bytes to File
 ```python
-def write_bytes(filename, bytes):
+def write_bytes(filename, bytes_obj):
     with open(filename, 'wb') as file:
-        file.write(bytes)
-```
-
-```python
-<Bytes> = b''.join(<list_of_Bytes>)
+        file.write(bytes_obj)
 ```
 
 
 Struct
 ------
-**This module performs conversions between Python values and C struct represented as Python Bytes object.**
+**This module performs conversions between Python values and C struct represented as Python bytes object. By default machine’s native sizes and byte order are used.**
+
 ```python
-from struct import pack, unpack
-<Bytes> = pack('<format>', <value_1> [, <value_2>, ...])
-<tuple> = unpack('<format>', <Bytes>)
+from struct import pack, unpack, calcsize
+<bytes> = pack('<format>', <value_1> [, <value_2>, ...])
+<tuple> = unpack('<format>', <bytes>)
 ```
 
 ### Example
 ```python
->>> pack('hhl', 1, 2, 3)
+>>> pack('>hhl', 1, 2, 3)
 b'\x00\x01\x00\x02\x00\x00\x00\x03'
->>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
+>>> unpack('>hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
 (1, 2, 3)
->>> calcsize('hhl')
+>>> calcsize('>hhl')
 8
 ```
 
 ### Format
-**Use capital leters for unsigned type.** 
+**For standard sizes start format string with:**
+* `'='` - native byte order
+* `'<'` - little-endian
+* `'>'` - big-endian
+
+**Use capital leter for unsigned type. Standard size in brackets.** 
 * `'x'` - pad byte
-* `'c'` - char
-* `'h'` - short
-* `'i'` - int
-* `'l'` - long
-* `'q'` - long long
-* `'f'` - float
-* `'d'` - double
+* `'c'` - char (1)
+* `'h'` - short (2)
+* `'i'` - int (4)
+* `'l'` - long (4)
+* `'q'` - long long (8)
+* `'f'` - float (4)
+* `'d'` - double (8)
 
 
 Hashlib
 -------
 ```python
+>>> import hashlib
 >>> hashlib.md5(<str>.encode()).hexdigest()
 '33d0eba106da4d3ebca17fcd3f4c3d77'
 ```
@@ -936,7 +958,7 @@ thread.join()
 
 ### Lock
 ```python
-lock = Rlock()
+lock = RLock()
 lock.acquire()
 ...
 lock.release()
@@ -945,7 +967,7 @@ lock.release()
 
 Itertools
 ---------
-**Every function returns an iterator and can accept any collection and/or iterator. If you want to print the iterator, you need to pass it to the list() function.**
+**Every function returns an iterator and can accept any collection and/or iterator. If you want to print the iterator, you need to pass it to the list() function!**
 
 ```python
 from itertools import *
@@ -1022,9 +1044,9 @@ Introspection and Metaprograming
 
 ### Variables
 ```python
-<list> = dir()      # In-scope variables.
-<dict> = locals()   # Local variables.
-<dict> = globals()  # Global variables.
+<list> = dir()      # Names of in-scope variables.
+<dict> = locals()   # Dict of local variables, same as vars().
+<dict> = globals()  # Dict of global variables.
 ```
 
 ### Attributes
@@ -1050,11 +1072,11 @@ False
 ```
 
 ### Parameters
-#### Getting the number of parameters of a function:
 ```python
 from inspect import signature
 sig          = signature(<function>)
 no_of_params = len(sig.parameters)
+param_names  = list(sig.parameters.keys())
 ```
 
 ### Type
@@ -1072,7 +1094,7 @@ type(<class_name>, <parents_tuple>, <attributes_dict>)
 #### Class that creates class.
 ```python
 def my_meta_class(name, parents, attrs):
-    attrs['a'] = 1
+    attrs['a'] = 'abcde'
     return type(name, parents, attrs)
 ```
 
@@ -1080,7 +1102,7 @@ def my_meta_class(name, parents, attrs):
 ```python
 class MyMetaClass(type):
     def __new__(klass, name, parents, attrs):
-        attrs['a'] = 1
+        attrs['a'] = 'abcde'
         return type.__new__(klass, name, parents, attrs)
 ```
 
@@ -1089,7 +1111,7 @@ class MyMetaClass(type):
 ```python
 class MyClass(metaclass=MyMetaClass):
     def __init__(self):
-        self.b = 2
+        self.b = 12345
 ```
 
 
@@ -1121,7 +1143,7 @@ Eval
 3
 >>> literal_eval('[1, 2, 3]')
 [1, 2, 3]
->>> ast.literal_eval('abs(-1)')
+>>> ast.literal_eval('abs(1)')
 ValueError: malformed node or string
 ```
 
@@ -1218,6 +1240,45 @@ reader(adder(printer()))  # 100, 101, ..., 109
 Libraries
 =========
 
+Argparse
+--------
+```python
+import argparse
+parser = argparse.ArgumentParser(description='calculate X to the power of Y')
+group = parser.add_mutually_exclusive_group()
+group.add_argument('-v', '--verbose', action='store_true')
+group.add_argument('-q', '--quiet', action='store_true')
+parser.add_argument('x', type=int, help='the base')
+parser.add_argument('y', type=int, help='the exponent')
+args = parser.parse_args()
+answer = args.x ** args.y
+
+if args.quiet:
+    print(answer)
+elif args.verbose:
+    print('{args.x} to the power {args.y} equals {answer}')
+else:
+    print('{args.x}^{args.y} == {answer}')
+```
+
+#### Usage:
+```bash
+$ python3 prog.py --help
+usage: test2.py [-h] [-v | -q] x y
+
+calculate X to the power of Y
+
+positional arguments:
+  x              the base
+  y              the exponent
+
+optional arguments:
+  -h, --help     show this help message and exit
+  -v, --verbose
+  -q, --quiet
+```
+
+
 Plot
 ----
 ```python
@@ -1235,10 +1296,10 @@ Progress Bar
 # $ pip3 install tqdm
 from tqdm import tqdm
 from time import sleep
-for i in tqdm(range(100)):
-    sleep(0.02)
 for i in tqdm([1, 2, 3]):
     sleep(0.2)
+for i in tqdm(range(100)):
+    sleep(0.02)
 ```
 
 
@@ -1348,7 +1409,7 @@ Scraping
 >>> document = BeautifulSoup(page.text, 'html.parser')
 >>> table    = document.find('table', class_='infobox vevent')
 >>> rows     = table.find_all('tr')
->>> website  = rows[11].find('a')['href']
+>>> link     = rows[11].find('a')['href']
 'https://www.python.org/'
 >>> latest_v = rows[6].find('div').text.split()[0]
 '3.7.2'
@@ -1396,7 +1457,7 @@ def odds_handler(sport):
     home_odds, away_odds = get_odds(db, sport, team)
     db.close()
 
-    response.headers['Content-Type'] = 'application/json'
+    response.headers['Content-Type']  = 'application/json'
     response.headers['Cache-Control'] = 'no-cache'
     return json.dumps([home_odds, away_odds])
 ```
@@ -1456,6 +1517,7 @@ with PyCallGraph(output=graph):
 NumPy
 -----
 **Array manipulation mini language. Can run up to 100 times faster than equivalent Python code.**
+
 ```python
 # $ pip3 install numpy
 import numpy as np
@@ -1463,7 +1525,7 @@ import numpy as np
 
 ```python
 <array> = np.array(<list>)
-<array> = np.arange(from_inclusive, to_exclusive, step)
+<array> = np.arange(from_inclusive, to_exclusive, step_size)
 <array> = np.ones(<shape>)
 <array> = np.random.randint(from_inclusive, to_exclusive, <shape>)
 ```
@@ -1501,27 +1563,27 @@ right = [[0.1, 0.6, 0.8], [0.1, 0.6, 0.8], [0.1, 0.6, 0.8]]  # Shape: (3, 3) <-
 **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])
-array([ 0.1,  0.6,  0.8])
+[ 0.1,  0.6,  0.8]
 >>> wrapped_points = points.reshape(3, 1)
-array([[ 0.1],
-       [ 0.6],
-       [ 0.8]])
+[[ 0.1],
+ [ 0.6],
+ [ 0.8]]
 >>> distances = wrapped_points - points
-array([[ 0. , -0.5, -0.7],
-       [ 0.5,  0. , -0.2],
-       [ 0.7,  0.2,  0. ]])
+[[ 0. , -0.5, -0.7],
+ [ 0.5,  0. , -0.2],
+ [ 0.7,  0.2,  0. ]]
 >>> distances = np.abs(distances)
-array([[ 0. ,  0.5,  0.7],
-       [ 0.5,  0. ,  0.2],
-       [ 0.7,  0.2,  0. ]])
+[[ 0. ,  0.5,  0.7],
+ [ 0.5,  0. ,  0.2],
+ [ 0.7,  0.2,  0. ]]
 >>> i = np.arange(3)
-array([0, 1, 2])
+[0, 1, 2]
 >>> distances[i, i] = np.inf
-array([[ inf,  0.5,  0.7],
-       [ 0.5,  inf,  0.2],
-       [ 0.7,  0.2,  inf]])
+[[ inf,  0.5,  0.7],
+ [ 0.5,  inf,  0.2],
+ [ 0.7,  0.2,  inf]]
 >>> distances.argmin(1)
-array([1, 2, 1])
+[1, 2, 1]
 ```