diff --git a/index.html b/index.html index 4a89cc6..a5fd5d9 100644 --- a/index.html +++ b/index.html @@ -146,46 +146,55 @@ pre.prettyprint { } #return-to-top { - position: fixed; - bottom: 20px; - right: 20px; - background: rgb(0, 0, 0); - background: rgba(0, 0, 0, 0.2); - width: 50px; - height: 50px; - display: block; - text-decoration: none; - -webkit-border-radius: 35px; - -moz-border-radius: 35px; - border-radius: 35px; - display: none; - -webkit-transition: all 0.3s linear; - -moz-transition: all 0.3s ease; - -ms-transition: all 0.3s ease; - -o-transition: all 0.3s ease; - transition: all 0.3s ease; + position: fixed; + bottom: 20px; + right: 20px; + background: rgb(0, 0, 0); + background: rgba(0, 0, 0, 0.2); + width: 50px; + height: 50px; + display: block; + text-decoration: none; + -webkit-border-radius: 35px; + -moz-border-radius: 35px; + border-radius: 35px; + display: none; + -webkit-transition: all 0.3s linear; + -moz-transition: all 0.3s ease; + -ms-transition: all 0.3s ease; + -o-transition: all 0.3s ease; + transition: all 0.3s ease; } #return-to-top i { - color: #fff; - margin: 0; - position: relative; - left: 16px; - top: 13px; - font-size: 19px; - -webkit-transition: all 0.3s ease; - -moz-transition: all 0.3s ease; - -ms-transition: all 0.3s ease; - -o-transition: all 0.3s ease; - transition: all 0.3s ease; + color: #fff; + margin: 0; + position: relative; + left: 16px; + top: 13px; + font-size: 19px; + -webkit-transition: all 0.3s ease; + -moz-transition: all 0.3s ease; + -ms-transition: all 0.3s ease; + -o-transition: all 0.3s ease; + transition: all 0.3s ease; } #return-to-top:hover { - background: rgba(0, 0, 0, 0.35); + background: rgba(0, 0, 0, 0.35); } #return-to-top:hover i { - color: #f0f0f0; + color: #f0f0f0; +} + +@media print { + div { + page-break-inside: avoid; + } + pre { + page-break-inside: avoid; + } } @@ -196,14 +205,13 @@ pre.prettyprint { -

Comprehensive Python Cheatsheet

- - +

Comprehensive Python Cheatsheet


+ + -

#Contents

-
ToC = {
+

#Contents

ToC = {
     '1. Collections': [List, Dictionary, Set, Tuple, Range, Enumerate, Iterator, Generator],
     '2. Types':       [Type, String, Regular_Exp, Format, Numbers, Combinatorics, Datetime],
     '3. Syntax':      [Args, Inline, Closure, Decorator, Class, Duck_Types, Enum, Exceptions],
@@ -213,14 +221,15 @@ pre.prettyprint {
     '7. Libraries':   [Progress_Bar, Plot, Table, Curses, Logging, Scraping, Web, Profile,
                        NumPy, Image, Audio]
 }
-
-

#Main

-
if __name__ == '__main__':     # Runs main() if file wasn't imported.
+
+ +

#Main

if __name__ == '__main__':     # Runs main() if file wasn't imported.
     main()
-
-

#List

-
<list> = <list>[from_inclusive : to_exclusive : ±step_size]
-
+
+ +

#List

<list> = <list>[from_inclusive : to_exclusive : ±step_size]
+
+
<list>.append(<el>)            # Or: <list> += [<el>]
 <list>.extend(<collection>)    # Or: <list> += <collection>
 
@@ -243,11 +252,11 @@ list_of_chars = list(<str>) <list>.remove(<el>) # Removes first occurrence of item or raises ValueError. <list>.clear() # Removes all items. Also works on dict and set. -

#Dictionary

-
<view> = <dict>.keys()                          # Coll. of keys that reflects changes.
+

#Dictionary

<view> = <dict>.keys()                          # Coll. of keys that reflects changes.
 <view> = <dict>.values()                        # Coll. of values that reflects changes.
 <view> = <dict>.items()                         # Coll. of key-value tuples.
-
+
+
value  = <dict>.get(key, default=None)          # Returns default if key does not exist.
 value  = <dict>.setdefault(key, default=None)   # Same, but also adds default to dict.
 <dict> = collections.defaultdict(<type>)        # Creates a dict with default value of type.
@@ -261,17 +270,17 @@ value  = <dict>.setdefault(key, default=Nonevalue = <dict>.pop(key)                         # Removes item from dictionary.
 {k: v for k, v in <dict>.items() if k in keys}  # Filters dictionary by keys.
 
-

Counter

-
>>> from collections import Counter
+

Counter

>>> from collections import Counter
 >>> colors = ['red', 'blue', 'yellow', 'blue', 'red', 'blue']
 >>> counter = Counter(colors)
 Counter({'blue': 3, 'red': 2, 'yellow': 1})
 >>> counter.most_common()[0]
 ('blue', 3)
-
-

#Set

-
<set> = set()
-
+
+ +

#Set

<set> = set()
+
+
<set>.add(<el>)                               # Or: <set> |= {<el>}
 <set>.update(<collection>)                    # Or: <set> |= <set>
 
@@ -285,22 +294,20 @@ Counter({'blue': 3<set>.remove(<el>) # Raises KeyError. <set>.discard(<el>) # Doesn't raise an error. -

Frozen Set

-
<frozenset> = frozenset(<collection>)
+
+ + +

#Tuple

Tuple is an immutable and hashable list.

<tuple> = ()
 <tuple> = (<el>, )
 <tuple> = (<el_1>, <el_2>, ...)
-
-

Named Tuple

-

Tuple's subclass with named elements.

-
>>> from collections import namedtuple
+
+ + +

Named Tuple

Tuple's subclass with named elements.

>>> from collections import namedtuple
 >>> Point = namedtuple('Point', 'x y')
 >>> p = Point(1, y=2)
 Point(x=1, y=2)
@@ -312,27 +319,29 @@ Point(x=1, y=2
 2
 >>> p._fields  # Or: Point._fields
 ('x', 'y')
-
-

#Range

-
<range> = range(to_exclusive)
+
+ + +

#Range

<range> = range(to_exclusive)
 <range> = range(from_inclusive, to_exclusive)
 <range> = range(from_inclusive, to_exclusive, ±step_size)
-
+
+
from_inclusive = <range>.start
 to_exclusive   = <range>.stop
 
-

#Enumerate

-
for i, el in enumerate(<collection> [, i_start]):
+

#Enumerate

for i, el in enumerate(<collection> [, i_start]):
     ...
-
-

#Iterator

-
<iter> = iter(<collection>)                 # Calling `iter(<iter>)` returns unmodified iterator.
+
+ +

#Iterator

<iter> = iter(<collection>)                 # Calling `iter(<iter>)` returns unmodified iterator.
 <iter> = iter(<function>, to_exclusive)     # Sequence of return values until 'to_exclusive'.
 <el>   = next(<iter> [, default])           # Raises StopIteration or returns 'default' on end.
-
-

Itertools

-
from itertools import count, repeat, cycle, chain, islice
-
+
+ +

Itertools

from itertools import count, repeat, cycle, chain, islice
+
+
<iter> = count(start=0, step=1)             # Returns incremented value endlessly.
 <iter> = repeat(<el> [, times])             # Returns element endlessly or 'times' times.
 <iter> = cycle(<collection>)                # Repeats the sequence indefinitely.
@@ -344,42 +353,42 @@ to_exclusive   = <range>.stop
 <iter> = islice(<collection>, from_inclusive, to_exclusive)
 <iter> = islice(<collection>, from_inclusive, to_exclusive, +step_size)
 
-

#Generator

-
def count(start, step):
     while True:
         yield start
         start += step
-
+ + +
>>> counter = count(10, 2)
 >>> next(counter), next(counter), next(counter)
 (10, 12, 14)
 
-

#Type

-
<type> = type(<el>)                # Or: <el>.__class__
 <bool> = isinstance(<el>, <type>)  # Or: issubclass(type(<el>), <type>)
-
+ + +
>>> type('a'), 'a'.__class__, str
 (<class 'str'>, <class 'str'>, <class 'str'>)
 
-

Some types do not have builtin names, so they must be imported:

-
from types import FunctionType, MethodType, LambdaType, GeneratorType
-
-

ABC

-

An abstract base class introduces virtual subclasses, that don’t inherit from it but are still recognized by isinstance() and issubclass().

-
>>> from collections.abc import Sequence, Collection, Iterable
+

Some types do not have builtin names, so they must be imported:

from types import FunctionType, MethodType, LambdaType, GeneratorType
+
+ +

ABC

An abstract base class introduces virtual subclasses, that don’t inherit from it but are still recognized by isinstance() and issubclass().

>>> from collections.abc import Sequence, Collection, Iterable
 >>> isinstance([1, 2, 3], Iterable)
 True
-
+
+ +
+------------------+----------+------------+----------+
 |                  | Sequence | Collection | Iterable |
 +------------------+----------+------------+----------+
@@ -401,10 +410,10 @@ to_exclusive   = <range>.stop
 | complex            |          |          |      |   yes   |  yes   |
 +--------------------+----------+----------+------+---------+--------+
 
-

#String

-
<str>  = <str>.strip()                       # Strips all whitespace characters from both ends.
+

#String

<str>  = <str>.strip()                       # Strips all whitespace characters from both ends.
 <str>  = <str>.strip('<chars>')              # Strips all passed characters from both ends.
-
+
+
<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)    # Splits on line breaks. Keeps them if 'keepends'.
@@ -424,10 +433,10 @@ to_exclusive   = <range>.stop
 
  • Also: 'lstrip()', 'rstrip()'.
  • Also: 'lower()', 'upper()', 'capitalize()' and 'title()'.
  • -

    Char

    -
    <str> = chr(<int>)  # Converts int to unicode char.
    +

    Char

    <str> = chr(<int>)  # Converts int to unicode char.
     <int> = ord(<str>)  # Converts unicode char to int.
    -
    +
    +
    >>> ord('0'), ord('9')
     (48, 57)
     >>> ord('A'), ord('Z')
    @@ -435,15 +444,15 @@ to_exclusive   = <range>.stop
     >>> ord('a'), ord('z')
     (97, 122)
     
    -

    #Regex

    -
    import re
    +

    #Regex

    import re
     <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.
     <iter>  = re.finditer(<regex>, text)           # Returns all occurrences as match objects.
    -
    +
    +
    • Argument 'flags=re.IGNORECASE' can be used with all functions.
    • Argument 'flags=re.MULTILINE' makes '^' and '$' match the start/end of each line.
    • @@ -451,65 +460,64 @@ to_exclusive = <range>.stop
    • Use r'\1' or '\\1' for backreference.
    • Use '?' to make an operator non-greedy.
    -

    Match Object

    -
    <str>   = <Match>.group()   # Whole match. Also group(0).
    +

    Match Object

    <str>   = <Match>.group()   # Whole match. Also group(0).
     <str>   = <Match>.group(1)  # Part in first bracket.
     <tuple> = <Match>.groups()  # All bracketed parts.
     <int>   = <Match>.start()   # Start index of a match.
     <int>   = <Match>.end()     # Exclusive end index of a match.
    -
    -

    Special Sequences

    -
      +
    + +

    Special Sequences

    • By default digits, whitespaces and alphanumerics from all alphabets are matched, unless 'flags=re.ASCII' argument is used.
    • Use capital letters for negation.
    • -
    -
    '\d' == '[0-9]'             # Digit
    +
    '\d' == '[0-9]'             # Digit
     '\s' == '[ \t\n\r\f\v]'     # Whitespace
     '\w' == '[a-zA-Z0-9_]'      # Alphanumeric
    -
    -

    #Format

    -
    <str> = f'{<el_1>}, {<el_2>}'
    +
    + + +

    #Format

    <str> = f'{<el_1>}, {<el_2>}'
     <str> = '{}, {}'.format(<el_1>, <el_2>)
    -
    -

    Attributes

    -
    >>> from collections import namedtuple
    +
    + +

    Attributes

    >>> from collections import namedtuple
     >>> Person = namedtuple('Person', 'name height')
     >>> person = Person('Jean-Luc', 187)
     >>> f'{person.height}'
     '187'
     >>> '{p.height}'.format(p=person)
     '187'
    -
    -

    General Options

    -
    {<el>:<10}       # '<el>      '
    +
    + +

    General Options

    {<el>:<10}       # '<el>      '
     {<el>:^10}       # '   <el>   '
     {<el>:>10}       # '      <el>'
    -
    +
    +
    {<el>:.<10}      # '<el>......'
     {<el>:>0}        # '<el>'
     
    -

    Strings

    -

    '!r' calls object's repr() method, instead of str(), to get a string.

    -
    {'abcde'!r:<10}  # "'abcde'   "
    +

    Strings

    '!r' calls object's repr() method, instead of str(), to get a string.

    {'abcde'!r:<10}  # "'abcde'   "
     {'abcde':.3}     # 'abc'
     {'abcde':10.3}   # 'abc       '
    -
    -

    Numbers

    -
    { 123456:10,}    # '   123,456'
    +
    + + +

    Numbers

    { 123456:10,}    # '   123,456'
     { 123456:10_}    # '   123_456'
     { 123456:+10}    # '   +123456'
     {-123456:=10}    # '-   123456'
     { 123456: }      # ' 123456'
     {-123456: }      # '-123456'
    -
    -

    Floats

    -
    {1.23456:10.3}   # '      1.23'
    +
    + +

    Floats

    {1.23456:10.3}   # '      1.23'
     {1.23456:10.3f}  # '     1.235'
     {1.23456:10.3e}  # ' 1.235e+00'
     {1.23456:10.3%}  # '  123.456%'
    -
    -

    Comparison of float presentation types:

    -
    +----------------+----------------+---------------+----------------+-----------------+
    +
    + +

    Comparison of float presentation types:

    +----------------+----------------+---------------+----------------+-----------------+
     |                |    {<float>}   |  {<float>:f}  |   {<float>:e}  |   {<float>:%}   |
     +----------------+----------------+---------------+----------------+-----------------+
     |    0.000056789 |   '5.6789e-05' |    '0.000057' | '5.678900e-05' |     '0.005679%' |
    @@ -521,7 +529,8 @@ to_exclusive   = <range>.stop
     |   56.789       |  '56.789'      |   '56.789000' | '5.678900e+01' |  '5678.900000%' |
     |  567.89        | '567.89'       |  '567.890000' | '5.678900e+02' | '56789.000000%' |
     +----------------+----------------+---------------+----------------+-----------------+
    -
    +
    +
    +----------------+----------------+---------------+----------------+-----------------+
     |                |  {<float>:.2}  | {<float>:.2f} |  {<float>:.2e} |  {<float>:.2%}  |
     +----------------+----------------+---------------+----------------+-----------------+
    @@ -535,62 +544,62 @@ to_exclusive   = <range>.stop
     |  567.89        |   '5.7e+02'    |    '567.89'   |   '5.68e+02'   |   '56789.00%'   |
     +----------------+----------------+---------------+----------------+-----------------+
     
    -

    Ints

    -
    {90:c}           # 'Z'
    +

    Ints

    {90:c}           # 'Z'
     {90:X}           # '5A'
     {90:b}           # '1011010'
    -
    -

    #Numbers

    -
    <int>      = int(<float/str/bool>)    # Or: math.floor(<float>)
    +
    + +

    #Numbers

    <int>      = int(<float/str/bool>)    # Or: math.floor(<float>)
     <float>    = float(<int/str/bool>)
     <complex>  = complex(real=0, imag=0)  # Or: <real> + <real>j
     <Fraction> = fractions.Fraction(numerator=0, denominator=1)
    -
    +
    +
    • 'int(<str>)' and 'float(<str>)' raise 'ValueError' on malformed strings.
    -

    Basic Functions

    -
    <num>  = pow(<num>, <num>)            # Or: <num> ** <num>
    +

    Basic Functions

    <num>  = pow(<num>, <num>)            # Or: <num> ** <num>
     <real> = abs(<num>)
     <int>  = round(<real>)
     <real> = round(<real>, ±ndigits)      # `round(126, -1) == 130`
    -
    -

    Math

    -
    from math import e, pi, inf, nan
    +
    + +

    Math

    from math import e, pi, inf, nan
     from math import cos, acos, sin, asin, tan, atan, degrees, radians
     from math import log, log10, log2
    -
    -

    Statistics

    -
    from statistics import mean, median, variance, pvariance, pstdev
    -
    -

    Random

    -
    from random import random, randint, choice, shuffle
    +
    + +

    Statistics

    from statistics import mean, median, variance, pvariance, pstdev
    +
    + +

    Random

    from random import random, randint, choice, shuffle
     <float> = random()
     <int>   = randint(from_inclusive, to_inclusive)
     <el>    = choice(<list>)
     shuffle(<list>)
    -
    -

    Bin, Hex

    -
    <int>     = 0b<bin>            # Or: 0x<hex>
    +
    + +

    Bin, Hex

    <int>     = 0b<bin>            # Or: 0x<hex>
     <int>     = int('0b<bin>', 0)  # Or: int('0x<hex>', 0)
     <int>     = int('<bin>', 2)    # Or: int('<hex>', 16)
     '0b<bin>' = bin(<int>)         # Or: '0x<hex>' = hex(<int>)
    -
    -

    Bitwise Operators

    -
    <int>     = <int> & <int>      # And
    +
    + +

    Bitwise Operators

    <int>     = <int> & <int>      # And
     <int>     = <int> | <int>      # Or
     <int>     = <int> ^ <int>      # Xor (0 if both bits equal)
     <int>     = <int> << n_bits    # Shift left
     <int>     = <int> >> n_bits    # Shift right
     <int>     = ~<int>             # Compliment (flips bits)
    -
    -

    #Combinatorics

    -
      +
    + +

    #Combinatorics

    • Every function returns an iterator.
    • If you want to print the iterator, you need to pass it to the list() function!
    • -
    -
    from itertools import product, combinations, combinations_with_replacement, permutations
    -
    +
    from itertools import product, combinations, combinations_with_replacement, permutations
    +
    + +
    >>> 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)]
    @@ -612,111 +621,111 @@ shuffle(<list>)
      ('b', 'a'), ('b', 'c'),
      ('c', 'a'), ('c', 'b')]
     
    -

    #Datetime

    -
      +

      #Datetime

      • Module 'datetime' provides 'date' <D>, 'time' <T>, 'datetime' <DT> and 'timedelta' <TD> classes. All are immutable and hashable.
      • Time and datetime can be 'aware' <a>, meaning they have defined timezone, or 'naive' <n>, meaning they don't.
      • If object is naive it is presumed to be in system's timezone.
      • -
      -
      from datetime import date, time, datetime, timedelta
      +
    from datetime import date, time, datetime, timedelta
     from dateutil.tz import UTC, tzlocal, gettz
    -
    -

    Constructors

    -
    <D>  = date(year, month, day)
    +
    + + +

    Constructors

    <D>  = date(year, month, day)
     <T>  = time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, fold=0)
     <DT> = datetime(year, month, day, hour=0, minute=0, second=0, ...)
     <TD> = timedelta(days=0, seconds=0, microseconds=0, milliseconds=0,
                      minutes=0, hours=0, weeks=0)
    -
    +
    +
    • Use '<D/DT>.weekday()' to get the day of the week (Mon == 0).
    • 'fold=1' means second pass in case of time jumping back for one hour.
    -

    Now

    -
    <D/DTn>  = D/DT.today()                     # Current local date or naive datetime.
    +

    Now

    <D/DTn>  = D/DT.today()                     # Current local date or naive datetime.
     <DTn>    = DT.utcnow()                      # Naive datetime from current UTC time.
     <DTa>    = DT.now(<tzinfo>)                 # Aware datetime from current tz time.
    -
    +
    +
    • To extract time use '<DTn>.time()', '<DTa>.time()' or '<DTa>.timetz()'.
    -

    Timezone

    -
    <tzinfo> = UTC                              # UTC timezone. London without DST.
    +

    Timezone

    <tzinfo> = UTC                              # UTC timezone. London without DST.
     <tzinfo> = tzlocal()                        # Local timezone. Also gettz().
     <tzinfo> = gettz('<Cont.>/<City>')          # Timezone from 'Continent/City_Name' str.
    -
    +
    +
    <DTa>    = <DT>.astimezone(<tzinfo>)        # Datetime, converted to passed timezone.
     <Ta/DTa> = <T/DT>.replace(tzinfo=<tzinfo>)  # Unconverted object with new timezone.
     
    -

    Encode

    -
    <D/T/DT> = D/T/DT.fromisoformat('<iso>')    # Object from ISO string.
    +

    Encode

    <D/T/DT> = D/T/DT.fromisoformat('<iso>')    # Object from ISO string.
     <DT>     = DT.strptime(<str>, '<format>')   # Datetime from str, according to format.
     <D/DTn>  = D/DT.fromordinal(<int>)          # D/DTn from days since Christ, at midnight.
     <DTn>    = DT.fromtimestamp(<real>)         # Local time DTn from seconds since Epoch.
     <DTa>    = DT.fromtimestamp(<real>, <tz.>)  # Aware datetime from seconds since Epoch.
    -
    +
    +
    • ISO strings come in following forms: 'YYYY-MM-DD', 'HH:MM:SS.ffffff[±<offset>]', or both separated by 'T'. Offset is formatted as: 'HH:MM'.
    • On Unix systems Epoch is '1970-01-01 00:00 UTC', '1970-01-01 01:00 CET', …
    -

    Decode

    -
    <str>    = <D/T/DT>.isoformat()             # ISO string representation.
    +

    Decode

    <str>    = <D/T/DT>.isoformat()             # ISO string representation.
     <str>    = <D/T/DT>.strftime('<format>')    # Custom string representation.
     <int>    = <D/DT>.toordinal()               # Days since Christ, ignoring time and tz.
     <float>  = <DTn>.timestamp()                # Seconds since Epoch from DTn in local time.
     <float>  = <DTa>.timestamp()                # Seconds since Epoch from DTa.
    -
    -

    Format

    -
    >>> from datetime import datetime
    +
    + +

    Format

    >>> from datetime import datetime
     >>> dt = datetime.strptime('2015-05-14 23:39:00.00 +0200', '%Y-%m-%d %H:%M:%S.%f %z')
     >>> dt.strftime("%A, %dth of %B '%y, %I:%M%p %Z")
     "Thursday, 14th of May '15, 11:39PM UTC+02:00"
    -
    +
    +
    • For abbreviated weekday and month use '%a' and '%b'.
    • When parsing, '%z' also accepts '±HH:MM'.
    -

    Arithmetics

    -
    <D/DT>   = <D/DT> ±  <TD>
    +

    Arithmetics

    <D/DT>   = <D/DT> ±  <TD>
     <TD>     = <TD>   ±  <TD>
     <TD>     = <TD>   */ <real>
     <float>  = <TD>   /  <TD>
    -
    -

    #Arguments

    -

    Inside Function Call

    -
    <function>(<positional_args>)                  # f(0, 0)
    +
    + +

    #Arguments

    Inside Function Call

    <function>(<positional_args>)                  # f(0, 0)
     <function>(<keyword_args>)                     # f(x=0, y=0)
     <function>(<positional_args>, <keyword_args>)  # f(0, y=0)
    -
    -

    Inside Function Definition

    -
    def f(<nondefault_args>):                      # def f(x, y):
    +
    + + +

    Inside Function Definition

    def f(<nondefault_args>):                      # def f(x, y):
     def f(<default_args>):                         # def f(x=0, y=0):
     def f(<nondefault_args>, <default_args>):      # def f(x, y=0):
    -
    -

    #Splat Operator

    -

    Inside Function Call

    -

    Splat expands a collection into positional arguments, while splatty-splat expands a dictionary into keyword arguments.

    -
    args   = (1, 2)
    +
    + +

    #Splat Operator

    Inside Function Call

    Splat expands a collection into positional arguments, while splatty-splat expands a dictionary into keyword arguments.

    args   = (1, 2)
     kwargs = {'x': 3, 'y': 4, 'z': 5}
     func(*args, **kwargs)
    -
    -

    Is the same as:

    -
    func(1, 2, x=3, y=4, z=5)
    -
    -

    Inside Function Definition

    -

    Splat combines zero or more positional arguments into a tuple, while splatty-splat combines zero or more keyword arguments into a dictionary.

    -
    def add(*a):
    +
    + + + +

    Is the same as:

    func(1, 2, x=3, y=4, z=5)
    +
    + +

    Inside Function Definition

    Splat combines zero or more positional arguments into a tuple, while splatty-splat combines zero or more keyword arguments into a dictionary.

    def add(*a):
         return sum(a)
    -
    +
    + +
    >>> add(1, 2, 3)
     6
     
    -

    Legal argument combinations:

    -
    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)
    +

    Legal argument combinations:

    def f(x, y, z):                # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3) | f(1, 2, 3)
     def f(*, x, y, z):             # f(x=1, y=2, z=3)
     def f(x, *, y, z):             # f(x=1, y=2, z=3) | f(1, y=2, z=3)
     def f(x, y, *, z):             # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3)
    -
    +
    +
    def f(*args):                  # f(1, 2, 3)
     def f(x, *args):               # f(1, 2, 3)
     def f(*args, z):               # f(1, 2, z=3)
    @@ -731,54 +740,54 @@ func(*args, **kwargs)
     def f(*args, y, **kwargs):     # f(x=1, y=2, z=3) | f(1, y=2, z=3)
     def f(x, *args, z, **kwargs):  # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z=3)
     
    -

    Other Uses

    -
    <list>  = [*<collection> [, ...]]
    +

    Other Uses

    <list>  = [*<collection> [, ...]]
     <set>   = {*<collection> [, ...]}
     <tuple> = (*<collection>, [...])
     <dict>  = {**<dict> [, ...]}
    -
    +
    +
    head, *body, tail = <collection>
     
    -

    #Inline

    -

    Lambda

    -
    <function> = lambda: <return_value>
    +

    #Inline

    Lambda

    <function> = lambda: <return_value>
     <function> = lambda <argument_1>, <argument_2>: <return_value>
    -
    -

    Comprehension

    -
    <list> = [i+1 for i in range(10)]                   # [1, 2, ..., 10]
    +
    + + +

    Comprehension

    <list> = [i+1 for i in range(10)]                   # [1, 2, ..., 10]
     <set>  = {i for i in range(10) if i > 5}            # {6, 7, 8, 9}
     <iter> = (i+5 for i in range(10))                   # (5, 6, ..., 14)
     <dict> = {i: i*2 for i in range(10)}                # {0: 0, 1: 2, ..., 9: 18}
    -
    +
    +
    out = [i+j for i in range(10) for j in range(10)]
     
    -

    Is the same as:

    -
    out = []
    +

    Is the same as:

    out = []
     for i in range(10):
         for j in range(10):
             out.append(i+j)
    -
    -

    Map, Filter, Reduce

    -
    from functools import reduce
    +
    + +

    Map, Filter, Reduce

    from functools import reduce
     <iter> = map(lambda x: x + 1, range(10))            # (1, 2, ..., 10)
     <iter> = filter(lambda x: x > 5, range(10))         # (6, 7, 8, 9)
     <int>  = reduce(lambda out, x: out + x, range(10))  # 45
    -
    -

    Any, All

    -
    <bool> = any(<collection>)                          # False if empty.
    +
    + +

    Any, All

    <bool> = any(<collection>)                          # False if empty.
     <bool> = all(el[1] for el in <collection>)          # True if empty.
    -
    -

    If - Else

    -
    <expression_if_true> if <condition> else <expression_if_false>
    -
    +
    + +

    If - Else

    <expression_if_true> if <condition> else <expression_if_false>
    +
    +
    >>> [a if a else 'zero' for a in (0, 1, 0, 3)]
     ['zero', 1, 'zero', 3]
     
    -

    Namedtuple, Enum, Dataclass

    -
    from collections import namedtuple
    +

    Namedtuple, Enum, Dataclass

    from collections import namedtuple
     Point     = namedtuple('Point', 'x y')
     point     = Point(0, 0)
    -
    +
    +
    from enum import Enum
     Direction = Enum('Direction', 'n e s w')
     direction = Direction.n
    @@ -787,17 +796,17 @@ direction = Direction.n
     Creature  = make_dataclass('Creature', ['location', 'direction'])
     creature  = Creature(Point(0, 0), Direction.n)
     
    -

    #Closure

    -

    We have a closure in Python when:

    -
      +

      #Closure

      We have a closure in Python when:

      • A nested function references a value of its enclosing function and then
      • the enclosing function returns the nested function.
      • -
      -
      def get_multiplier(a):
      +
    def get_multiplier(a):
         def out(b):
             return a * b
         return out
    -
    + + + +
    >>> multiply_by_3 = get_multiplier(3)
     >>> multiply_by_3(10)
     30
    @@ -806,10 +815,10 @@ creature  = Creature(Point(0, '<function>.__closure__[0].cell_contents'.
     
    -

    Partial

    -
    from functools import partial
    +

    Partial

    from functools import partial
     <function> = partial(<function> [, <arg_1>, <arg_2>, ...])
    -
    +
    +
    >>> import operator as op
     >>> multiply_by_3 = partial(op.mul, 3)
     >>> multiply_by_3(10)
    @@ -819,29 +828,27 @@ creature  = Creature(Point(0, 'defaultdict(<function>)', 'iter(<function>, to_exclusive)' and dataclass's 'field(default_factory=<function>)'.
     
    -

    Nonlocal

    -

    If variable is being assigned to anywhere in the scope, it is regarded as a local variable, unless it is declared as a 'global' or a 'nonlocal'.

    -
    def get_counter():
    +

    Nonlocal

    If variable is being assigned to anywhere in the scope, it is regarded as a local variable, unless it is declared as a 'global' or a 'nonlocal'.

    def get_counter():
         i = 0
         def out():
             nonlocal i
             i += 1
             return i
         return out
    -
    +
    + +
    >>> counter = get_counter()
     >>> counter(), counter(), counter()
     (1, 2, 3)
     
    -

    #Decorator

    -

    A decorator takes a function, adds some functionality and returns it.

    -
    @decorator_name
    +

    #Decorator

    A decorator takes a function, adds some functionality and returns it.

    @decorator_name
     def function_that_gets_passed_to_decorator():
         ...
    -
    -

    Debugger Example

    -

    Decorator that prints function's name every time it gets called.

    -
    from functools import wraps
    +
    + + +

    Debugger Example

    Decorator that prints function's name every time it gets called.

    from functools import wraps
     
     def debug(func):
         @wraps(func)
    @@ -853,25 +860,25 @@ creature  = Creature(Point(0, @debug
     def add(x, y):
         return x + y
    -
    +
    + +
    • Wraps is a helper decorator that copies metadata of function add() to function out().
    • Without it 'add.__name__' would return 'out'.
    -

    LRU Cache

    -

    Decorator that caches function's return values. All function's arguments must be hashable.

    -
    from functools import lru_cache
    +

    LRU Cache

    Decorator that caches function's return values. All function's arguments must be hashable.

    from functools import lru_cache
     
     @lru_cache(maxsize=None)
     def fib(n):
         return n if n < 2 else fib(n-2) + fib(n-1)
    -
    +
    + +
    • Recursion depth is limited to 1000 by default. To increase it use 'sys.setrecursionlimit(<depth>)'.
    -

    Parametrized Decorator

    -

    A decorator that accepts arguments and returns a normal decorator that accepts a function.

    -
    from functools import wraps
    +

    Parametrized Decorator

    A decorator that accepts arguments and returns a normal decorator that accepts a function.

    from functools import wraps
     
     def debug(print_result=False):
         def decorator(func):
    @@ -886,9 +893,10 @@ creature  = Creature(Point(0, @debug(print_result=True)
     def add(x, y):
         return x + y
    -
    -

    #Class

    -
    class <name>:
    +
    + + +

    #Class

    class <name>:
         def __init__(self, a):
             self.a = a
         def __repr__(self):
    @@ -900,32 +908,32 @@ creature  = Creature(Point(0,     @classmethod
         def get_class_name(cls):
             return cls.__name__
    -
    +
    +
    • Return value of repr() should be unambiguous and of str() readable.
    • If only repr() is defined, it will be also used for str().
    -

    Str() use cases:

    -
    print(<el>)
    +

    Str() use cases:

    print(<el>)
     print(f'{<el>}')
     raise Exception(<el>)
     logging.debug(<el>)
     csv.writer(<file>).writerow([<el>])
    -
    -

    Repr() use cases:

    -
    print([<el>])
    +
    + +

    Repr() use cases:

    print([<el>])
     print(f'{<el>!r}')
     >>> <el>
     loguru.logger.exception()
     Z = dataclasses.make_dataclass('Z', ['a']); print(Z(<el>))
    -
    -

    Constructor Overloading

    -
    class <name>:
    +
    + +

    Constructor Overloading

    class <name>:
         def __init__(self, a=None):
             self.a = a
    -
    -

    Inheritance

    -
    class Person:
    +
    + +

    Inheritance

    class Person:
         def __init__(self, name, age):
             self.name = name
             self.age  = age
    @@ -934,18 +942,18 @@ Z = dataclasses.make_dataclass('Z', [def __init__(self, name, age, staff_num):
             super().__init__(name, age)
             self.staff_num = staff_num
    -
    -

    Multiple Inheritance

    -
    class A: pass
    +
    + +

    Multiple Inheritance

    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:

    >>> C.mro()
     [<class 'C'>, <class 'A'>, <class 'B'>, <class 'object'>]
     
    -

    Property

    -
    class MyClass:
    +

    Property

    class MyClass:
         @property
         def a(self):
             return self._a
    @@ -953,62 +961,61 @@ Z = dataclasses.make_dataclass('Z', [    @a.setter
         def a(self, value):
             self._a = value
    -
    +
    +
    >>> el = MyClass()
     >>> el.a = 123
     >>> el.a
     123
     
    -

    Dataclass

    -

    Decorator that automatically generates init(), repr() and eq() special methods.

    -
    from dataclasses import dataclass, field
    +

    Dataclass

    Decorator that automatically generates init(), repr() and eq() special methods.

    from dataclasses import dataclass, field
     
     @dataclass(order=False, frozen=False)
     class <class_name>:
         <attr_name_1>: <type>
         <attr_name_2>: <type> = <default_value>
         <attr_name_3>: list/dict/set = field(default_factory=list/dict/set)
    -
    +
    + +
    • An object can be made sortable with 'order=True' or immutable with 'frozen=True'.
    • Function field() is needed because '<attr_name>: list = []' would make a list that is shared among all instances.
    • Default_factory can be any callable.
    -

    Slots

    -

    Mechanism that restricts objects to attributes listed in 'slots' and significantly reduces their memory footprint.

    -
    class MyClassWithSlots:
    +

    Slots

    Mechanism that restricts objects to attributes listed in 'slots' and significantly reduces their memory footprint.

    class MyClassWithSlots:
         __slots__ = ['a']
         def __init__(self):
             self.a = 1
    -
    -

    Copy

    -
    from copy import copy, deepcopy
    +
    + + +

    Copy

    from copy import copy, deepcopy
     <object> = copy(<object>)
     <object> = deepcopy(<object>)
    -
    -

    #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

    -
      +
    + +

    #Duck Types

    A duck type is an implicit type that prescribes a set of special methods. Any object that has those methods defined is considered a member of that duck type.

    Comparable

    • If eq() method is not overridden, it returns 'id(self) == id(other)', which is the same as 'self is other'.
    • That means all objects compare not equal by default.
    • Only left side object has eq() method called, unless it returns 'NotImplemented', in which case the right object is consulted.
    • -
    -
    class MyComparable:
    +
    class MyComparable:
         def __init__(self, a):
             self.a = a
         def __eq__(self, other):
             if isinstance(other, type(self)):
                 return self.a == other.a
             return NotImplemented
    -
    -

    Hashable

    -
      +
    + + + + +

    Hashable

    • 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().
    • -
    -
    class MyHashable:
    +
    class MyHashable:
         def __init__(self, a):
             self._a = copy.deepcopy(a)
         @property
    @@ -1020,12 +1027,12 @@ Z = dataclasses.make_dataclass('Z', [return NotImplemented
         def __hash__(self):
             return hash(self.a)
    -
    -

    Sortable

    -
      +
    + + +

    Sortable

    • With 'total_ordering' decorator you only need to provide eq() and one of lt(), gt(), le() or ge() special methods.
    • -
    -
    from functools import total_ordering
    +
    from functools import total_ordering
     
     @total_ordering
     class MySortable:
    @@ -1039,13 +1046,13 @@ Z = dataclasses.make_dataclass('Z', [if isinstance(other, type(self)):
                 return self.a < other.a
             return NotImplemented
    -
    -

    Iterator

    -
      +
    + + +

    Iterator

    • Next() should return next item or raise 'StopIteration'.
    • Iter() should return 'self'.
    • -
    -
    class Counter:
    +
    class Counter:
         def __init__(self):
             self.i = 0
         def __next__(self):
    @@ -1053,25 +1060,26 @@ Z = dataclasses.make_dataclass('Z', [return self.i
         def __iter__(self):
             return self
    -
    +
    + +
    >>> counter = Counter()
     >>> next(counter), next(counter), next(counter)
     (1, 2, 3)
     
    -

    Callable

    -
    class Counter:
    +

    Callable

    class Counter:
         def __init__(self):
             self.i = 0
         def __call__(self):
             self.i += 1
             return self.i
    -
    +
    +
    >>> counter = Counter()
     >>> counter(), counter(), counter()
     (1, 2, 3)
     
    -

    Context Manager

    -
    class MyOpen():
    +

    Context Manager

    class MyOpen():
         def __init__(self, filename):
             self.filename = filename
         def __enter__(self):
    @@ -1079,46 +1087,45 @@ Z = dataclasses.make_dataclass('Z', [return self.file
         def __exit__(self, *args):
             self.file.close()
    -
    +
    +
    >>> with open('test.txt', 'w') as file:
     ...     file.write('Hello World!')
     >>> with MyOpen('test.txt') as file:
     ...     print(file.read())
     Hello World!
     
    -

    List of existing context managers:

    -
    with open('<path>', ...) as file: ...
    +

    List of existing context managers:

    with open('<path>', ...) as file: ...
     with wave.open('<path>', ...) as wave_file: ...
     with memoryview(<bytes/bytearray/array>) as view: ...
     db = sqlite3.connect('<path>'); with db: db.execute('<insert_query>')
     lock = threading.RLock(); with lock: ...
    -
    -

    #Iterable Duck Types

    -

    Iterable

    -
      +
    + +

    #Iterable Duck Types

    Iterable

    • Only required method is iter(). It should return an iterator of object's items.
    • Contains() automatically works on any object that has iter() defined.
    • -
    -
    class MyIterable:
    +
    class MyIterable:
         def __init__(self, a):
             self.a = a
         def __iter__(self):
             for el in self.a:
                 yield el
    -
    +
    + + +
    >>> a = MyIterable([1, 2, 3])
     >>> iter(a)
     <generator object MyIterable.__iter__ at 0x1026c18b8>
     >>> 1 in a
     True
     
    -

    Collection

    -
      +

      Collection

      • Only required methods are iter() and len().
      • This cheatsheet actually means '<iterable>' when it uses '<collection>'.
      • I chose not to use the name 'iterable' because it sounds scarier and more vague than 'collection'.
      • -
      -
      class MyCollection:
      +
    class MyCollection:
         def __init__(self, a):
             self.a = a
         def __iter__(self):
    @@ -1127,15 +1134,15 @@ lock = threading.RLock(); with lock: ...
             return el in self.a
         def __len__(self):
             return len(self.a)
    -
    -

    Sequence

    -
      +
    + + +

    Sequence

    • Only required methods are len() and getitem().
    • Getitem() should return an item at index or raise 'IndexError'.
    • Iter() and contains() automatically work on any object that has getitem() defined.
    • Reversed() automatically works on any object that has getitem() and len() defined.
    • -
    -
    class MySequence:
    +
    class MySequence:
         def __init__(self, a):
             self.a = a
         def __iter__(self):
    @@ -1148,23 +1155,24 @@ lock = threading.RLock(); with lock: ...
             return self.a[i]
         def __reversed__(self):
             return reversed(self.a)
    -
    -

    Collections.abc.Sequence

    -
      +
    + + +

    Collections.abc.Sequence

    • It's a richer interface than the basic sequence.
    • Extending it generates iter(), contains(), reversed(), index(), and count().
    • Unlike 'abc.Iterable' and 'abc.Collection', it is not a duck type. That is why 'issubclass(MySequence, collections.abc.Sequence)' would return 'False' even if 'MySequence' had all the methods defined.
    • -
    -
    class MyAbcSequence(collections.abc.Sequence):
    +
    class MyAbcSequence(collections.abc.Sequence):
         def __init__(self, a):
             self.a = a
         def __len__(self):
             return len(self.a)
         def __getitem__(self, i):
             return self.a[i]
    -
    -

    Table of required and available special methods:

    -
    +------------+----------+------------+----------+--------------+
    +
    + + +

    Table of required and available special methods:

    +------------+----------+------------+----------+--------------+
     |            | Iterable | Collection | Sequence | abc.Sequence |
     +------------+----------+------------+----------+--------------+
     | iter()     |   REQ    |    REQ     |   yes    |     yes      |
    @@ -1175,12 +1183,12 @@ lock = threading.RLock(); with lock: ...
     | index()    |          |            |          |     yes      |
     | count()    |          |            |          |     yes      |
     +------------+----------+------------+----------+--------------+
    -
    +
    +
    • Other useful ABCs that automatically generate missing methods are: MutableSequence, Set, MutableSet, Mapping and MutableMapping.
    -

    #Enum

    -
    from enum import Enum, auto
    +

    #Enum

    from enum import Enum, auto
     
     class <enum_name>(Enum):
         <member_name_1> = <value_1>
    @@ -1190,7 +1198,8 @@ lock = threading.RLock(); with lock: ...
         @classmethod
         def get_member_names(cls):
             return [a.name for a in cls.__members__.values()]
    -
    +
    +
    <str> = input(prompt=None)
    +
    + + +

    Prints lines until EOF:

    while True:
         try:
             print(input())
         except EOFError:
             break
    -
    -

    #Command Line Arguments

    -
    import sys
    +
    + +

    #Command Line Arguments

    import sys
     script_name = sys.argv[0]
     arguments   = sys.argv[1:]
    -
    -

    Argparse

    -
    from argparse import ArgumentParser, FileType
    +
    + +

    Argparse

    from argparse import ArgumentParser, FileType
     p = ArgumentParser(description=<str>)
     p.add_argument('-<short_name>', '--<name>', action='store_true')  # Flag
     p.add_argument('-<short_name>', '--<name>', type=<type>)          # Option
    @@ -1335,22 +1343,22 @@ p.add_argument('<name>', type=<type>
     p.add_argument('<name>', type=<type>, nargs='+')                  # Arguments
     args  = p.parse_args()
     value = args.<name>
    -
    +
    +
    • Use 'help=<str>' for argument description.
    • Use 'type=FileType(<mode>)' for files.
    -

    #Open

    -

    Opens a file and returns a corresponding file object.

    -
    <file> = open('<path>', mode='r', encoding=None, newline=None)
    -
    +

    #Open

    Opens a file and returns a corresponding file object.

    <file> = open('<path>', mode='r', encoding=None, newline=None)
    +
    + +
    • 'encoding=None' means default encoding is used, which is platform dependent. Best practice is to use 'encoding="utf-8"' whenever possible.
    • '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 lines are still broken by readline() on either '\n', '\r' or '\r\n'.
    -

    Modes

    -
      +

      Modes

      • 'r' - Read (default).
      • 'w' - Write (truncate).
      • 'x' - Write or fail if the file already exists.
      • @@ -1360,20 +1368,21 @@ value = args.<name>
      • 'a+' - Read and write from the end.
      • 't' - Text mode (default).
      • 'b' - Binary mode.
      • -
      -

      Exceptions

      -
        +

      Exceptions

      • 'FileNotFoundError' can be risen when reading with 'r' or 'r+'.
      • 'FileExistsError' can be risen when writing with 'x'.
      • 'IsADirectoryError' and 'PermissionError' can be risen by any.
      • 'OSError' is the parent class of all listed exceptions.
      • -
      -

      File

      -
      <file>.seek(0)                      # Moves to the start of the file.
      +

    File

    <file>.seek(0)                      # Moves to the start of the file.
     <file>.seek(offset)                 # Moves 'offset' chars/bytes from the start.
     <file>.seek(0, 2)                   # Moves to the end of the file.
     <bin_file>.seek(±offset, <anchor>)  # Anchor: 0 start, 1 current pos., 2 end.
    -
    +
    + + + + +
    <str/bytes> = <file>.read(size=-1)  # Reads 'size' chars/bytes or until EOF.
     <str/bytes> = <file>.readline()     # Returns a line or empty string on EOF.
     <list>      = <file>.readlines()    # Returns a list of lines or empty list.
    @@ -1386,20 +1395,20 @@ value = args.<name>
     
    • Methods do not add or strip trailing newlines, even writelines().
    -

    Read Text from File

    -
    def read_file(filename):
    +

    Read Text from File

    def read_file(filename):
         with open(filename, encoding='utf-8') as file:
             return file.readlines()
    -
    -

    Write Text to File

    -
    def write_to_file(filename, text):
    +
    + +

    Write Text to File

    def write_to_file(filename, text):
         with open(filename, 'w', encoding='utf-8') as file:
             file.write(text)
    -
    -

    #Path

    -
    from os import path, listdir
    +
    + +

    #Path

    from os import path, listdir
     from glob import glob
    -
    +
    +
    <bool> = path.exists('<path>')
     <bool> = path.isfile('<path>')
     <bool> = path.isdir('<path>')
    @@ -1407,9 +1416,9 @@ value = args.<name>
     
    <list> = listdir('<path>')         # List of filenames located at 'path'.
     <list> = glob('<pattern>')         # Filenames matching the wildcard pattern.
     
    -

    Pathlib

    -
    from pathlib import Path
    -
    +

    Pathlib

    from pathlib import Path
    +
    +
    cwd    = Path()
     <Path> = Path('<path>' [, '<path>', <Path>, ...])
     <Path> = <Path> / '<dir>' / '<file>'
    @@ -1430,16 +1439,16 @@ value = args.<name>
     <str>  = <Path>.suffix             # Final component's extension.
     <Path> = <Path>.parent             # Path without final component.
     
    -

    #Command Execution

    -

    Files and Directories

    -
      +

      #Command Execution

      Files and Directories

      • Paths can be either strings or Path objects.
      • All exceptions are either 'OSError' or its subclasses.
      • -
      -
      import os
      +
    import os
     <str> = os.getcwd()                # Returns the current working directory.
     os.chdir(<path>)                   # Changes the current working directory.
    -
    +
    + + +
    os.remove(<path>)                  # Deletes the file.
     os.rmdir(<path>)                   # Deletes empty directory.
     shutil.rmtree(<path>)              # Deletes the entire directory tree.
    @@ -1450,32 +1459,32 @@ os.replace(from, to)               # Same, but overwr
     
    os.mkdir(<path>, mode=0o777)       # Creates a directory.
     <iter> = os.scandir(path='.')      # Returns os.DirEntry objects located at path.
     
    -

    DirEntry:

    -
    <str>  = <DirEntry>.name           # Final component of the path.
    +

    DirEntry:

    <str>  = <DirEntry>.name           # Final component of the path.
     <str>  = <DirEntry>.path           # Path with final component.
     <Path> = Path(<DirEntry>)          # Path object.
    -
    +
    +
    <bool> = <DirEntry>.is_file()
     <bool> = <DirEntry>.is_dir()
     <bool> = <DirEntry>.is_symlink()
     
    -

    Shell Commands

    -
    import os
    +

    Shell Commands

    import os
     <str> = os.popen('<shell_command>').read()
    -
    -

    Using subprocess:

    -
    >>> import subprocess, shlex
    +
    + +

    Using subprocess:

    >>> import subprocess, shlex
     >>> a = subprocess.run(shlex.split('ls -a'), stdout=subprocess.PIPE)
     >>> a.stdout
     b'.\n..\nfile1.txt\nfile2.txt\n'
     >>> a.returncode
     0
    -
    -

    #CSV

    -
    import csv
    +
    + +

    #CSV

    import csv
     <reader> = csv.reader(<file>, dialect='excel', delimiter=',')
     <list>   = next(<reader>)        # Returns a row as list of strings.
    -
    +
    +
    <writer> = csv.writer(<file>, dialect='excel', delimiter=',')
     <writer>.writerow(<collection>)  # Encodes objects using `str(<el>)`.
     <writer>.writerows(<coll_of_coll>)
    @@ -1483,8 +1492,7 @@ os.replace(from, to)               # Same, but overwr
     
    • File must be opened with 'newline=""' argument, or newlines embedded inside quoted fields will not be interpreted correctly!
    -

    Parameters

    -
      +

      Parameters

      • 'dialect' - Master parameter that sets the default values.
      • 'delimiter' - A one-character string used to separate fields.
      • 'quotechar' - Character for quoting fields that contain special characters.
      • @@ -1493,9 +1501,7 @@ os.replace(from, to) # Same, but overwr
      • 'lineterminator' - How does writer terminate lines.
      • 'quoting' - Controls the amount of quoting: 0 - as necessary, 1 - all.
      • 'escapechar' - Character for escaping quotechar if doublequote is false.
      • -
      -

      Dialects

      -
      +------------------+-----------+-----------+--------------+
      +

    Dialects

    +------------------+-----------+-----------+--------------+
     |                  |   excel   | excel_tab | unix_dialect |
     +------------------+-----------+-----------+--------------+
     | delimiter        |      ','  |     '\t'  |       ','    |
    @@ -1506,172 +1512,175 @@ os.replace(from, to)               # Same, but overwr
     | quoting          |        0  |        0  |         1    |
     | escapechar       |     None  |     None  |      None    |
     +------------------+-----------+-----------+--------------+
    -
    -

    Read Rows from CSV File

    -
    def read_csv_file(filename):
    +
    + + + +

    Read Rows from CSV File

    def read_csv_file(filename):
         with open(filename, encoding='utf-8', newline='') as file:
             return csv.reader(file)
    -
    -

    Write Rows to CSV File

    -
    def write_to_csv_file(filename, rows):
    +
    + +

    Write Rows to CSV File

    def write_to_csv_file(filename, rows):
         with open(filename, 'w', encoding='utf-8', newline='') as file:
             writer = csv.writer(file)
             writer.writerows(rows)
    -
    -

    #JSON

    -
    import json
    +
    + +

    #JSON

    import json
     <str>    = json.dumps(<object>, ensure_ascii=True, indent=None)
     <object> = json.loads(<str>)
    -
    -

    Read Object from JSON File

    -
    def read_json_file(filename):
    +
    + +

    Read Object from JSON File

    def read_json_file(filename):
         with open(filename, encoding='utf-8') as file:
             return json.load(file)
    -
    -

    Write Object to JSON File

    -
    def write_to_json_file(filename, an_object):
    +
    + +

    Write Object to JSON File

    def write_to_json_file(filename, an_object):
         with open(filename, 'w', encoding='utf-8') as file:
             json.dump(an_object, file, ensure_ascii=False, indent=2)
    -
    -

    #Pickle

    -
    import pickle
    +
    + +

    #Pickle

    import pickle
     <bytes>  = pickle.dumps(<object>)
     <object> = pickle.loads(<bytes>)
    -
    -

    Read Object from File

    -
    def read_pickle_file(filename):
    +
    + +

    Read Object from File

    def read_pickle_file(filename):
         with open(filename, 'rb') as file:
             return pickle.load(file)
    -
    -

    Write Object to File

    -
    def write_to_pickle_file(filename, an_object):
    +
    + +

    Write Object to File

    def write_to_pickle_file(filename, an_object):
         with open(filename, 'wb') as file:
             pickle.dump(an_object, file)
    -
    -

    #SQLite

    -

    Server-less database engine that stores each database into separate file.

    -
    import sqlite3
    +
    + +

    #SQLite

    Server-less database engine that stores each database into separate file.

    import sqlite3
     db = sqlite3.connect('<path>')                # Also ':memory:'.
     ...
     db.close()
    -
    +
    + +
    • New database will be created if path doesn't exist.
    -

    Read

    -
    cursor = db.execute('<query>')
    +

    Read

    cursor = db.execute('<query>')
     if cursor:
         <tuple> = cursor.fetchone()               # First row.
         <list>  = cursor.fetchall()               # Remaining rows.
    -
    +
    +
    • Returned values can be of type str, int, float, bytes or None.
    -

    Write

    -
    db.execute('<query>')
    +

    Write

    db.execute('<query>')
     db.commit()
    -
    -

    Placeholders

    -
    db.execute('<query>', <list/tuple>)           # Replaces '?'s in query with values.
    +
    + +

    Placeholders

    db.execute('<query>', <list/tuple>)           # Replaces '?'s in query with values.
     db.execute('<query>', <dict/namedtuple>)      # Replaces ':<key>'s with values.
     db.executemany('<query>', <coll_of_above>)    # Runs execute() many times.
    -
    +
    +
    • Passed values can be of type str, int, float, bytes, None, bool, datetime.date or datetime.datetme.
    -

    MySQL

    -

    Has a very similar interface, with differences listed below.

    -
    # $ pip3 install mysql-connector
    +

    MySQL

    Has a very similar interface, with differences listed below.

    # $ pip3 install mysql-connector
     from mysql import connector
     db = connector.connect(host=<str>, user=<str>, password=<str>, database=<str>)
     cursor = db.cursor()
     cursor.execute('<query>')                     # Connector doesn't have execute method.
     cursor.execute('<query>', <list/tuple>)       # Replaces '%s's in query with values.
     cursor.execute('<query>', <dict/namedtuple>)  # Replaces '%(<key>)s's with values.
    -
    -

    #Bytes

    -

    Bytes object is an immutable sequence of single bytes. Mutable version is called 'bytearray'.

    -
    <bytes> = b'<str>'                       # Only accepts ASCII characters and \x00 - \xff.
    +
    + + +

    #Bytes

    Bytes object is an immutable sequence of single bytes. Mutable version is called 'bytearray'.

    <bytes> = b'<str>'                       # Only accepts ASCII characters and \x00 - \xff.
     <int>   = <bytes>[<index>]               # Returns int 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 object as separator.
    -
    -

    Encode

    -
    <bytes> = <str>.encode('utf-8')          # Or: bytes(<str>, 'utf-8')
    +
    + + +

    Encode

    <bytes> = <str>.encode('utf-8')          # Or: bytes(<str>, 'utf-8')
     <bytes> = bytes(<coll_of_ints>)          # Ints must be in range from 0 to 255.
     <bytes> = <int>.to_bytes(<length>, byteorder='big|little', signed=False)
     <bytes> = bytes.fromhex('<hex>')
    -
    -

    Decode

    -
    <str>   = <bytes>.decode('utf-8')        # Or: str(<bytes>, 'utf-8')
    +
    + +

    Decode

    <str>   = <bytes>.decode('utf-8')        # Or: str(<bytes>, 'utf-8')
     <list>  = list(<bytes>)                  # Returns ints in range from 0 to 255.
     <int>   = int.from_bytes(<bytes>, byteorder='big|little', signed=False)
     '<hex>' = <bytes>.hex()
    -
    -

    Read Bytes from File

    -
    def read_bytes(filename):
    +
    + +

    Read Bytes from File

    def read_bytes(filename):
         with open(filename, 'rb') as file:
             return file.read()
    -
    -

    Write Bytes to File

    -
    def write_bytes(filename, bytes_obj):
    +
    + +

    Write Bytes to File

    def write_bytes(filename, bytes_obj):
         with open(filename, 'wb') as file:
             file.write(bytes_obj)
    -
    -

    #Struct

    -
      +
    + +

    #Struct

    • Module that performs conversions between a sequence of numbers and a C struct, represented as a Python bytes object.
    • Machine’s native type sizes and byte order are used by default.
    • -
    -
    from struct import pack, unpack, iter_unpack, calcsize
    +
    from struct import pack, unpack, iter_unpack, calcsize
     <bytes>  = pack('<format>', <num_1> [, <num_2>, ...])
     <tuple>  = unpack('<format>', <bytes>)
     <tuples> = iter_unpack('<format>', <bytes>)
    -
    -

    Example

    -
    >>> pack('>hhl', 1, 2, 3)
    +
    + + +

    Example

    >>> pack('>hhl', 1, 2, 3)
     b'\x00\x01\x00\x02\x00\x00\x00\x03'
     >>> unpack('>hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
     (1, 2, 3)
     >>> calcsize('>hhl')
     8
    -
    -

    Format

    -

    For standard sizes start format string with:

    -
      +
    + +

    Format

    For standard sizes start format string with:

    • '=' - native byte order
    • '<' - little-endian
    • '>' - big-endian
    • -
    -

    Integer types. Use capital letter for unsigned type. Standard sizes are in brackets:

    -
      +

    Integer types. Use capital letter for unsigned type. Standard sizes are in brackets:

    • 'x' - pad byte
    • 'b' - char (1)
    • 'h' - short (2)
    • 'i' - int (4)
    • 'l' - long (4)
    • 'q' - long long (8)
    • -
    -

    Floating point types:

    -
      +

    Floating point types:

    • 'f' - float (4)
    • 'd' - double (8)
    • -
    -

    #Array

    -

    List that can only hold numbers of predefined type. Available types and their sizes in bytes are listed above.

    -
    from array import array
    +
    + + + + + + +

    #Array

    List that can only hold numbers of predefined type. Available types and their sizes in bytes are listed above.

    from array import array
     <array> = array('<typecode>' [, <collection>])
    -
    -

    #Memory View

    -

    Used for accessing the internal data of an object that supports the buffer protocol.

    -
    <memoryview> = memoryview(<bytes> / <bytearray> / <array>)
    +
    + + +

    #Memory View

    Used for accessing the internal data of an object that supports the buffer protocol.

    <memoryview> = memoryview(<bytes> / <bytearray> / <array>)
     <memoryview>.release()
    -
    -

    #Deque

    -

    A thread-safe list with efficient appends and pops from either side. Pronounced "deck".

    -
    from collections import deque
    +
    + + +

    #Deque

    A thread-safe list with efficient appends and pops from either side. Pronounced "deck".

    from collections import deque
     <deque> = deque(<collection>, maxlen=None)
    -
    +
    + +
    <deque>.appendleft(<el>)
     <el> = <deque>.popleft()
     <deque>.extendleft(<collection>)            # Collection gets reversed.
    @@ -1685,83 +1694,83 @@ cursor.execute('<query>', <dict/namedt
     >>> a.insert(1, 6)
     IndexError: deque already at its maximum size
     
    -

    #Threading

    -
    from threading import Thread, RLock
    -
    -

    Thread

    -
    thread = Thread(target=<function>, args=(<first_arg>, ))
    +

    #Threading

    from threading import Thread, RLock
    +
    + +

    Thread

    thread = Thread(target=<function>, args=(<first_arg>, ))
     thread.start()
     ...
     thread.join()
    -
    -

    Lock

    -
    lock = RLock()
    +
    + +

    Lock

    lock = RLock()
     lock.acquire()
     ...
     lock.release()
    -
    -

    Or:

    -
    lock = RLock()
    +
    + +

    Or:

    lock = RLock()
     with lock:
         ...
    -
    -

    #Introspection

    -

    Inspecting code at runtime.

    -

    Variables

    -
    <list> = dir()      # Names of variables in current scope.
    +
    + +

    #Introspection

    Inspecting code at runtime.

    Variables

    <list> = dir()      # Names of variables in current scope.
     <dict> = locals()   # Dict of local variables. Also vars().
     <dict> = globals()  # Dict of global variables.
    -
    -

    Attributes

    -
    <dict> = vars(<object>)
    +
    + + + +

    Attributes

    <dict> = vars(<object>)
     <bool> = hasattr(<object>, '<attr_name>')
     value  = getattr(<object>, '<attr_name>')
     setattr(<object>, '<attr_name>', value)
    -
    -

    Parameters

    -
    from inspect import signature
    +
    + +

    Parameters

    from inspect import signature
     <sig>        = signature(<function>)
     no_of_params = len(<sig>.parameters)
     param_names  = list(<sig>.parameters.keys())
    -
    -

    #Metaprograming

    -

    Code that generates code.

    -

    Type

    -

    Type is the root class. If only passed an object it returns its type (class). Otherwise it creates a new class.

    -
    <class> = type(<class_name>, <parents_tuple>, <attributes_dict>)
    -
    +
    + +

    #Metaprograming

    Code that generates code.

    Type

    Type is the root class. If only passed an object it returns its type (class). Otherwise it creates a new class.

    <class> = type(<class_name>, <parents_tuple>, <attributes_dict>)
    +
    + + + +
    >>> Z = type('Z', (), {'a': 'abcde', 'b': 12345})
     >>> z = Z()
     
    -

    Meta Class

    -

    Class that creates class.

    -
    def my_meta_class(name, parents, attrs):
    +

    Meta Class

    Class that creates class.

    def my_meta_class(name, parents, attrs):
         attrs['a'] = 'abcde'
         return type(name, parents, attrs)
    -
    -

    Or:

    -
    class MyMetaClass(type):
    +
    + + +

    Or:

    class MyMetaClass(type):
         def __new__(cls, name, parents, attrs):
             attrs['a'] = 'abcde'
             return type.__new__(cls, name, parents, attrs)
    -
    +
    +
    • New() is a class method that gets called before init(). If it returns an instance of its class, then that instance gets passed to init() as a 'self' argument.
    • It receives the same arguments as init(), except for the first one that specifies the desired class of returned instance ('MyMetaClass' in our case).
    • New() can also be called directly, usually from a new() method of a child class (def __new__(cls): return super().__new__(cls)), in which case init() is not called.
    -

    Metaclass Attribute

    -

    Right before a class is created it checks if it has metaclass defined. If not, it recursively checks if any of his parents has it defined and eventually comes to type().

    -
    class MyClass(metaclass=MyMetaClass):
    +

    Metaclass Attribute

    Right before a class is created it checks if it has metaclass defined. If not, it recursively checks if any of his parents has it defined and eventually comes to type().

    class MyClass(metaclass=MyMetaClass):
         b = 12345
    -
    +
    + +
    >>> MyClass.a, MyClass.b
     ('abcde', 12345)
     
    -

    Type Diagram

    -
    type(MyClass)     == MyMetaClass  # MyClass is an instance of MyMetaClass.
    +

    Type Diagram

    type(MyClass)     == MyMetaClass  # MyClass is an instance of MyMetaClass.
     type(MyMetaClass) == type         # MyMetaClass is an instance of type.
    -
    +
    +
    +---------+-------------+
     | Classes | Metaclasses |
     +---------+-------------|
    @@ -1772,10 +1781,10 @@ type(MyMetaClass) == type         # MyMetaClass is an
     |   str -------+        |
     +---------+-------------+
     
    -

    Inheritance Diagram

    -
    MyClass.__base__     == object    # MyClass is a subclass of object.
    +

    Inheritance Diagram

    MyClass.__base__     == object    # MyClass is a subclass of object.
     MyMetaClass.__base__ == type      # MyMetaClass is a subclass of type.
    -
    +
    +
    +---------+-------------+
     | Classes | Metaclasses |
     +---------+-------------|
    @@ -1786,12 +1795,12 @@ MyMetaClass.__base__ == type      # MyMetaClass is a
     |   str   |             |
     +---------+-------------+
     
    -

    #Operator

    -
    from operator import add, sub, mul, truediv, floordiv, mod, pow, neg, abs
    +

    #Operator

    from operator import add, sub, mul, truediv, floordiv, mod, pow, neg, abs
     from operator import eq, ne, lt, le, gt, ge
     from operator import and_, or_, not_
     from operator import itemgetter, attrgetter, methodcaller
    -
    +
    +
    import operator as op
     sorted_by_second = sorted(<collection>, key=op.itemgetter(1))
     sorted_by_both   = sorted(<collection>, key=op.itemgetter(1, 0))
    @@ -1799,36 +1808,35 @@ product_of_elems = functools.reduce(op.mul, <collection>)
     LogicOp          = enum.Enum('LogicOp', {'AND': op.and_, 'OR' : op.or_})
     last_el          = op.methodcaller('pop')(<list>)
     
    -

    #Eval

    -
    >>> from ast import literal_eval
    +

    #Eval

    >>> from ast import literal_eval
     >>> literal_eval('1 + 2')
     3
     >>> literal_eval('[1, 2, 3]')
     [1, 2, 3]
     >>> literal_eval('abs(1)')
     ValueError: malformed node or string
    -
    -

    #Coroutine

    -
      +
    + +

    #Coroutine

    • Similar to generator, but generator pulls data through the pipe with iteration, while coroutine pushes data into the pipeline with send().
    • Coroutines provide more powerful data routing possibilities than iterators.
    • If you build a collection of simple data processing components, you can glue them together into complex arrangements of pipes, branches, merging, etc.
    • -
    -

    Helper Decorator

    -
      +

    Helper Decorator

    • All coroutines must be "primed" by first calling next().
    • Remembering to call next() is easy to forget.
    • Solved by wrapping coroutines with a decorator:
    • -
    -
    def coroutine(func):
    +
    def coroutine(func):
         def out(*args, **kwargs):
             cr = func(*args, **kwargs)
             next(cr)
             return cr
         return out
    -
    -

    Pipeline Example

    -
    def reader(target):
    +
    + + + + +

    Pipeline Example

    def reader(target):
         for i in range(10):
             target.send(i)
         target.close()
    @@ -1846,29 +1854,28 @@ ValueError: malformed node or string
             print(value)
     
     reader(adder(printer()))  # 100, 101, ..., 109
    -
    +
    +



    -

    Libraries

    -

    #Progress Bar

    -
    # $ pip3 install tqdm
    +

    Libraries

    +

    #Progress Bar

    # $ pip3 install tqdm
     from tqdm import tqdm
     from time import sleep
     for i in tqdm([1, 2, 3]):
         sleep(0.2)
     for i in tqdm(range(100)):
         sleep(0.02)
    -
    -

    #Plot

    -
    # $ pip3 install matplotlib
    +
    + +

    #Plot

    # $ pip3 install matplotlib
     from matplotlib import pyplot
     pyplot.plot(<data_1> [, <data_2>, ...])  # Or: hist(<data>).
     pyplot.savefig(<filename>)
     pyplot.show()
     pyplot.clf()                             # Clears figure.
    -
    -

    #Table

    -

    Prints a CSV file as an ASCII table:

    -
    # $ pip3 install tabulate
    +
    + +

    #Table

    Prints a CSV file as an ASCII table:

    # $ pip3 install tabulate
     from tabulate import tabulate
     import csv
     with open(<filename>, encoding='utf-8', newline='') as file:
    @@ -1876,9 +1883,10 @@ pyplot.clf()                             # Clears fig
         headers = [header.title() for header in next(lines)]
         table   = tabulate(lines, headers)
         print(table)
    -
    -

    #Curses

    -
    from curses import wrapper, ascii
    +
    + + +

    #Curses

    from curses import wrapper, ascii
     
     def main():
         wrapper(draw)
    @@ -1897,11 +1905,12 @@ pyplot.clf()                             # Clears fig
     
     if __name__ == '__main__':
         main()
    -
    -

    #Logging

    -
    # $ pip3 install loguru
    +
    + +

    #Logging

    # $ pip3 install loguru
     from loguru import logger
    -
    +
    +
    logger.add('debug_{time}.log', colorize=True)  # Connects a log file.
     logger.add('error_{time}.log', level='ERROR')  # Another file for errors or higher.
     logger.<level>('A logging message.')
    @@ -1909,35 +1918,33 @@ logger.<level>('A logging message.')
     
    • Levels: 'debug', 'info', 'success', 'warning', 'error', 'critical'.
    -

    Exceptions

    -

    Error description, stack trace and values of variables are appended automatically.

    -
    try:
    +

    Exceptions

    Error description, stack trace and values of variables are appended automatically.

    try:
         ...
     except <exception>:
         logger.exception('An error happened.')
    -
    -

    Rotation

    -

    Argument that sets a condition when a new log file is created.

    -
    rotation=<int>|<datetime.timedelta>|<datetime.time>|<str>
    -
    +
    + + +

    Rotation

    Argument that sets a condition when a new log file is created.

    rotation=<int>|<datetime.timedelta>|<datetime.time>|<str>
    +
    + +
    • '<int>' - Max file size in bytes.
    • '<timedelta>' - Max age of a file.
    • '<time>' - Time of day.
    • '<str>' - Any of above as a string: '100 MB', '1 month', 'monday at 12:00', …
    -

    Retention

    -

    Sets a condition which old log files are deleted.

    -
    retention=<int>|<datetime.timedelta>|<str>
    -
    +

    Retention

    Sets a condition which old log files are deleted.

    retention=<int>|<datetime.timedelta>|<str>
    +
    + +
    • '<int>' - Max number of files.
    • '<timedelta>' - Max age of a file.
    • '<str>' - Max age as a string: '1 week, 3 days', '2 months', …
    -

    #Scraping

    -

    Scrapes and prints Python's URL and version number from Wikipedia:

    -
    # $ pip3 install requests beautifulsoup4
    +

    #Scraping

    Scrapes and prints Python's URL and version number from Wikipedia:

    # $ pip3 install requests beautifulsoup4
     import requests
     from bs4 import BeautifulSoup
     url   = 'https://en.wikipedia.org/wiki/Python_(programming_language)'
    @@ -1948,83 +1955,83 @@ rows  = table.find_all('tr')
     link  = rows[11].find('a')['href']
     ver   = rows[6].find('div').text.split()[0]
     print(link, ver)
    -
    -

    #Web

    -
    # $ pip3 install bottle
    +
    + + +

    #Web

    # $ pip3 install bottle
     from bottle import run, route, post, template, request, response
     import json
    -
    -

    Run

    -
    run(host='localhost', port=8080)
    +
    + +

    Run

    run(host='localhost', port=8080)
     run(host='0.0.0.0', port=80, server='cherrypy')
    -
    -

    Static Request

    -
    @route('/img/<image>')
    +
    + +

    Static Request

    @route('/img/<image>')
     def send_image(image):
         return static_file(image, 'images/', mimetype='image/png')
    -
    -

    Dynamic Request

    -
    @route('/<sport>')
    +
    + +

    Dynamic Request

    @route('/<sport>')
     def send_page(sport):
         return template('<h1>{{title}}</h1>', title=sport)
    -
    -

    REST Request

    -
    @post('/odds/<sport>')
    +
    + +

    REST Request

    @post('/odds/<sport>')
     def odds_handler(sport):
         team = request.forms.get('team')
         home_odds, away_odds = 2.44, 3.29
         response.headers['Content-Type'] = 'application/json'
         response.headers['Cache-Control'] = 'no-cache'
         return json.dumps([team, home_odds, away_odds])
    -
    -

    Test:

    -
    # $ pip3 install requests
    +
    + +

    Test:

    # $ pip3 install requests
     >>> import requests
     >>> url  = 'http://localhost:8080/odds/football'
     >>> data = {'team': 'arsenal f.c.'}
     >>> response = requests.post(url, data=data)
     >>> response.json()
     ['arsenal f.c.', 2.44, 3.29]
    -
    -

    #Profile

    -

    Basic

    -
    from time import time
    +
    + +

    #Profile

    Basic

    from time import time
     start_time = time()                  # Seconds since Epoch.
     ...
     duration = time() - start_time
    -
    -

    High Performance

    -
    from time import perf_counter as pc
    +
    + + +

    High Performance

    from time import perf_counter as pc
     start_time = pc()                    # Seconds since restart.
     ...
     duration = pc() - start_time
    -
    -

    Timing a Snippet

    -
    >>> from timeit import timeit
    +
    + +

    Timing a Snippet

    >>> from timeit import timeit
     >>> timeit('"-".join(str(a) for a in range(100))',
     ...        number=10000, globals=globals(), setup='pass')
     0.34986
    -
    -

    Line Profiler

    -
    # $ pip3 install line_profiler
    +
    + +

    Line Profiler

    # $ pip3 install line_profiler
     @profile
     def main():
         a = [*range(10000)]
         b = {*range(10000)}
     main()
    -
    -

    Usage:

    -
    $ kernprof -lv test.py
    +
    + +

    Usage:

    $ kernprof -lv test.py
     Line #      Hits         Time  Per Hit   % Time  Line Contents
     ==============================================================
          1                                           @profile
          2                                           def main():
          3         1       1128.0   1128.0     27.4      a = [*range(10000)]
          4         1       2994.0   2994.0     72.6      b = {*range(10000)}
    -
    -

    Call Graph

    -

    Generates a PNG image of a call graph with highlighted bottlenecks:

    -
    # $ pip3 install pycallgraph
    +
    + +

    Call Graph

    Generates a PNG image of a call graph with highlighted bottlenecks:

    # $ pip3 install pycallgraph
     from pycallgraph import output, PyCallGraph
     from datetime import datetime
     time_str = datetime.now().strftime('%Y%m%d%H%M%S')
    @@ -2032,12 +2039,14 @@ filename = f'profile-{time_st
     drawer = output.GraphvizOutput(output_file=filename)
     with PyCallGraph(drawer):
         <code_to_be_profiled>
    -
    -

    #NumPy

    -

    Array manipulation mini language. Can run up to one hundred times faster than equivalent Python code.

    -
    # $ pip3 install numpy
    +
    + + +

    #NumPy

    Array manipulation mini language. Can run up to one hundred times faster than equivalent Python code.

    # $ pip3 install numpy
     import numpy as np
    -
    +
    + +
    <array> = np.array(<list>)
     <array> = np.arange(from_inclusive, to_exclusive, ±step_size)
     <array> = np.ones(<shape>)
    @@ -2054,12 +2063,12 @@ indexes = <array>.argmin(axis)
     
  • Shape is a tuple of dimension sizes.
  • Axis is an index of dimension that gets collapsed. Leftmost dimension has index 0.
  • -

    Indexing

    -
    <el>       = <2d_array>[0, 0]        # First element.
    +

    Indexing

    <el>       = <2d_array>[0, 0]        # First element.
     <1d_view>  = <2d_array>[0]           # First row.
     <1d_view>  = <2d_array>[:, 0]        # First column. Also [..., 0].
     <3d_view>  = <2d_array>[None, :, :]  # Expanded by dimension of size 1.
    -
    +
    +
    <1d_array> = <2d_array>[<1d_row_indexes>, <1d_column_indexes>]
     <2d_array> = <2d_array>[<2d_row_indexes>, <2d_column_indexes>]
     
    @@ -2069,23 +2078,20 @@ indexes = <array>.argmin(axis)
    • If row and column indexes differ in shape, they are combined with broadcasting.
    -

    Broadcasting

    -

    Broadcasting is a set of rules by which NumPy functions operate on arrays of different sizes and/or dimensions.

    -
    left  = [[0.1], [0.6], [0.8]]  # Shape: (3, 1)
    +

    Broadcasting

    Broadcasting is a set of rules by which NumPy functions operate on arrays of different sizes and/or dimensions.

    left  = [[0.1], [0.6], [0.8]]  # Shape: (3, 1)
     right = [ 0.1 ,  0.6 ,  0.8 ]  # Shape: (3)
    -
    -

    1. If array shapes differ in length, left-pad the shorter shape with ones:

    -
    left  = [[0.1], [0.6], [0.8]]  # Shape: (3, 1)
    +
    + + +

    1. If array shapes differ in length, left-pad the shorter shape with ones:

    left  = [[0.1], [0.6], [0.8]]  # Shape: (3, 1)
     right = [[0.1 ,  0.6 ,  0.8]]  # Shape: (1, 3) <- !
    -
    -

    2. If any dimensions differ in size, expand the ones that have size 1 by duplicating their elements:

    -
    left  = [[0.1, 0.1, 0.1], [0.6, 0.6, 0.6], [0.8, 0.8, 0.8]]  # Shape: (3, 3) <- !
    +
    + +

    2. If any dimensions differ in size, expand the ones that have size 1 by duplicating their elements:

    left  = [[0.1, 0.1, 0.1], [0.6, 0.6, 0.6], [0.8, 0.8, 0.8]]  # Shape: (3, 3) <- !
     right = [[0.1, 0.6, 0.8], [0.1, 0.6, 0.8], [0.1, 0.6, 0.8]]  # Shape: (3, 3) <- !
    -
    -

    3. If neither non-matching dimension has size 1, rise an error.

    -

    Example

    -

    For each point returns index of its nearest point ([0.1, 0.6, 0.8] => [1, 2, 1]):

    -
    >>> points = np.array([0.1, 0.6, 0.8])
    +
    + +

    3. If neither non-matching dimension has size 1, rise an error.

    Example

    For each point returns index of its nearest point ([0.1, 0.6, 0.8] => [1, 2, 1]):

    >>> points = np.array([0.1, 0.6, 0.8])
     [ 0.1,  0.6,  0.8]
     >>> wrapped_points = points.reshape(3, 1)
     [[ 0.1],
    @@ -2107,13 +2113,15 @@ right = [[0.1, 0.60.7,  0.2,  inf]]
     >>> distances.argmin(1)
     [1, 2, 1]
    -
    -

    #Image

    -
    # $ pip3 install pillow
    +
    + + + +

    #Image

    # $ pip3 install pillow
     from PIL import Image
    -
    -

    Creates a PNG image of a rainbow gradient:

    -
    width  = 100
    +
    + +

    Creates a PNG image of a rainbow gradient:

    width  = 100
     height = 100
     size   = width * height
     pixels = [255 * i/size for i in range(size)]
    @@ -2121,56 +2129,56 @@ pixels = [255 * i/size 'HSV', (width, height))
     img.putdata([(int(a), 255, 255) for a in pixels])
     img.convert(mode='RGB').save('test.png')
    -
    -

    Adds noise to a PNG image:

    -
    from random import randint
    +
    + +

    Adds noise to a PNG image:

    from random import randint
     add_noise = lambda value: max(0, min(255, value + randint(-20, 20)))
     img = Image.open('test.png').convert(mode='HSV')
     img.putdata([(add_noise(h), s, v) for h, s, v in img.getdata()])
     img.convert(mode='RGB').save('test.png')
    -
    -

    Modes

    -
      +
    + +

    Modes

    • '1' - 1-bit pixels, black and white, stored with one pixel per byte.
    • 'L' - 8-bit pixels, greyscale.
    • 'RGB' - 3x8-bit pixels, true color.
    • 'RGBA' - 4x8-bit pixels, true color with transparency mask.
    • 'HSV' - 3x8-bit pixels, Hue, Saturation, Value color space.
    • -
    -

    #Audio

    -
    import wave
    +
    + +

    #Audio

    import wave
     from struct import pack, iter_unpack
    -
    -

    Read Frames from WAV File

    -
    def read_wav_file(filename):
    +
    + +

    Read Frames from WAV File

    def read_wav_file(filename):
         with wave.open(filename, 'rb') as wf:
             frames = wf.readframes(wf.getnframes())
             return [a[0] for a in iter_unpack('<h', frames)]
    -
    -

    Write Frames to WAV File

    -
    def write_to_wav_file(filename, frames_int, mono=True):
    +
    + +

    Write Frames to WAV File

    def write_to_wav_file(filename, frames_int, mono=True):
         frames_short = (pack('<h', a) for a in frames_int)
         with wave.open(filename, 'wb') as wf:
             wf.setnchannels(1 if mono else 2)
             wf.setsampwidth(2)
             wf.setframerate(44100)
             wf.writeframes(b''.join(frames_short))
    -
    -

    Examples

    -

    Saves a sine wave to a mono WAV file:

    -
    from math import pi, sin
    +
    + +

    Examples

    Saves a sine wave to a mono WAV file:

    from math import pi, sin
     frames_f = (sin(i * 2 * pi * 440 / 44100) for i in range(100000))
     frames_i = (int(a * 30000) for a in frames_f)
     write_to_wav_file('test.wav', frames_i)
    -
    -

    Adds noise to a mono WAV file:

    -
    from random import randint
    +
    + + +

    Adds noise to a mono WAV file:

    from random import randint
     add_noise = lambda value: max(-32768, min(32767, value + randint(-500, 500)))
     frames_i  = (add_noise(a) for a in read_wav_file('test.wav'))
     write_to_wav_file('test.wav', frames_i)
    -
    -

    Synthesizer

    -
    # $ pip3 install simpleaudio
    +
    + +

    Synthesizer

    # $ pip3 install simpleaudio
     import simpleaudio, math, struct
     from itertools import chain, repeat
     F  = 44100
    @@ -2185,9 +2193,9 @@ get_frames = lambda note: get_wave(*parse_note
     frames_f   = chain.from_iterable(get_frames(n) for n in f'{P1}{P1}{P2}'.split(','))
     frames_b   = b''.join(struct.pack('<h', int(f * 30000)) for f in frames_f)
     simpleaudio.play_buffer(frames_b, 1, 2, F)
    -
    -

    #Basic Script Template

    -
    #!/usr/bin/env python3
    +
    + +

    #Basic Script Template

    #!/usr/bin/env python3
     #
     # Usage: .py
     #
    @@ -2214,7 +2222,8 @@ simpleaudio.play_buffer(frames_b, 1, if __name__ == '__main__':
         main()
    -
    +
    +