diff --git a/README.md b/README.md index 3fa32085a..e905c08c2 100644 --- a/README.md +++ b/README.md @@ -28,21 +28,25 @@ if __name__ == '__main__': # Skips next line if file was imported. List ---- +```python + = [, , ...] # Creates new list. Also list(). +``` + ```python = [index] # First index is 0. Last -1. Allows assignments. - = [] # Or: [from_inclusive : to_exclusive : ±step] + = [] # Also [from_inclusive : to_exclusive : ±step]. ``` ```python -.append() # Or: += [] -.extend() # Or: += +.append() # Appends element to the end. Also += []. +.extend() # Appends elements to the end. Also += . ``` ```python -.sort() # Sorts in ascending order. +.sort() # Sorts elements in ascending order. .reverse() # Reverses the list in-place. - = sorted() # Returns a new sorted list. - = reversed() # Returns reversed iterator. + = sorted() # Returns new list with sorted elements. + = reversed() # Returns reversed iterator of elements. ``` ```python @@ -70,6 +74,10 @@ list_of_chars = list() Dictionary ---------- +```python + = {key_1: val_1, key_2: val_2, ...} # Use `[key]` to get or set the value. +``` + ```python = .keys() # Coll. of keys that reflects changes. = .values() # Coll. of values that reflects changes. @@ -101,17 +109,15 @@ value = .pop(key) # Removes item or raises KeyErro >>> from collections import Counter >>> counter = Counter(['blue', 'blue', 'blue', 'red', 'red']) >>> counter['yellow'] += 1 ->>> print(counter) -Counter({'blue': 3, 'red': 2, 'yellow': 1}) ->>> counter.most_common()[0] -('blue', 3) +>>> print(counter.most_common()) +[('blue', 3), ('red', 2), ('yellow', 1)] ``` Set --- ```python - = set() # `{}` returns a dictionary. + = {, , ...} # Use `set()` for empty set. ``` ```python @@ -384,7 +390,7 @@ import re ``` * **By default, decimal characters, alphanumerics and whitespaces from all alphabets are matched unless `'flags=re.ASCII'` argument is used.** -* **It restricts special sequence matches to `'[\x00-\x7f]'` (the first 128 characters) and also prevents `'\s'` from accepting `'[\x1c-\x1f]'` (the so-called separator characters).** +* **It restricts special sequence matches to `'[\x00-\x7f]'` (the first 128 characters) and also prevents `'\s'` from accepting `'[\x1c-\x1f]'` (file, table, row, and field separators).** * **Use a capital letter for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).** @@ -412,7 +418,7 @@ Format {:.<10} # '......' {:0} # '' ``` -* **Objects are rendered using `'format(, )'`.** +* **Objects are rendered using `'format(, "")'`.** * **Options can be generated dynamically: `f'{:{}[…]}'`.** * **Adding `'='` to the expression prepends it to the output: `f'{1+1=}'` returns `'1+1=2'`.** * **Adding `'!r'` to the expression converts object to string by calling its [repr()](#class) method.** @@ -590,7 +596,7 @@ Datetime ```python # $ pip3 install python-dateutil from datetime import date, time, datetime, timedelta, timezone -from dateutil.tz import tzlocal, gettz +import zoneinfo, dateutil.tz ``` ```python @@ -601,7 +607,7 @@ from dateutil.tz import tzlocal, gettz ``` * **Aware `` time and datetime objects have defined timezone, while naive `` don't. If object is naive, it is presumed to be in the system's timezone!** * **`'fold=1'` means the second pass in case of time jumping back for one hour.** -* **Timedelta normalizes arguments to ±days, seconds (< 86 400) and microseconds (< 1M).** +* **Timedelta normalizes arguments to ±days, seconds (< 86 400) and microseconds (< 1M). Its str() method returns `'[±D, ]H:MM:SS[.…]'` and total_seconds() a float of all seconds.** * **Use `'.weekday()'` to get the day of the week as an int, with Monday being 0.** ### Now @@ -615,13 +621,13 @@ from dateutil.tz import tzlocal, gettz ```python = timezone.utc # London without daylight saving time (DST). = timezone() # Timezone with fixed offset from UTC. - = tzlocal() # Local tz with dynamic offset. Also gettz(). - = gettz('/') # 'Continent/City_Name' timezone or None. + = dateutil.tz.tzlocal() # Local timezone with dynamic offset from UTC. + = zoneinfo.ZoneInfo('') # 'Continent/City_Name' zone with dynamic offset. =
.astimezone([]) # Converts DT to the passed or local fixed zone. = .replace(tzinfo=) # Changes object's timezone without conversion. ``` -* **Timezones returned by tzlocal(), gettz(), and implicit local timezone of naive objects have offsets that vary through time due to DST and historical changes of the zone's base offset.** -* **Standard library's zoneinfo.ZoneInfo() can be used instead of gettz() on Python 3.9 and later. It requires 'tzdata' package on Windows. It doesn't return local tz if arg. is omitted.** +* **Timezones returned by tzlocal(), ZoneInfo() and implicit local timezone of naive objects have offsets that vary through time due to DST and historical changes of the base offset.** +* **To get ZoneInfo() to work on Windows run `'> pip3 install tzdata'`.** ### Encode ```python @@ -660,7 +666,7 @@ from dateutil.tz import tzlocal, gettz = - # Ignores jumps if they share tzinfo object. = ± # Returned datetime can fall into missing hour. = * # Also: = abs() and = ±% . - = / # How many hours/weeks/years are in TD. Also //. + = / # E.g. how many hours are in TD. Also //, divmod(). ``` @@ -739,7 +745,7 @@ def f(x, y, *, z): ... # f(x=1, y=2, z=3) | f(1, y=2, z=3) | f(1, 2, z= = [* [, ...]] # Or: list() [+ ...] = (*, [...]) # Or: tuple() [+ ...] = {* [, ...]} # Or: set() [| ...] - = {** [, ...]} # Or: | ... (since 3.9) + = {** [, ...]} # Or: | ... ``` ```python @@ -862,7 +868,7 @@ from functools import partial >>> multiply_by_3(10) 30 ``` -* **Partial is also useful in cases when function needs to be passed as an argument because it enables us to set its arguments beforehand.** +* **Partial is also useful in cases when a function needs to be passed as an argument because it enables us to set its arguments beforehand.** * **A few examples being: `'defaultdict()'`, `'iter(, to_exc)'` and dataclass's `'field(default_factory=)'`.** ### Non-Local @@ -913,21 +919,20 @@ def debug(func): def add(x, y): return x + y ``` -* **Wraps is a helper decorator that copies the metadata of the passed function (func) to the function it is wrapping (out).** -* **Without it, `'add.__name__'` would return `'out'`.** +* **Wraps is a helper decorator that copies the metadata of the passed function (func) to the function it is wrapping (out). Without it, `'add.__name__'` would return `'out'`.** -### LRU Cache +### Cache **Decorator that caches function's return values. All function's arguments must be hashable.** ```python -from functools import lru_cache +from functools import cache -@lru_cache(maxsize=None) +@cache def fib(n): return n if n < 2 else fib(n-2) + fib(n-1) ``` -* **Default size of the cache is 128 values. Passing `'maxsize=None'` makes it unbounded.** -* **CPython interpreter limits recursion depth to 3000 by default. To increase it use `'sys.setrecursionlimit()'`.** +* **Potential problem with cache is that it can grow indefinitely. To clear its stored values run `'fib.cache_clear()'`, or use `'@lru_cache(maxsize=)'` decorator instead.** +* **CPython interpreter limits recursion depth to 3000 by default. To increase it run `'sys.setrecursionlimit()'`.** ### Parametrized Decorator **A decorator that accepts arguments and returns a normal decorator that accepts a function.** @@ -1184,7 +1189,7 @@ class Counter: ### Callable * **All functions and classes have a call() method, hence are callable.** -* **To check if object is callable use `'callable()'`, `'isinstance(, collections.abc.Callable)'`, or `'isinstance(, typing.Callable)'`.** +* **Use `'callable()'` or `'isinstance(, collections.abc.Callable)'` to check if object is callable.** * **When this cheatsheet uses `''` as an argument, it means `''`.** ```python class Counter: @@ -1253,7 +1258,7 @@ True ### Collection * **Only required methods are iter() and len(). Len() should return the number of items.** * **This cheatsheet actually means `''` when it uses `''`.** -* **I chose not to use the name 'iterable' because it sounds scarier and more vague than 'collection'. The only drawback of this decision is that the reader could think a certain function doesn't accept iterators when it does, since iterators are the only built-in objects that are iterable but are not collections.** +* **I chose not to use the name 'iterable' because it sounds scarier and more vague than 'collection'. The main drawback of this decision is that the reader could think a certain function doesn't accept iterators when it does, since iterators are the only built-in objects that are iterable but are not collections.** ```python class MyCollection: def __init__(self, a): @@ -1270,7 +1275,7 @@ class MyCollection: * **Only required methods are getitem() and len().** * **Getitem() should return an item at the passed 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.** +* **Reversed() automatically works on any object that has getitem() and len() defined. It returns reversed iterator of object's items.** ```python class MySequence: def __init__(self, a): @@ -1288,7 +1293,7 @@ class MySequence: ``` #### Discrepancies between glossary definitions and abstract base classes: -* **Glossary defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.** +* **Glossary on Python's website defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.** * **Passing ABC Iterable to isinstance() or issubclass() checks whether object/class has method iter(), while ABC Collection checks for iter(), contains() and len().** ### ABC Sequence @@ -1322,8 +1327,7 @@ class MyAbcSequence(abc.Sequence): +------------+------------+------------+------------+--------------+ ``` * **Method iter() is required for `'isinstance(, abc.Iterable)'` to return True, however any object with getitem() will work with any code expecting an iterable.** -* **Other extendable ABCs: MutableSequence, Set, MutableSet, Mapping, MutableMapping.** -* **Names of their required methods are stored in `'.__abstractmethods__'`.** +* **MutableSequence, Set, MutableSet, Mapping and MutableMapping ABCs are also extendable. Use `'.__abstractmethods__'` to get names of required methods.** Enum @@ -1550,8 +1554,8 @@ p.add_argument('-', '--', type=) # Option (defa p.add_argument('', type=, nargs=1) # Mandatory first argument. p.add_argument('', type=, nargs='+') # Mandatory remaining args. p.add_argument('', type=, nargs='?/*') # Optional argument/s. - = p.parse_args() # Exits on parsing error. - = . # Returns `()`. +args = p.parse_args() # Exits on parsing error. + = args. # Returns `()`. ``` * **Use `'help='` to set argument description that will be displayed in help message.** @@ -1578,7 +1582,7 @@ Open * **`'w+'` - Read and write. Deletes existing contents.** * **`'r+'` - Read and write from the start.** * **`'a+'` - Read and write from the end.** -* **`'b'` - Binary mode (`'br'`, `'bw'`, `'bx'`, …)** +* **`'b'` - Binary mode (`'rb'`, `'wb'`, `'xb'`, …)** ### Exceptions * **`'FileNotFoundError'` can be raised when reading with `'r'` or `'r+'`.** @@ -1591,7 +1595,7 @@ Open .seek(0) # Moves to the start of the file. .seek(offset) # Moves 'offset' chars/bytes from the start. .seek(0, 2) # Moves to the end of the file. -.seek(±offset, ) # Anchor: 0 start, 1 current position, 2 end. +.seek(±offset, origin) # Origin: 0 start, 1 current position, 2 end. ``` ```python @@ -1660,7 +1664,7 @@ from pathlib import Path ``` ### DirEntry -**Unlike listdir(), scandir() returns DirEntry objects that cache isfile, isdir and on Windows also stat information, thus significantly increasing the performance of code that requires it.** +**Unlike listdir(), scandir() returns DirEntry objects that cache isfile, isdir, and on Windows also stat information, thus significantly increasing the performance of code that requires it.** ```python = os.scandir(path='.') # Returns DirEntry objects located at the path. @@ -1671,16 +1675,16 @@ from pathlib import Path ### Path Object ```python - = Path( [, ...]) # Accepts strings, Paths and DirEntry objects. + = Path( [, ...]) # Accepts strings, Paths, and DirEntry objects. = / [/ ...] # First or second path must be a Path object. = .resolve() # Returns absolute path with resolved symlinks. ``` ```python - = Path() # Returns relative cwd. Also Path('.'). - = Path.cwd() # Returns absolute cwd. Also Path().resolve(). + = Path() # Returns relative CWD. Also Path('.'). + = Path.cwd() # Returns absolute CWD. Also Path().resolve(). = Path.home() # Returns user's home directory (absolute). - = Path(__file__).resolve() # Returns script's path if cwd wasn't changed. + = Path(__file__).resolve() # Returns script's path if CWD wasn't changed. ``` ```python @@ -1834,7 +1838,7 @@ import csv .writerows() # Appends multiple rows. ``` * **File must be opened with a `'newline=""'` argument, or '\r' will be added in front of every '\n' on platforms that use '\r\n' line endings!** -* **Open existing file with `'mode="w"'` to overwrite it or `'mode="a"'` to append to it.** +* **Open existing file with `'mode="a"'` to append to it or `'mode="w"'` to overwrite it.** ### Parameters * **`'dialect'` - Master parameter that sets the default values. String or a 'csv.Dialect' object.** @@ -1863,16 +1867,16 @@ import csv ### Read Rows from CSV File ```python -def read_csv_file(filename, dialect='excel', **params): +def read_csv_file(filename, **csv_params): with open(filename, encoding='utf-8', newline='') as file: - return list(csv.reader(file, dialect, **params)) + return list(csv.reader(file, **csv_params)) ``` ### Write Rows to CSV File ```python -def write_to_csv_file(filename, rows, mode='w', dialect='excel', **params): +def write_to_csv_file(filename, rows, mode='w', **csv_params): with open(filename, mode, encoding='utf-8', newline='') as file: - writer = csv.writer(file, dialect, **params) + writer = csv.writer(file, **csv_params) writer.writerows(rows) ``` @@ -1938,14 +1942,14 @@ with .begin(): ... # Exits the block with commit or ``` ```text -+------------+--------------+----------+----------------------------------+ -| Dialect | pip3 install | import | Dependencies | -+------------+--------------+----------+----------------------------------+ -| mysql | mysqlclient | MySQLdb | www.pypi.org/project/mysqlclient | -| postgresql | psycopg2 | psycopg2 | www.pypi.org/project/psycopg2 | -| mssql | pyodbc | pyodbc | www.pypi.org/project/pyodbc | -| oracle | oracledb | oracledb | www.pypi.org/project/oracledb | -+------------+--------------+----------+----------------------------------+ ++-----------------+--------------+----------------------------------+ +| Dialect | pip3 install | Dependencies | ++-----------------+--------------+----------------------------------+ +| mysql | mysqlclient | www.pypi.org/project/mysqlclient | +| postgresql | psycopg2 | www.pypi.org/project/psycopg2 | +| mssql | pyodbc | www.pypi.org/project/pyodbc | +| oracle+oracledb | oracledb | www.pypi.org/project/oracledb | ++-----------------+--------------+----------------------------------+ ``` @@ -2059,14 +2063,14 @@ Memory View ```python = memoryview() # Immutable if bytes is passed, else mutable. - = [index] # Returns int/float. Bytes if format is 'c'. + = [index] # Returns int or float. Bytes if format is 'c'. = [] # Returns memoryview with rearranged elements. = .cast('') # Only works between B/b/c and other types. .release() # Releases memory buffer of the base object. ``` ```python - = bytes() # Returns a new bytes object. + = bytes() # Returns a new bytes object. Also bytearray(). = .join() # Joins memoryviews using bytes as a separator. = array('', ) # Treats memoryview as a sequence of numbers. .write() # Writes `bytes()` to the binary file. @@ -2156,7 +2160,7 @@ with : # Enters the block by calling acq = .cancel() # Cancels or returns False if running/finished. = as_completed() # `next()` returns next completed Future. ``` -* **Map() and as\_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called/blocking. Map() times from original call and as_completed() from first call to next(). As\_completed() fails if next() is called too late, even if all threads have finished.** +* **Map() and as\_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called/blocking. Map() times from original call and as_completed() from first call to next(). As\_completed() fails if next() is called too late, even if all threads are done.** * **Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.** * **ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be [pickable](#pickle), queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via `'if __name__ == "__main__": ...'`.** @@ -2166,6 +2170,9 @@ Operator **Module of functions that provide the functionality of operators. Functions are ordered by operator precedence, starting with least binding.** ```python import operator as op +``` + +```python = op.not_() # or, and, not (or/and missing) = op.eq/ne/lt/ge/is_/is_not/contains(, ) # ==, !=, <, >=, is, is not, in = op.or_/xor/and_(, ) # |, ^, & @@ -2201,8 +2208,8 @@ match : ### Patterns ```python = 1/'abc'/True/None/math.pi # Matches the literal or a dotted name. - = () # Matches any object of that type. - = _ # Matches any object. + = () # Matches any object of that type (or ABC). + = _ # Matches any object. Useful in last case. = # Matches any object and binds it to name. = as # Binds match to name. Also (). = | [| ...] # Matches any of the patterns. @@ -2212,7 +2219,7 @@ match : ``` * **Sequence pattern can also be written as a tuple.** * **Use `'*'` and `'**'` in sequence/mapping patterns to bind remaining items.** -* **Sequence pattern must match all items, while mapping pattern does not.** +* **Sequence pattern must match all items of the collection, while mapping pattern does not.** * **Patterns can be surrounded with brackets to override precedence (`'|'` > `'as'` > `','`).** * **Built-in types allow a single positional pattern that is matched against the entire object.** * **All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement.** @@ -2222,11 +2229,9 @@ match : >>> from pathlib import Path >>> match Path('/home/gto/python-cheatsheet/README.md'): ... case Path( -... parts=['/', 'home', user, *_], -... stem=stem, -... suffix=('.md' | '.txt') as suffix -... ) if stem.lower() == 'readme': -... print(f'{stem}{suffix} is a readme file that belongs to user {user}.') +... parts=['/', 'home', user, *_] +... ) as p if p.name.lower().startswith('readme') and p.is_file(): +... print(f'{p.name} is a readme file that belongs to user {user}.') 'README.md is a readme file that belongs to user gto.' ``` @@ -2239,9 +2244,9 @@ import logging as log ```python log.basicConfig(filename=, level='DEBUG') # Configures the root logger (see Setup). -log.debug/info/warning/error/critical() # Logs to the root logger. - = log.getLogger(__name__) # Logger named after the module. -.() # Logs to the logger. +log.debug/info/warning/error/critical() # Sends message to the root logger. + = log.getLogger(__name__) # Returns logger named after the module. +.() # Sends message to the logger. .exception() # Error() that appends caught exception. ``` @@ -2265,12 +2270,12 @@ log.basicConfig( .propagate = # Cuts off ancestors' handlers if False. ``` * **Parent logger can be specified by naming the child logger `'.'`.** -* **If logger doesn't have a set level it inherits it from the first ancestor that does.** +* **If logger doesn't have a set level, it inherits it from the first ancestor that does.** * **Formatter also accepts: pathname, filename, funcName, lineno, thread and process.** -* **RotatingFileHandler creates and deletes files based on 'maxBytes' and 'backupCount' args.** +* **RotatingFileHandler creates and deletes files based on 'maxBytes', 'backupCount' args.** * **An object with `'filter()'` method (or the method itself) can be added to loggers and handlers via addFilter(). Message is dropped if filter() returns a false value.** -#### Creates a logger that writes all messages to file and sends them to the root's handler that prints warnings or higher: +#### Creates a logger that writes all messages to a file and sends them to the root's handler that prints warnings or higher: ```python >>> logger = log.getLogger('my_module') >>> handler = log.FileHandler('test.log', encoding='utf-8') @@ -2289,25 +2294,25 @@ CRITICAL:my_module:Running out of disk space. Introspection ------------- ```python - = dir() # Names of local vars, functions, classes and modules. - = vars() # Dict of local vars, functions, etc. Also locals(). - = globals() # Dict of global vars, etc. (including '__builtins__'). + = dir() # List of of local names (including functions and classes). + = vars() # Dict of local names and their objects. Also locals(). + = globals() # Dict of global names (for instance '__builtin__' module). ``` ```python - = dir() # Names of all object's attributes (including methods). - = vars() # Dict of writable attributes. Also .__dict__. - = hasattr(, '') # Checks if getattr() raises AttributeError. -value = getattr(, '') # Default value can be passed as the third argument. -setattr(, '', value) # Only works on objects with __dict__ attribute. -delattr(, '') # Same. Also `del .`. + = dir() # Returns names of all object's attributes (incl. methods). + = vars() # Returns dict of writable attributes. Also .__dict__. + = hasattr(, '') # Checks if object possesses attribute with passed name. +value = getattr(, '') # Returns object's attribute or raises AttributeError. +setattr(, '', value) # Sets attribute. Only works on objects with __dict__. +delattr(, '') # Deletes attribute from __dict__. Also `del .`. ``` ```python - = inspect.signature() # Returns function's Signature object. - = .parameters # Dict of Parameters. Also .return_annotation. - = .kind # Member of ParamKind enum (Parameter.KEYWORD_ONLY, …). - = .default # Parameter.empty if missing. Also .annotation. + = inspect.signature() # Returns function's Signature object. Can accept a class. + = .parameters # Returns dict of Parameters. Also .return_annotation. + = .kind # Returns ParameterKind member (Parameter.KEYWORD_ONLY, …). + = .annotation # Returns Parameter.empty if missing. Also .default. ``` @@ -2315,7 +2320,7 @@ Coroutines ---------- * **Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t use as much memory.** * **Coroutine definition starts with `'async'` and its call with `'await'`.** -* **`'asyncio.run()'` is the main entry point for asynchronous programs.** +* **Use `'asyncio.run()'` to start the first/main coroutine.** ```python import asyncio as aio @@ -2323,9 +2328,9 @@ import asyncio as aio ```python = () # Creates a coroutine by calling async def function. - = await # Starts the coroutine and returns result. + = await # Starts the coroutine and returns its result. = aio.create_task() # Schedules the coroutine for execution. - = await # Returns result. Also .cancel(). + = await # Returns coroutine's result. Also .cancel(). ``` ```python @@ -2349,7 +2354,7 @@ def main(screen): async def main_coroutine(screen): moves = asyncio.Queue() - state = {'*': P(0, 0), **{id_: P(W//2, H//2) for id_ in range(10)}} + state = {'*': P(0, 0)} | {id_: P(W//2, H//2) for id_ in range(10)} ai = [random_controller(id_, moves) for id_ in range(10)] mvc = [human_controller(screen, moves), model(moves, state), view(state, screen)] tasks = [asyncio.create_task(coro) for coro in ai + mvc] @@ -2411,9 +2416,9 @@ Plot # $ pip3 install matplotlib import matplotlib.pyplot as plt -plt.plot/bar/scatter(x_data, y_data [, label=]) # Or: plt.plot(y_data) +plt.plot/bar/scatter(x_data, y_data [, label=]) # Also plt.plot(y_data). plt.legend() # Adds a legend. -plt.title/xlabel/ylabel() # Adds a title/label. +plt.title/xlabel/ylabel() # Adds a title or label. plt.savefig() # Saves the figure. plt.show() # Displays the figure. plt.clf() # Clears the figure. @@ -2471,7 +2476,7 @@ GUI App # $ pip3 install PySimpleGUI import PySimpleGUI as sg -text_box = sg.Input(default_text='100', enable_events=True, key='-VALUE-') +text_box = sg.Input(default_text='100', enable_events=True, key='-QUANTITY-') dropdown = sg.InputCombo(['g', 'kg', 't'], 'kg', readonly=True, enable_events=True, k='-UNIT-') label = sg.Text('100 kg is 220.462 lbs.', key='-OUTPUT-') button = sg.Button('Close') @@ -2482,13 +2487,13 @@ while True: if event in [sg.WIN_CLOSED, 'Close']: break try: - value = float(values['-VALUE-']) + quantity = float(values['-QUANTITY-']) except ValueError: continue unit = values['-UNIT-'] factors = {'g': 0.001, 'kg': 1, 't': 1000} - lbs = value * factors[unit] / 0.45359237 - window['-OUTPUT-'].update(value=f'{value} {unit} is {lbs:g} lbs.') + lbs = quantity * factors[unit] / 0.45359237 + window['-OUTPUT-'].update(value=f'{quantity} {unit} is {lbs:g} lbs.') window.close() ``` @@ -2518,37 +2523,37 @@ print(f'{python_url}, file://{os.path.abspath(filename)}') # $ pip3 install selenium from selenium import webdriver - = webdriver.Chrome/Firefox/Safari/Edge() # Opens the browser. Also .quit(). -.get('') # Also .implicitly_wait(seconds). - = .find_element('css selector', '') # '#.[=""]'. - = .find_elements('xpath', '') # '//[@=""]'. - = .get_attribute() # Property if exists. Also .text. -.click/clear() # Also .send_keys(). + = webdriver.Chrome/Firefox/Safari/Edge() # Opens a browser. Also .quit(). +.get('') # Also .implicitly_wait(seconds). + = .find_element('css selector', …) # '#.[=""]…'. + = .find_elements('xpath', …) # '//[@=""]…'. See XPath. + = .get_attribute() # Property if exists. Also .text. +.click/clear() # Also .send_keys(). ``` -#### XPath — also available in lxml, Scrapy, and browser's console via `'$x()'`: +#### XPath — also available in lxml, Scrapy, and browser's console via `'$x("")'`: ```python - = //[/ or // ] # /, //, /../ - = ///following:: # Next element. Also preceding/parent/… - = # ` = */a/…`, ` = [1/2/…]`. - = [ [and/or ]] # For negation use `not()`. - = @[=""] # `text()=`, `.=` match (complete) text. - = contains(@, "") # Is a substring of attr's value? - = [//] # Has matching child? Descendant if //. + = //[/ or // ] # /, //, /../ + = ///following:: # Next element. Also preceding/parent/… + = # ` = */a/…`, ` = [1/2/…]`. + = [ [and/or ]] # For negation use `not()`. + = @[=""] # `text()=`, `.=` match (complete) text. + = contains(@, "") # Is a substring of attr's value? + = [//] # Has matching child? Descendant if //. ``` -Web ---- +Web App +------- **Flask is a micro web framework/server. If you just want to open a html file in a web browser use `'webbrowser.open()'` instead.** ```python # $ pip3 install flask -import flask +import flask as fl ``` ```python -app = flask.Flask(__name__) # Returns app object. Put at the top. -app.run(host=None, port=None, debug=None) # Or: $ flask --app FILE run [--ARG[=VAL]] +app = fl.Flask(__name__) # Returns the app object. Put at the top. +app.run(host=None, port=None, debug=None) # Or: $ flask --app FILE run [--ARG[=VAL] …] ``` * **Starts the app at `'http://localhost:5000'`. Use `'host="0.0.0.0"'` to run externally.** * **Install a WSGI server like [Waitress](https://flask.palletsprojects.com/en/latest/deploying/waitress/) and a HTTP server such as [Nginx](https://flask.palletsprojects.com/en/latest/deploying/nginx/) for better security.** @@ -2558,25 +2563,25 @@ app.run(host=None, port=None, debug=None) # Or: $ flask --app FILE run [--ARG[= ```python @app.route('/img/') def serve_file(filename): - return flask.send_from_directory('dirname/', filename) + return fl.send_from_directory('dirname/', filename) ``` ### Dynamic Request ```python @app.route('/') def serve_html(sport): - return flask.render_template_string('

{{title}}

', title=sport) + return fl.render_template_string('

{{title}}

', title=sport) ``` -* **Use `'render_template(filename, )'` to render file located in templates dir.** -* **To return an error code use `'abort()'` and to redirect use `'redirect()'`.** -* **`'request.args[]'` returns parameter from the query string (URL part after '?').** -* **`'session[] = '` stores session data. Needs `'app.secret_key = '`.** +* **`'fl.render_template(filename, )'` renders a file located in 'templates' dir.** +* **`'fl.abort()'` returns error code and `'return fl.redirect()'` redirects.** +* **`'fl.request.args[]'` returns parameter from the query string (URL right of '?').** +* **`'fl.session[] = '` stores session data. It requires secret key to be set at the startup with `'app.secret_key = '`.** ### REST Request ```python @app.post('//odds') def serve_json(sport): - team = flask.request.form['team'] + team = fl.request.form['team'] return {'team': team, 'odds': [2.09, 3.74, 3.68]} ``` @@ -2586,8 +2591,7 @@ def serve_json(sport): >>> import threading, requests >>> threading.Thread(target=app.run, daemon=True).start() >>> url = 'http://localhost:5000/football/odds' ->>> request_data = {'team': 'arsenal f.c.'} ->>> response = requests.post(url, data=request_data) +>>> response = requests.post(url, data={'team': 'arsenal f.c.'}) >>> response.json() {'team': 'arsenal f.c.', 'odds': [2.09, 3.74, 3.68]} ``` @@ -2712,7 +2716,7 @@ import numpy as np * **Any value that is broadcastable to the indexed shape can be assigned to the selection.** ### Broadcasting -**Set of rules by which NumPy functions operate on arrays of different sizes and/or dimensions.** +**A set of rules by which NumPy functions operate on arrays of different shapes.** ```python left = [ 0.1 , 0.6 , 0.8 ] # Shape: (3,) @@ -2771,22 +2775,22 @@ from PIL import Image ```python = Image.new('', (width, height)) # Creates new image. Also `color=`. = Image.open() # Identifies format based on file's contents. - = .convert('') # Converts image to the new mode. + = .convert('') # Converts image to the new mode (see Modes). .save() # Selects format based on extension (PNG/JPG…). .show() # Opens image in the default preview app. ``` ```python - = .getpixel((x, y)) # Returns pixel's value (its color). -.putpixel((x, y), ) # Updates pixel's value. - = .getdata() # Returns a flattened view of pixel values. -.putdata() # Updates pixels with a copy of the sequence. + = .getpixel((x, y)) # Returns pixel's value (its color). + = .getdata() # Returns a flattened view of pixel values. +.putpixel((x, y), ) # Updates pixel's value. Clips passed int/s. +.putdata() # Updates pixels with a copy of the sequence. .paste(, (x, y)) # Draws passed image at the specified location. ``` ```python - = .filter() # ` = ImageFilter.()` - = .enhance() # ` = ImageEnhance.()` + = .filter() # Use ImageFilter.() for Filter. + = .enhance() # Use ImageEnhance.() for Enhance. ``` ```python @@ -2797,7 +2801,7 @@ from PIL import Image ### Modes * **`'L'` - Lightness (greyscale image). Each pixel is an int between 0 and 255.** * **`'RGB'` - Red, green, blue (true color image). Each pixel is a tuple of three ints.** -* **`'RGBA'` - RGB with alpha. Low alpha (i.e. forth int) makes pixel more transparent.** +* **`'RGBA'` - RGB with alpha. Low alpha (i.e. forth int) makes pixels more transparent.** * **`'HSV'` - Hue, saturation, value. Three ints representing color in HSV color space.** @@ -2827,10 +2831,10 @@ from PIL import ImageDraw = ImageDraw.Draw() # Object for adding 2D graphics to the image. .point((x, y)) # Draws a point. Truncates floats into ints. .line((x1, y1, x2, y2 [, ...])) # To get anti-aliasing use Image's resize(). -.arc((x1, y1, x2, y2), deg1, deg2) # Always draws in clockwise direction. +.arc((x1, y1, x2, y2), deg1, deg2) # Draws in clockwise dir. Also pieslice(). .rectangle((x1, y1, x2, y2)) # To rotate use Image's rotate() and paste(). .polygon((x1, y1, x2, y2, ...)) # Last point gets connected to the first. -.ellipse((x1, y1, x2, y2)) # To rotate use Image's rotate() and paste(). +.ellipse((x1, y1, x2, y2)) # Also rounded_rectangle(), regular_polygon(). .text((x, y), , font=) # ` = ImageFont.truetype(, size)` ``` * **Use `'fill='` to set the primary color.** @@ -2867,7 +2871,7 @@ import wave ``` ```python - = wave.open('', 'rb') # Opens the WAV file. + = wave.open('') # Opens the WAV file for reading. = .getframerate() # Returns number of frames per second. = .getnchannels() # Returns number of samples per frame. = .getsampwidth() # Returns number of bytes per sample. @@ -2880,14 +2884,13 @@ import wave .setframerate() # Pass 44100 for CD, 48000 for video. .setnchannels() # Pass 1 for mono, 2 for stereo. .setsampwidth() # Pass 2 for CD, 3 for hi-res sound. -.setparams() # Sets all parameters. +.setparams() # Tuple must contain all parameters. .writeframes() # Appends frames to the file. ``` * **Bytes object contains a sequence of frames, each consisting of one or more samples.** * **In a stereo signal, the first sample of a frame belongs to the left channel.** * **Each sample consists of one or more bytes that, when converted to an integer, indicate the displacement of a speaker membrane at a given moment.** -* **If sample width is one byte, then the integer should be encoded unsigned.** -* **For all other sizes, the integer should be encoded signed with little-endian byte order.** +* **If sample width is one byte, then the integer should be encoded unsigned. For all other sizes, the integer should be encoded signed with little-endian byte order.** ### Sample Values ```text @@ -2904,28 +2907,28 @@ import wave ```python def read_wav_file(filename): def get_int(bytes_obj): - an_int = int.from_bytes(bytes_obj, 'little', signed=(sampwidth != 1)) - return an_int - 128 * (sampwidth == 1) - with wave.open(filename, 'rb') as file: - sampwidth = file.getsampwidth() + an_int = int.from_bytes(bytes_obj, 'little', signed=(p.sampwidth != 1)) + return an_int - 128 * (p.sampwidth == 1) + with wave.open(filename) as file: + p = file.getparams() frames = file.readframes(-1) - bytes_samples = (frames[i : i+sampwidth] for i in range(0, len(frames), sampwidth)) - return [get_int(b) / pow(2, sampwidth * 8 - 1) for b in bytes_samples] + bytes_samples = (frames[i : i + p.sampwidth] for i in range(0, len(frames), p.sampwidth)) + return [get_int(b) / pow(2, p.sampwidth * 8 - 1) for b in bytes_samples], p ``` ### Write Float Samples to WAV File ```python -def write_to_wav_file(filename, float_samples, nchannels=1, sampwidth=2, framerate=44100): +def write_to_wav_file(filename, samples_f, p=None, nchannels=1, sampwidth=2, framerate=44100): def get_bytes(a_float): a_float = max(-1, min(1 - 2e-16, a_float)) - a_float += sampwidth == 1 - a_float *= pow(2, sampwidth * 8 - 1) - return int(a_float).to_bytes(sampwidth, 'little', signed=(sampwidth != 1)) + a_float += p.sampwidth == 1 + a_float *= pow(2, p.sampwidth * 8 - 1) + return int(a_float).to_bytes(p.sampwidth, 'little', signed=(p.sampwidth != 1)) + if p is None: + p = wave._wave_params(nchannels, sampwidth, framerate, 0, 'NONE', 'not compressed') with wave.open(filename, 'wb') as file: - file.setnchannels(nchannels) - file.setsampwidth(sampwidth) - file.setframerate(framerate) - file.writeframes(b''.join(get_bytes(f) for f in float_samples)) + file.setparams(p) + file.writeframes(b''.join(get_bytes(f) for f in samples_f)) ``` ### Examples @@ -2936,19 +2939,19 @@ samples_f = (sin(i * 2 * pi * 440 / 44100) for i in range(100_000)) write_to_wav_file('test.wav', samples_f) ``` -#### Adds noise to the mono WAV file: +#### Adds noise to the WAV file: ```python -from random import random -add_noise = lambda value: value + (random() - 0.5) * 0.03 -samples_f = (add_noise(f) for f in read_wav_file('test.wav')) -write_to_wav_file('test.wav', samples_f) +from random import uniform +samples_f, params = read_wav_file('test.wav') +samples_f = (f + uniform(-0.05, 0.05) for f in samples_f) +write_to_wav_file('test.wav', samples_f, params) ``` #### Plays the WAV file: ```python # $ pip3 install simpleaudio from simpleaudio import play_buffer -with wave.open('test.wav', 'rb') as file: +with wave.open('test.wav') as file: p = file.getparams() frames = file.readframes(-1) play_buffer(frames, p.nchannels, p.sampwidth, p.framerate).wait_done() @@ -2977,7 +2980,7 @@ P2 = '71♩,73♪,,74♩,73♪,,74♪,,71♪,,73♩,71♪,,73♪,,69♪,,71♩,6 get_pause = lambda seconds: it.repeat(0, int(seconds * F)) sin_f = lambda i, hz: math.sin(i * 2 * math.pi * hz / F) get_wave = lambda hz, seconds: (sin_f(i, hz) for i in range(int(seconds * F))) -get_hz = lambda note: 8.176 * 2 ** (int(note[:2]) / 12) +get_hz = lambda note: 440 * 2 ** ((int(note[:2]) - 69) / 12) get_sec = lambda note: 1/4 if '♩' in note else 1/8 get_samples = lambda note: get_wave(get_hz(note), get_sec(note)) if note else get_pause(1/8) samples_f = it.chain.from_iterable(get_samples(n) for n in (P1+P2).split(',')) @@ -3018,7 +3021,7 @@ while not pg.event.get(pg.QUIT): = .collidepoint((x, y)) # Checks if rectangle contains the point. = .colliderect() # Checks if the two rectangles overlap. = .collidelist() # Returns index of first colliding Rect or -1. - = .collidelistall() # Returns indexes of all colliding rectangles. + = .collidelistall() # Returns indices of all colliding rectangles. ``` ### Surface @@ -3130,7 +3133,7 @@ def draw(screen, images, mario, tiles): mario.facing_left = mario.spd.x < 0 if mario.spd.x else mario.facing_left is_airborne = D.s not in get_boundaries(mario.rect, tiles) image_index = 4 if is_airborne else (next(mario.frame_cycle) if mario.spd.x else 6) - screen.blit(images[image_index + mario.facing_left * 9], mario.rect) + screen.blit(images[image_index + (mario.facing_left * 9)], mario.rect) for t in tiles: is_border = t.x in [0, (W-1)*16] or t.y in [0, (H-1)*16] screen.blit(images[18 if is_border else 19], t) @@ -3152,7 +3155,7 @@ import pandas as pd, matplotlib.pyplot as plt **Ordered dictionary with a name.** ```python ->>> pd.Series([1, 2], index=['x', 'y'], name='a') +>>> sr = pd.Series([1, 2], index=['x', 'y'], name='a'); sr x 1 y 2 Name: a, dtype: int64 @@ -3200,7 +3203,7 @@ plt.show() # Displays the plot. Also plt.sav ``` ```python ->>> sr = pd.Series([2, 3], index=['x', 'y']) +>>> sr = pd.Series([2, 3], index=['x', 'y']); sr x 2 y 3 ``` @@ -3231,7 +3234,7 @@ y 3 **Table with labeled rows and columns.** ```python ->>> pd.DataFrame([[1, 2], [3, 4]], index=['a', 'b'], columns=['x', 'y']) +>>> l = pd.DataFrame([[1, 2], [3, 4]], index=['a', 'b'], columns=['x', 'y']); l x y a 1 2 b 3 4 @@ -3267,13 +3270,14 @@ b 3 4 = .sort_values(col_key/s) # Sorts rows by passed column/s. Also `axis=1`. ``` +```python +.plot.line/area/bar/scatter(x=col_key, …) # `y=col_key/s`. Also hist/box(by=col_key). +plt.show() # Displays the plot. Also plt.savefig(). +``` + #### DataFrame — Merge, Join, Concat: ```python ->>> l = pd.DataFrame([[1, 2], [3, 4]], index=['a', 'b'], columns=['x', 'y']) - x y -a 1 2 -b 3 4 ->>> r = pd.DataFrame([[4, 5], [6, 7]], index=['b', 'c'], columns=['y', 'z']) +>>> r = pd.DataFrame([[4, 5], [6, 7]], index=['b', 'c'], columns=['y', 'z']); r y z b 4 5 c 6 7 @@ -3320,7 +3324,7 @@ c 6 7 * **All operations operate on columns by default. Pass `'axis=1'` to process the rows instead.** ```python ->>> df = pd.DataFrame([[1, 2], [3, 4]], index=['a', 'b'], columns=['x', 'y']) +>>> df = pd.DataFrame([[1, 2], [3, 4]], index=['a', 'b'], columns=['x', 'y']); df x y a 1 2 b 3 4 @@ -3347,42 +3351,44 @@ b 3 4 ``` * **Use `'[col_key_1, col_key_2][row_key]'` to get the fifth result's values.** -#### DataFrame — Plot, Encode, Decode: -```python -.plot.line/area/bar/scatter(x=col_key, …) # `y=col_key/s`. Also hist/box(by=col_key). -plt.show() # Displays the plot. Also plt.savefig(). -``` +#### DataFrame — Encode, Decode: ```python = pd.read_json/html('') # Run `$ pip3 install beautifulsoup4 lxml`. - = pd.read_csv('') # `header/index_col/dtype/parse_dates/…=`. + = pd.read_csv('') # `header/index_col/dtype/usecols/…=`. = pd.read_pickle/excel('') # Use `sheet_name=None` to get all Excel sheets. = pd.read_sql('', ) # SQLite3/SQLAlchemy connection (see #SQLite). ``` ```python = .to_dict('d/l/s/…') # Returns columns as dicts, lists or series. - = .to_json/html/csv/latex() # Saves output to file if path is passed. + = .to_json/html/csv/latex() # Saves output to a file if path is passed. .to_pickle/excel() # Run `$ pip3 install "pandas[excel]" odfpy`. .to_sql('', ) # Also `if_exists='fail/replace/append'`. ``` +* **Read\_csv() only parses dates of columns that were specified by 'parse\_dates' argument. It automatically tries to detect the format, but it can be helped with 'date\_format' or 'datefirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.** +* **If there's a single invalid date then it returns the whole column as a series of strings, unlike `' = pd.to_datetime(, errors="coerce")'`, which uses pd.NaT.** +* **To get specific attributes from a series of Timestamps use `'.dt.year/date/…'`.** ### GroupBy **Object that groups together rows of a dataframe based on the value of the passed column.** ```python >>> df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 6]], list('abc'), list('xyz')) ->>> df.groupby('z').get_group(6) +>>> gb = df.groupby('z'); gb.apply(print) + x y z +a 1 2 3 x y z b 4 5 6 c 7 8 6 ``` ```python - = .groupby(column_key/s) # Splits DF into groups based on passed column. + = .groupby(col_key/s) # Splits DF into groups based on passed column. = .apply() # Maps each group. Func can return DF, Sr or el. - = [column_key] # Single column GB. All operations return a Sr. + = .get_group() # Selects a group by grouping column's value. = .size() # A Sr of group sizes. Same keys as get_group(). + = [col_key] # Single column GB. All operations return a Sr. ``` #### GroupBy — Aggregate, Transform, Map: @@ -3393,37 +3399,20 @@ c 7 8 6 ``` ```python ->>> gb = df.groupby('z'); gb.apply(print) - x y z -a 1 2 3 - x y z -b 4 5 6 -c 7 8 6 -``` - -```text -+-----------------+-------------+-------------+-------------+---------------+ -| | 'sum' | 'rank' | ['rank'] | {'x': 'rank'} | -+-----------------+-------------+-------------+-------------+---------------+ -| gb.agg(…) | x y | | x y | | -| | z | x y | rank rank | x | -| | 3 1 2 | a 1 1 | a 1 1 | a 1 | -| | 6 11 13 | b 1 1 | b 1 1 | b 1 | -| | | c 2 2 | c 2 2 | c 2 | -+-----------------+-------------+-------------+-------------+---------------+ -| gb.transform(…) | x y | x y | | | -| | a 1 2 | a 1 1 | | | -| | b 11 13 | b 1 1 | | | -| | c 11 13 | c 2 2 | | | -+-----------------+-------------+-------------+-------------+---------------+ +>>> gb.sum() + x y +z +3 1 2 +6 11 13 ``` +* **Result has a named index that creates column `'z'` instead of `'index'` on reset_index().** ### Rolling **Object for rolling window calculations.** ```python = .rolling(win_size) # Also: `min_periods=None, center=False`. - = [column_key/s] # Or: .column_key + = [col_key/s] # Or: .col_key = .mean/sum/max() # Or: .apply/agg() ``` @@ -3431,11 +3420,21 @@ c 7 8 6 Plotly ------ ```python -# $ pip3 install pandas plotly kaleido -import pandas as pd, plotly.express as ex -
= ex.line(, x=, y=) # Or: ex.line(x=, y=) -
.update_layout(margin=dict(t=0, r=0, b=0, l=0), …) # `paper_bgcolor='rgb(0, 0, 0)'`. -
.write_html/json/image('') # Also
.show(). +# $ pip3 install plotly kaleido pandas +import plotly.express as px, pandas as pd +``` + +```python + = px.line(, x=col_key, y=col_key) # Or: px.line(x=, y=) +.update_layout(margin=dict(t=0, r=0, b=0, l=0)) # Also `paper_bgcolor='rgb(0, 0, 0)'`. +.write_html/json/image('') # Also .show(). +``` + +```python + = px.area/bar/box(, x=col_key, y=col_key) # Also `color=col_key`. + = px.scatter(, x=col_key, y=col_key) # Also `color/size/symbol=col_key`. + = px.scatter_3d(, x=col_key, y=col_key, …) # `z=col_key`. Also color/size/symbol. + = px.histogram(, x=col_key [, nbins=]) # Number of bins depends on DF size. ``` #### Displays a line chart of total coronavirus deaths per million grouped by continent: @@ -3454,7 +3453,7 @@ df = df.groupby(['Continent_Name', 'date']).sum().reset_index() df['Total Deaths per Million'] = df.total_deaths * 1e6 / df.population df = df[df.date > '2020-03-14'] df = df.rename({'date': 'Date', 'Continent_Name': 'Continent'}, axis='columns') -ex.line(df, x='Date', y='Total Deaths per Million', color='Continent').show() +px.line(df, x='Date', y='Total Deaths per Million', color='Continent').show() ``` #### Displays a multi-axis line chart of total coronavirus cases and changes in prices of Bitcoin, Dow Jones and gold: @@ -3467,20 +3466,23 @@ import pandas as pd, plotly.graph_objects as go def main(): covid, bitcoin, gold, dow = scrape_data() - display_data(wrangle_data(covid, bitcoin, gold, dow)) + df = wrangle_data(covid, bitcoin, gold, dow) + display_data(df) def scrape_data(): def get_covid_cases(): url = 'https://covid.ourworldindata.org/data/owid-covid-data.csv' df = pd.read_csv(url, usecols=['location', 'date', 'total_cases']) - return df[df.location == 'World'].set_index('date').total_cases + df = df[df.location == 'World'] + return df.set_index('date').total_cases def get_ticker(symbol): url = (f'https://query1.finance.yahoo.com/v7/finance/download/{symbol}?' 'period1=1579651200&period2=9999999999&interval=1d&events=history') df = pd.read_csv(url, usecols=['Date', 'Close']) return df.set_index('Date').Close out = get_covid_cases(), get_ticker('BTC-USD'), get_ticker('GC=F'), get_ticker('^DJI') - return map(pd.Series.rename, out, ['Total Cases', 'Bitcoin', 'Gold', 'Dow Jones']) + names = ['Total Cases', 'Bitcoin', 'Gold', 'Dow Jones'] + return map(pd.Series.rename, out, names) def wrangle_data(covid, bitcoin, gold, dow): df = pd.concat([bitcoin, gold, dow], axis=1) # Creates table by joining columns on dates. @@ -3588,3 +3590,4 @@ Index * **Only available in the [PDF](https://transactions.sendowl.com/products/78175486/4422834F/view).** * **Ctrl+F / ⌘F is usually sufficient.** * **Searching `'#'` on the [webpage](https://gto76.github.io/python-cheatsheet/) will limit the search to the titles.** +* **Click on the `'🔗'` symbol to get a link to specific section.** diff --git a/index.html b/index.html index 2d4c44002..a297efed2 100644 --- a/index.html +++ b/index.html @@ -35,18 +35,19 @@ <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="Comprehensive Python Cheatsheet"> <meta name="twitter:description" content="Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language."> - <meta name="twitter:image" content="https://gto76.github.io/python-cheatsheet/web/image_social_3.png"> + <meta name="twitter:image" content="https://gto76.github.io/python-cheatsheet/web/image_social_4.png"> <meta property="og:url" content="https://gto76.github.io/python-cheatsheet/"> <meta property="og:title" content="Comprehensive Python Cheatsheet"> <meta property="og:description" content="Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language."> <meta property="og:site_name" content="gto76.github.io"> - <meta property="og:image" content="https://gto76.github.io/python-cheatsheet/web/image_social_3.png"> + <meta property="og:image" content="https://gto76.github.io/python-cheatsheet/web/image_social_4.png"> + <meta property="og:type" content="article"> <meta itemprop="url" content="https://gto76.github.io/python-cheatsheet/"> <meta itemprop="name" content="Comprehensive Python Cheatsheet"> <meta itemprop="description" content="Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language."> - <meta itemprop="image" content="https://gto76.github.io/python-cheatsheet/web/image_social_3.png"> + <meta itemprop="image" content="https://gto76.github.io/python-cheatsheet/web/image_social_4.png"> <meta name="google-site-verification" content="w3rvuG0D1kUm_w20qsJecSEZh59Am8jK4eSPVU83e_M"> <meta name="viewport" id="viewport-meta"> @@ -54,12 +55,12 @@ <body> <header> - <aside>September 27, 2024</aside> + <aside>October 28, 2024</aside> <a href="https://gto76.github.io" rel="author">Jure Šorn</a> </header> <div><h1 id="comprehensivepythoncheatsheet">Comprehensive Python Cheatsheet</h1><p class="banner"><sup><a href="https://raw.githubusercontent.com/gto76/python-cheatsheet/main/README.md">Download text file</a>, <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">Buy PDF</a>, <a href="https://github.com/gto76/python-cheatsheet">Fork me on GitHub</a>, <a href="https://github.com/gto76/python-cheatsheet/wiki/Frequently-Asked-Questions">Check out FAQ</a> or <a href="index.html?theme=dark3">Switch to dark theme</a>. -</sup></p><p class="banner"><img src="web/image_888.jpeg" alt="Monty Python"></p><script> +</sup></p><p class="banner" style="margin-bottom: 20px; padding-bottom: 7px;"><img src="web/image_888.jpeg" alt="Monty Python"></p><script> // Changes the image and link to theme if URL ends with "index.html?theme=dark". if (window.location.search.search(/[?&]theme=dark/) !== -1) { @@ -79,7 +80,7 @@ } document.getElementsByClassName("banner")[1].firstChild.replaceWith(img_dark); } -</script><br><div><h2 id="toc"><a href="#toc" name="toc">#</a>Contents</h2><pre><code class="hljs bash" style="line-height: 1.327em;"><strong>ToC</strong> = { +</script><pre style="border-left: none;padding-left: 1.9px;"><code class="hljs bash" style="line-height: 1.327em;"><strong>ToC</strong> = { <strong><span class="hljs-string"><span class="hljs-string">'1. Collections'</span></span></strong>: [<a href="#list">List</a>, <a href="#dictionary">Dictionary</a>, <a href="#set">Set</a>, <a href="#tuple">Tuple</a>, <a href="#range">Range</a>, <a href="#enumerate">Enumerate</a>, <a href="#iterator">Iterator</a>, <a href="#generator">Generator</a>], <strong><span class="hljs-string"><span class="hljs-string">'2. Types'</span></span></strong>: [<a href="#type">Type</a>, <a href="#string">String</a>, <a href="#regex">Regular_Exp</a>, <a href="#format">Format</a>, <a href="#numbers">Numbers</a>, <a href="#combinatorics">Combinatorics</a>, <a href="#datetime">Datetime</a>], <strong><span class="hljs-string"><span class="hljs-string">'3. Syntax'</span></span></strong>: [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>], @@ -89,8 +90,7 @@ <strong><span class="hljs-string"><span class="hljs-string">'7. Libraries'</span></span></strong>: [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>, <a href="#consoleapp">Console_App</a>, <a href="#guiapp">GUI</a>, <a href="#scraping">Scraping</a>, <a href="#web">Web</a>, <a href="#profiling">Profile</a>], <strong><span class="hljs-string"><span class="hljs-string">'8. Multimedia'</span></span></strong>: [<a href="#numpy">NumPy</a>, <a href="#image">Image</a>, <a href="#animation">Animation</a>, <a href="#audio">Audio</a>, <a href="#synthesizer">Synthesizer</a>, <a href="#pygame">Pygame</a>, <a href="#pandas">Pandas</a>, <a href="#plotly">Plotly</a>] } -</code></pre></div></div> - +</code></pre></div> @@ -100,17 +100,19 @@ main() <span class="hljs-comment"># Runs `def main(): ...` function.</span> </code></pre></div> -<div><h2 id="list"><a href="#list" name="list">#</a>List</h2><pre><code class="python language-python hljs"><el> = <list>[index] <span class="hljs-comment"># First index is 0. Last -1. Allows assignments.</span> -<list> = <list>[<slice>] <span class="hljs-comment"># Or: <list>[from_inclusive : to_exclusive : ±step]</span> +<div><h2 id="list"><a href="#list" name="list">#</a>List</h2><pre><code class="python language-python hljs"><list> = [<el_1>, <el_2>, ...] <span class="hljs-comment"># Creates new list. Also list(<collection>).</span> </code></pre></div> -<pre><code class="python language-python hljs"><list>.append(<el>) <span class="hljs-comment"># Or: <list> += [<el>]</span> -<list>.extend(<collection>) <span class="hljs-comment"># Or: <list> += <collection></span> +<pre><code class="python language-python hljs"><el> = <list>[index] <span class="hljs-comment"># First index is 0. Last -1. Allows assignments.</span> +<list> = <list>[<slice>] <span class="hljs-comment"># Also <list>[from_inclusive : to_exclusive : ±step].</span> </code></pre> -<pre><code class="python language-python hljs"><list>.sort() <span class="hljs-comment"># Sorts in ascending order.</span> +<pre><code class="python language-python hljs"><list>.append(<el>) <span class="hljs-comment"># Appends element to the end. Also <list> += [<el>].</span> +<list>.extend(<collection>) <span class="hljs-comment"># Appends elements to the end. Also <list> += <coll>.</span> +</code></pre> +<pre><code class="python language-python hljs"><list>.sort() <span class="hljs-comment"># Sorts elements in ascending order.</span> <list>.reverse() <span class="hljs-comment"># Reverses the list in-place.</span> -<list> = sorted(<collection>) <span class="hljs-comment"># Returns a new sorted list.</span> -<iter> = reversed(<list>) <span class="hljs-comment"># Returns reversed iterator.</span> +<list> = sorted(<collection>) <span class="hljs-comment"># Returns new list with sorted elements.</span> +<iter> = reversed(<list>) <span class="hljs-comment"># Returns reversed iterator of elements.</span> </code></pre> <pre><code class="python language-python hljs">sum_of_elements = sum(<collection>) elementwise_sum = [sum(pair) <span class="hljs-keyword">for</span> pair <span class="hljs-keyword">in</span> zip(list_a, list_b)] @@ -132,11 +134,13 @@ <list>.remove(<el>) <span class="hljs-comment"># Removes first occurrence of the item or raises ValueError.</span> <list>.clear() <span class="hljs-comment"># Removes all items. Also works on dictionary and set.</span> </code></pre> -<div><h2 id="dictionary"><a href="#dictionary" name="dictionary">#</a>Dictionary</h2><pre><code class="python language-python hljs"><view> = <dict>.keys() <span class="hljs-comment"># Coll. of keys that reflects changes.</span> -<view> = <dict>.values() <span class="hljs-comment"># Coll. of values that reflects changes.</span> -<view> = <dict>.items() <span class="hljs-comment"># Coll. of key-value tuples that reflects chgs.</span> +<div><h2 id="dictionary"><a href="#dictionary" name="dictionary">#</a>Dictionary</h2><pre><code class="python language-python hljs"><dict> = {key_1: val_1, key_2: val_2, ...} <span class="hljs-comment"># Use `<dict>[key]` to get or set the value.</span> </code></pre></div> +<pre><code class="python language-python hljs"><view> = <dict>.keys() <span class="hljs-comment"># Coll. of keys that reflects changes.</span> +<view> = <dict>.values() <span class="hljs-comment"># Coll. of values that reflects changes.</span> +<view> = <dict>.items() <span class="hljs-comment"># Coll. of key-value tuples that reflects chgs.</span> +</code></pre> <pre><code class="python language-python hljs">value = <dict>.get(key, default=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Returns default if key is missing.</span> value = <dict>.setdefault(key, default=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Returns and writes default if key is missing.</span> <dict> = collections.defaultdict(<type>) <span class="hljs-comment"># Returns a dict with default value `<type>()`.</span> @@ -154,13 +158,11 @@ <div><h3 id="counter">Counter</h3><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> Counter <span class="hljs-meta">>>> </span>counter = Counter([<span class="hljs-string">'blue'</span>, <span class="hljs-string">'blue'</span>, <span class="hljs-string">'blue'</span>, <span class="hljs-string">'red'</span>, <span class="hljs-string">'red'</span>]) <span class="hljs-meta">>>> </span>counter[<span class="hljs-string">'yellow'</span>] += <span class="hljs-number">1</span> -<span class="hljs-meta">>>> </span>print(counter) -Counter({<span class="hljs-string">'blue'</span>: <span class="hljs-number">3</span>, <span class="hljs-string">'red'</span>: <span class="hljs-number">2</span>, <span class="hljs-string">'yellow'</span>: <span class="hljs-number">1</span>}) -<span class="hljs-meta">>>> </span>counter.most_common()[<span class="hljs-number">0</span>] -(<span class="hljs-string">'blue'</span>, <span class="hljs-number">3</span>) +<span class="hljs-meta">>>> </span>print(counter.most_common()) +[(<span class="hljs-string">'blue'</span>, <span class="hljs-number">3</span>), (<span class="hljs-string">'red'</span>, <span class="hljs-number">2</span>), (<span class="hljs-string">'yellow'</span>, <span class="hljs-number">1</span>)] </code></pre></div> -<div><h2 id="set"><a href="#set" name="set">#</a>Set</h2><pre><code class="python language-python hljs"><set> = set() <span class="hljs-comment"># `{}` returns a dictionary.</span> +<div><h2 id="set"><a href="#set" name="set">#</a>Set</h2><pre><code class="python language-python hljs"><set> = {<el_1>, <el_2>, ...} <span class="hljs-comment"># Use `set()` for empty set.</span> </code></pre></div> <pre><code class="python language-python hljs"><set>.add(<el>) <span class="hljs-comment"># Or: <set> |= {<el>}</span> @@ -358,7 +360,7 @@ <ul> <li><strong>By default, decimal characters, alphanumerics and whitespaces from all alphabets are matched unless <code class="python hljs"><span class="hljs-string">'flags=re.ASCII'</span></code> argument is used.</strong></li> -<li><strong>It restricts special sequence matches to <code class="python hljs"><span class="hljs-string">'[\x00-\x7f]'</span></code> (the first 128 characters) and also prevents <code class="python hljs"><span class="hljs-string">'\s'</span></code> from accepting <code class="python hljs"><span class="hljs-string">'[\x1c-\x1f]'</span></code> (the so-called separator characters).</strong></li> +<li><strong>It restricts special sequence matches to <code class="python hljs"><span class="hljs-string">'[\x00-\x7f]'</span></code> (the first 128 characters) and also prevents <code class="python hljs"><span class="hljs-string">'\s'</span></code> from accepting <code class="python hljs"><span class="hljs-string">'[\x1c-\x1f]'</span></code> (file, table, row, and field separators).</strong></li> <li><strong>Use a capital letter for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).</strong></li> </ul> <div><h2 id="format"><a href="#format" name="format">#</a>Format</h2><pre><code class="python hljs"><str> = <span class="hljs-string">f'<span class="hljs-subst">{<el_1>}</span>, <span class="hljs-subst">{<el_2>}</span>'</span> <span class="hljs-comment"># Curly brackets can also contain expressions.</span> @@ -380,7 +382,7 @@ </code></pre></div> <ul> -<li><strong>Objects are rendered using <code class="python hljs"><span class="hljs-string">'format(<el>, <options>)'</span></code>.</strong></li> +<li><strong>Objects are rendered using <code class="python hljs"><span class="hljs-string">'format(<el>, "<options>")'</span></code>.</strong></li> <li><strong>Options can be generated dynamically: <code class="python hljs"><span class="hljs-string">f'<span class="hljs-subst">{<el>:{<str/int>}</span>[…]}'</span></code>.</strong></li> <li><strong>Adding <code class="python hljs"><span class="hljs-string">'='</span></code> to the expression prepends it to the output: <code class="python hljs"><span class="hljs-string">f'<span class="hljs-subst">{<span class="hljs-number">1</span>+<span class="hljs-number">1</span>=}</span>'</span></code> returns <code class="python hljs"><span class="hljs-string">'1+1=2'</span></code>.</strong></li> <li><strong>Adding <code class="python hljs"><span class="hljs-string">'!r'</span></code> to the expression converts object to string by calling its <a href="#class">repr()</a> method.</strong></li> @@ -515,7 +517,7 @@ </code></pre> <div><h2 id="datetime"><a href="#datetime" name="datetime">#</a>Datetime</h2><p><strong>Provides 'date', 'time', 'datetime' and 'timedelta' classes. All are immutable and hashable.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install python-dateutil</span> <span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> date, time, datetime, timedelta, timezone -<span class="hljs-keyword">from</span> dateutil.tz <span class="hljs-keyword">import</span> tzlocal, gettz +<span class="hljs-keyword">import</span> zoneinfo, dateutil.tz </code></pre></div> @@ -527,7 +529,7 @@ <ul> <li><strong>Aware <code class="apache hljs"><span class="hljs-section"><a></span></code> time and datetime objects have defined timezone, while naive <code class="apache hljs"><span class="hljs-section"><n></span></code> don't. If object is naive, it is presumed to be in the system's timezone!</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'fold=1'</span></code> means the second pass in case of time jumping back for one hour.</strong></li> -<li><strong>Timedelta normalizes arguments to ±days, seconds (< 86 400) and microseconds (< 1M).</strong></li> +<li><strong>Timedelta normalizes arguments to ±days, seconds (< 86 400) and microseconds (< 1M). Its str() method returns <code class="python hljs"><span class="hljs-string">'[±D, ]H:MM:SS[.…]'</span></code> and total_seconds() a float of all seconds.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'<D/DT>.weekday()'</span></code> to get the day of the week as an int, with Monday being 0.</strong></li> </ul> <div><h3 id="now">Now</h3><pre><code class="python language-python hljs"><D/DTn> = D/DT.today() <span class="hljs-comment"># Current local date or naive DT. Also DT.now().</span> @@ -539,15 +541,15 @@ </ul> <div><h3 id="timezone">Timezone</h3><pre><code class="python language-python apache hljs"><tzinfo> = timezone.utc <span class="hljs-comment"># London without daylight saving time (DST).</span> <tzinfo> = timezone(<timedelta>) <span class="hljs-comment"># Timezone with fixed offset from UTC.</span> -<tzinfo> = tzlocal() <span class="hljs-comment"># Local tz with dynamic offset. Also gettz().</span> -<tzinfo> = gettz(<span class="hljs-string">'<Continent>/<City>'</span>) <span class="hljs-comment"># 'Continent/City_Name' timezone or None.</span> +<tzinfo> = dateutil.tz.tzlocal() <span class="hljs-comment"># Local timezone with dynamic offset from UTC.</span> +<tzinfo> = zoneinfo.ZoneInfo(<span class="hljs-string">'<iana_key>'</span>) <span class="hljs-comment"># 'Continent/City_Name' zone with dynamic offset.</span> <DTa> = <DT>.astimezone([<tzinfo>]) <span class="hljs-comment"># Converts DT to the passed or local fixed zone.</span> <Ta/DTa> = <T/DT>.replace(tzinfo=<tzinfo>) <span class="hljs-comment"># Changes object's timezone without conversion.</span> </code></pre></div> <ul> -<li><strong>Timezones returned by tzlocal(), gettz(), and implicit local timezone of naive objects have offsets that vary through time due to DST and historical changes of the zone's base offset.</strong></li> -<li><strong>Standard library's zoneinfo.ZoneInfo() can be used instead of gettz() on Python 3.9 and later. It requires 'tzdata' package on Windows. It doesn't return local tz if arg. is omitted.</strong></li> +<li><strong>Timezones returned by tzlocal(), ZoneInfo() and implicit local timezone of naive objects have offsets that vary through time due to DST and historical changes of the base offset.</strong></li> +<li><strong>To get ZoneInfo() to work on Windows run <code class="python hljs"><span class="hljs-string">'> pip3 install tzdata'</span></code>.</strong></li> </ul> <div><h3 id="encode">Encode</h3><pre><code class="python language-python apache hljs"><D/T/DT> = D/T/DT.fromisoformat(<str>) <span class="hljs-comment"># Object from ISO string. Raises ValueError.</span> <DT> = DT.strptime(<str>, <span class="hljs-string">'<format>'</span>) <span class="hljs-comment"># Datetime from str, according to format.</span> @@ -582,7 +584,7 @@ <TD> = <DTa> - <DTa> <span class="hljs-comment"># Ignores jumps if they share tzinfo object.</span> <D/DT> = <D/DT> ± <TD> <span class="hljs-comment"># Returned datetime can fall into missing hour.</span> <TD> = <TD> * <float> <span class="hljs-comment"># Also: <TD> = abs(<TD>) and <TD> = <TD> ±% <TD>.</span> -<float> = <TD> / <TD> <span class="hljs-comment"># How many hours/weeks/years are in TD. Also //.</span> +<float> = <TD> / <TD> <span class="hljs-comment"># E.g. how many hours are in TD. Also //, divmod().</span> </code></pre></div> <div><h2 id="arguments"><a href="#arguments" name="arguments">#</a>Arguments</h2><div><h3 id="insidefunctioncall">Inside Function Call</h3><pre><code class="python language-python hljs">func(<positional_args>) <span class="hljs-comment"># func(0, 0)</span> @@ -637,7 +639,7 @@ <div><h3 id="otheruses">Other Uses</h3><pre><code class="python language-python hljs"><list> = [*<coll.> [, ...]] <span class="hljs-comment"># Or: list(<collection>) [+ ...]</span> <tuple> = (*<coll.>, [...]) <span class="hljs-comment"># Or: tuple(<collection>) [+ ...]</span> <set> = {*<coll.> [, ...]} <span class="hljs-comment"># Or: set(<collection>) [| ...]</span> -<dict> = {**<dict> [, ...]} <span class="hljs-comment"># Or: <dict> | ... (since 3.9)</span> +<dict> = {**<dict> [, ...]} <span class="hljs-comment"># Or: <dict> | ...</span> </code></pre></div> <pre><code class="python language-python hljs">head, *body, tail = <coll.> <span class="hljs-comment"># Head or tail can be omitted.</span> @@ -724,7 +726,7 @@ <span class="hljs-number">30</span> </code></pre> <ul> -<li><strong>Partial is also useful in cases when function needs to be passed as an argument because it enables us to set its arguments beforehand.</strong></li> +<li><strong>Partial is also useful in cases when a function needs to be passed as an argument because it enables us to set its arguments beforehand.</strong></li> <li><strong>A few examples being: <code class="python hljs"><span class="hljs-string">'defaultdict(<func>)'</span></code>, <code class="python hljs"><span class="hljs-string">'iter(<func>, to_exc)'</span></code> and dataclass's <code class="python hljs"><span class="hljs-string">'field(default_factory=<func>)'</span></code>.</strong></li> </ul> <div><h3 id="nonlocal">Non-Local</h3><p><strong>If variable is being assigned to anywhere in the scope, it is regarded as a local variable, unless it is declared as a 'global' or a 'nonlocal'.</strong></p><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_counter</span><span class="hljs-params">()</span>:</span> @@ -766,20 +768,18 @@ <ul> -<li><strong>Wraps is a helper decorator that copies the metadata of the passed function (func) to the function it is wrapping (out).</strong></li> -<li><strong>Without it, <code class="python hljs"><span class="hljs-string">'add.__name__'</span></code> would return <code class="python hljs"><span class="hljs-string">'out'</span></code>.</strong></li> +<li><strong>Wraps is a helper decorator that copies the metadata of the passed function (func) to the function it is wrapping (out). Without it, <code class="python hljs"><span class="hljs-string">'add.__name__'</span></code> would return <code class="python hljs"><span class="hljs-string">'out'</span></code>.</strong></li> </ul> -<div><h3 id="lrucache">LRU Cache</h3><p><strong>Decorator that caches function's return values. All function's arguments must be hashable.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> lru_cache +<div><h3 id="cache">Cache</h3><p><strong>Decorator that caches function's return values. All function's arguments must be hashable.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> cache -<span class="hljs-meta">@lru_cache(maxsize=None)</span> +<span class="hljs-meta">@cache</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fib</span><span class="hljs-params">(n)</span>:</span> - <span class="hljs-keyword">return</span> n <span class="hljs-keyword">if</span> n < <span class="hljs-number">2</span> <span class="hljs-keyword">else</span> fib(n-<span class="hljs-number">2</span>) + fib(n-<span class="hljs-number">1</span>) -</code></pre></div> + <span class="hljs-keyword">return</span> n <span class="hljs-keyword">if</span> n < <span class="hljs-number">2</span> <span class="hljs-keyword">else</span> fib(n-<span class="hljs-number">2</span>) + fib(n-<span class="hljs-number">1</span>)</code></pre></div> <ul> -<li><strong>Default size of the cache is 128 values. Passing <code class="python hljs"><span class="hljs-string">'maxsize=None'</span></code> makes it unbounded.</strong></li> -<li><strong>CPython interpreter limits recursion depth to 3000 by default. To increase it use <code class="python hljs"><span class="hljs-string">'sys.setrecursionlimit(<int>)'</span></code>.</strong></li> +<li><strong>Potential problem with cache is that it can grow indefinitely. To clear its stored values run <code class="python hljs"><span class="hljs-string">'fib.cache_clear()'</span></code>, or use <code class="python hljs"><span class="hljs-string">'@lru_cache(maxsize=<int>)'</span></code> decorator instead.</strong></li> +<li><strong>CPython interpreter limits recursion depth to 3000 by default. To increase it run <code class="python hljs"><span class="hljs-string">'sys.setrecursionlimit(<int>)'</span></code>.</strong></li> </ul> <div><h3 id="parametrizeddecorator">Parametrized Decorator</h3><p><strong>A decorator that accepts arguments and returns a normal decorator that accepts a function.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps @@ -1000,7 +1000,7 @@ <li><strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong></li> </ul><div><h3 id="callable">Callable</h3><ul> <li><strong>All functions and classes have a call() method, hence are callable.</strong></li> -<li><strong>To check if object is callable use <code class="python hljs"><span class="hljs-string">'callable(<obj>)'</span></code>, <code class="python hljs"><span class="hljs-string">'isinstance(<obj>, collections.abc.Callable)'</span></code>, or <code class="python hljs"><span class="hljs-string">'isinstance(<obj>, typing.Callable)'</span></code>.</strong></li> +<li><strong>Use <code class="python hljs"><span class="hljs-string">'callable(<obj>)'</span></code> or <code class="python hljs"><span class="hljs-string">'isinstance(<obj>, collections.abc.Callable)'</span></code> to check if object is callable.</strong></li> <li><strong>When this cheatsheet uses <code class="python hljs"><span class="hljs-string">'<function>'</span></code> as an argument, it means <code class="python hljs"><span class="hljs-string">'<callable>'</span></code>.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self)</span>:</span> @@ -1063,7 +1063,7 @@ <div><h3 id="collection">Collection</h3><ul> <li><strong>Only required methods are iter() and len(). Len() should return the number of items.</strong></li> <li><strong>This cheatsheet actually means <code class="python hljs"><span class="hljs-string">'<iterable>'</span></code> when it uses <code class="python hljs"><span class="hljs-string">'<collection>'</span></code>.</strong></li> -<li><strong>I chose not to use the name 'iterable' because it sounds scarier and more vague than 'collection'. The only drawback of this decision is that the reader could think a certain function doesn't accept iterators when it does, since iterators are the only built-in objects that are iterable but are not collections.</strong></li> +<li><strong>I chose not to use the name 'iterable' because it sounds scarier and more vague than 'collection'. The main drawback of this decision is that the reader could think a certain function doesn't accept iterators when it does, since iterators are the only built-in objects that are iterable but are not collections.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyCollection</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span> self.a = a @@ -1080,7 +1080,7 @@ <li><strong>Only required methods are getitem() and len().</strong></li> <li><strong>Getitem() should return an item at the passed index or raise IndexError.</strong></li> <li><strong>Iter() and contains() automatically work on any object that has getitem() defined.</strong></li> -<li><strong>Reversed() automatically works on any object that has getitem() and len() defined.</strong></li> +<li><strong>Reversed() automatically works on any object that has getitem() and len() defined. It returns reversed iterator of object's items.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MySequence</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a)</span>:</span> self.a = a @@ -1098,7 +1098,7 @@ <div><h4 id="discrepanciesbetweenglossarydefinitionsandabstractbaseclasses">Discrepancies between glossary definitions and abstract base classes:</h4><ul> -<li><strong>Glossary defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.</strong></li> +<li><strong>Glossary on Python's website defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.</strong></li> <li><strong>Passing ABC Iterable to isinstance() or issubclass() checks whether object/class has method iter(), while ABC Collection checks for iter(), contains() and len().</strong></li> </ul></div> @@ -1133,8 +1133,7 @@ <ul> <li><strong>Method iter() is required for <code class="python hljs"><span class="hljs-string">'isinstance(<obj>, abc.Iterable)'</span></code> to return True, however any object with getitem() will work with any code expecting an iterable.</strong></li> -<li><strong>Other extendable ABCs: MutableSequence, Set, MutableSet, Mapping, MutableMapping.</strong></li> -<li><strong>Names of their required methods are stored in <code class="python hljs"><span class="hljs-string">'<abc>.__abstractmethods__'</span></code>.</strong></li> +<li><strong>MutableSequence, Set, MutableSet, Mapping and MutableMapping ABCs are also extendable. Use <code class="python hljs"><span class="hljs-string">'<abc>.__abstractmethods__'</span></code> to get names of required methods.</strong></li> </ul> <div><h2 id="enum"><a href="#enum" name="enum">#</a>Enum</h2><p><strong>Class of named constants called members.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> enum <span class="hljs-keyword">import</span> Enum, auto </code></pre></div> @@ -1314,8 +1313,8 @@ p.add_argument(<span class="hljs-string">'<name>'</span>, type=<type>, nargs=<span class="hljs-number">1</span>) <span class="hljs-comment"># Mandatory first argument.</span> p.add_argument(<span class="hljs-string">'<name>'</span>, type=<type>, nargs=<span class="hljs-string">'+'</span>) <span class="hljs-comment"># Mandatory remaining args.</span> p.add_argument(<span class="hljs-string">'<name>'</span>, type=<type>, nargs=<span class="hljs-string">'?/*'</span>) <span class="hljs-comment"># Optional argument/s.</span> -<args> = p.parse_args() <span class="hljs-comment"># Exits on parsing error.</span> -<obj> = <args>.<name> <span class="hljs-comment"># Returns `<type>(<arg>)`.</span> +args = p.parse_args() <span class="hljs-comment"># Exits on parsing error.</span> +<obj> = args.<name> <span class="hljs-comment"># Returns `<type>(<arg>)`.</span> </code></pre></div> <ul> @@ -1340,7 +1339,7 @@ <li><strong><code class="python hljs"><span class="hljs-string">'w+'</span></code> - Read and write. Deletes existing contents.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'r+'</span></code> - Read and write from the start.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'a+'</span></code> - Read and write from the end.</strong></li> -<li><strong><code class="python hljs"><span class="hljs-string">'b'</span></code> - Binary mode (<code class="python hljs"><span class="hljs-string">'br'</span></code>, <code class="python hljs"><span class="hljs-string">'bw'</span></code>, <code class="python hljs"><span class="hljs-string">'bx'</span></code>, …)</strong></li> +<li><strong><code class="python hljs"><span class="hljs-string">'b'</span></code> - Binary mode (<code class="python hljs"><span class="hljs-string">'rb'</span></code>, <code class="python hljs"><span class="hljs-string">'wb'</span></code>, <code class="python hljs"><span class="hljs-string">'xb'</span></code>, …)</strong></li> </ul><div><h3 id="exceptions-1">Exceptions</h3><ul> <li><strong><code class="python hljs"><span class="hljs-string">'FileNotFoundError'</span></code> can be raised when reading with <code class="python hljs"><span class="hljs-string">'r'</span></code> or <code class="python hljs"><span class="hljs-string">'r+'</span></code>.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'FileExistsError'</span></code> can be raised when writing with <code class="python hljs"><span class="hljs-string">'x'</span></code>.</strong></li> @@ -1349,7 +1348,7 @@ </ul><div><h3 id="fileobject">File Object</h3><pre><code class="python language-python hljs"><file>.seek(<span class="hljs-number">0</span>) <span class="hljs-comment"># Moves to the start of the file.</span> <file>.seek(offset) <span class="hljs-comment"># Moves 'offset' chars/bytes from the start.</span> <file>.seek(<span class="hljs-number">0</span>, <span class="hljs-number">2</span>) <span class="hljs-comment"># Moves to the end of the file.</span> -<bin_file>.seek(±offset, <anchor>) <span class="hljs-comment"># Anchor: 0 start, 1 current position, 2 end.</span> +<bin_file>.seek(±offset, origin) <span class="hljs-comment"># Origin: 0 start, 1 current position, 2 end.</span> </code></pre></div></div></div> @@ -1401,22 +1400,22 @@ <pre><code class="python language-python hljs"><stat> = os.stat(<path>) <span class="hljs-comment"># Or: <DirEntry/Path>.stat()</span> <num> = <stat>.st_mtime/st_size/… <span class="hljs-comment"># Modification time, size in bytes, ...</span> </code></pre> -<div><h3 id="direntry">DirEntry</h3><p><strong>Unlike listdir(), scandir() returns DirEntry objects that cache isfile, isdir and on Windows also stat information, thus significantly increasing the performance of code that requires it.</strong></p><pre><code class="python language-python hljs"><iter> = os.scandir(path=<span class="hljs-string">'.'</span>) <span class="hljs-comment"># Returns DirEntry objects located at the path.</span> +<div><h3 id="direntry">DirEntry</h3><p><strong>Unlike listdir(), scandir() returns DirEntry objects that cache isfile, isdir, and on Windows also stat information, thus significantly increasing the performance of code that requires it.</strong></p><pre><code class="python language-python hljs"><iter> = os.scandir(path=<span class="hljs-string">'.'</span>) <span class="hljs-comment"># Returns DirEntry objects located at the path.</span> <str> = <DirEntry>.path <span class="hljs-comment"># Returns the whole path as a string.</span> <str> = <DirEntry>.name <span class="hljs-comment"># Returns final component as a string.</span> <file> = open(<DirEntry>) <span class="hljs-comment"># Opens the file and returns a file object.</span> </code></pre></div> -<div><h3 id="pathobject">Path Object</h3><pre><code class="python language-python hljs"><Path> = Path(<path> [, ...]) <span class="hljs-comment"># Accepts strings, Paths and DirEntry objects.</span> +<div><h3 id="pathobject">Path Object</h3><pre><code class="python language-python hljs"><Path> = Path(<path> [, ...]) <span class="hljs-comment"># Accepts strings, Paths, and DirEntry objects.</span> <Path> = <path> / <path> [/ ...] <span class="hljs-comment"># First or second path must be a Path object.</span> <Path> = <Path>.resolve() <span class="hljs-comment"># Returns absolute path with resolved symlinks.</span> </code></pre></div> -<pre><code class="python language-python hljs"><Path> = Path() <span class="hljs-comment"># Returns relative cwd. Also Path('.').</span> -<Path> = Path.cwd() <span class="hljs-comment"># Returns absolute cwd. Also Path().resolve().</span> +<pre><code class="python language-python hljs"><Path> = Path() <span class="hljs-comment"># Returns relative CWD. Also Path('.').</span> +<Path> = Path.cwd() <span class="hljs-comment"># Returns absolute CWD. Also Path().resolve().</span> <Path> = Path.home() <span class="hljs-comment"># Returns user's home directory (absolute).</span> -<Path> = Path(__file__).resolve() <span class="hljs-comment"># Returns script's path if cwd wasn't changed.</span> +<Path> = Path(__file__).resolve() <span class="hljs-comment"># Returns script's path if CWD wasn't changed.</span> </code></pre> <pre><code class="python language-python hljs"><Path> = <Path>.parent <span class="hljs-comment"># Returns Path without the final component.</span> <str> = <Path>.name <span class="hljs-comment"># Returns final component as a string.</span> @@ -1524,7 +1523,7 @@ <ul> <li><strong>File must be opened with a <code class="python hljs"><span class="hljs-string">'newline=""'</span></code> argument, or '\r' will be added in front of every '\n' on platforms that use '\r\n' line endings!</strong></li> -<li><strong>Open existing file with <code class="python hljs"><span class="hljs-string">'mode="w"'</span></code> to overwrite it or <code class="python hljs"><span class="hljs-string">'mode="a"'</span></code> to append to it.</strong></li> +<li><strong>Open existing file with <code class="python hljs"><span class="hljs-string">'mode="a"'</span></code> to append to it or <code class="python hljs"><span class="hljs-string">'mode="w"'</span></code> to overwrite it.</strong></li> </ul> <div><h3 id="parameters">Parameters</h3><ul> <li><strong><code class="python hljs"><span class="hljs-string">'dialect'</span></code> - Master parameter that sets the default values. String or a 'csv.Dialect' object.</strong></li> @@ -1550,14 +1549,14 @@ -<div><h3 id="readrowsfromcsvfile">Read Rows from CSV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_csv_file</span><span class="hljs-params">(filename, dialect=<span class="hljs-string">'excel'</span>, **params)</span>:</span> +<div><h3 id="readrowsfromcsvfile">Read Rows from CSV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_csv_file</span><span class="hljs-params">(filename, **csv_params)</span>:</span> <span class="hljs-keyword">with</span> open(filename, encoding=<span class="hljs-string">'utf-8'</span>, newline=<span class="hljs-string">''</span>) <span class="hljs-keyword">as</span> file: - <span class="hljs-keyword">return</span> list(csv.reader(file, dialect, **params)) + <span class="hljs-keyword">return</span> list(csv.reader(file, **csv_params)) </code></pre></div> -<div><h3 id="writerowstocsvfile">Write Rows to CSV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_csv_file</span><span class="hljs-params">(filename, rows, mode=<span class="hljs-string">'w'</span>, dialect=<span class="hljs-string">'excel'</span>, **params)</span>:</span> +<div><h3 id="writerowstocsvfile">Write Rows to CSV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_csv_file</span><span class="hljs-params">(filename, rows, mode=<span class="hljs-string">'w'</span>, **csv_params)</span>:</span> <span class="hljs-keyword">with</span> open(filename, mode, encoding=<span class="hljs-string">'utf-8'</span>, newline=<span class="hljs-string">''</span>) <span class="hljs-keyword">as</span> file: - writer = csv.writer(file, dialect, **params) + writer = csv.writer(file, **csv_params) writer.writerows(rows) </code></pre></div> @@ -1607,14 +1606,14 @@ </code></pre></div> -<pre><code class="text language-text">┏━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ -┃ Dialect │ pip3 install │ import │ Dependencies ┃ -┠────────────┼──────────────┼──────────┼──────────────────────────────────┨ -┃ mysql │ mysqlclient │ MySQLdb │ www.pypi.org/project/mysqlclient ┃ -┃ postgresql │ psycopg2 │ psycopg2 │ www.pypi.org/project/psycopg2 ┃ -┃ mssql │ pyodbc │ pyodbc │ www.pypi.org/project/pyodbc ┃ -┃ oracle │ oracledb │ oracledb │ www.pypi.org/project/oracledb ┃ -┗━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ +<pre><code class="text language-text">┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ +┃ Dialect │ pip3 install │ Dependencies ┃ +┠─────────────────┼──────────────┼──────────────────────────────────┨ +┃ mysql │ mysqlclient │ www.pypi.org/project/mysqlclient ┃ +┃ postgresql │ psycopg2 │ www.pypi.org/project/psycopg2 ┃ +┃ mssql │ pyodbc │ www.pypi.org/project/pyodbc ┃ +┃ oracle+oracledb │ oracledb │ www.pypi.org/project/oracledb ┃ +┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛ </code></pre> <div><h2 id="bytes"><a href="#bytes" name="bytes">#</a>Bytes</h2><p><strong>A bytes object is an immutable sequence of single bytes. Mutable version is called bytearray.</strong></p><pre><code class="python language-python hljs"><bytes> = <span class="hljs-string">b'<str>'</span> <span class="hljs-comment"># Only accepts ASCII characters and \x00-\xff.</span> <int> = <bytes>[index] <span class="hljs-comment"># Returns an int in range from 0 to 255.</span> @@ -1698,14 +1697,14 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <file>.write(<array>) <span class="hljs-comment"># Writes array's memory to binary file.</span> </code></pre> <div><h2 id="memoryview"><a href="#memoryview" name="memoryview">#</a>Memory View</h2><p><strong>A sequence object that points to the memory of another bytes-like object. Each element can reference a single or multiple consecutive bytes, depending on format. Order and number of elements can be changed with slicing.</strong></p><pre><code class="python language-python hljs"><mview> = memoryview(<bytes/bytearray/array>) <span class="hljs-comment"># Immutable if bytes is passed, else mutable.</span> -<obj> = <mview>[index] <span class="hljs-comment"># Returns int/float. Bytes if format is 'c'.</span> +<obj> = <mview>[index] <span class="hljs-comment"># Returns int or float. Bytes if format is 'c'.</span> <mview> = <mview>[<slice>] <span class="hljs-comment"># Returns memoryview with rearranged elements.</span> <mview> = <mview>.cast(<span class="hljs-string">'<typecode>'</span>) <span class="hljs-comment"># Only works between B/b/c and other types.</span> <mview>.release() <span class="hljs-comment"># Releases memory buffer of the base object.</span> </code></pre></div> -<pre><code class="python language-python hljs"><bytes> = bytes(<mview>) <span class="hljs-comment"># Returns a new bytes object.</span> +<pre><code class="python language-python hljs"><bytes> = bytes(<mview>) <span class="hljs-comment"># Returns a new bytes object. Also bytearray().</span> <bytes> = <bytes>.join(<coll_of_mviews>) <span class="hljs-comment"># Joins memoryviews using bytes as a separator.</span> <array> = array(<span class="hljs-string">'<typecode>'</span>, <mview>) <span class="hljs-comment"># Treats memoryview as a sequence of numbers.</span> <file>.write(<mview>) <span class="hljs-comment"># Writes `bytes(<mview>)` to the binary file.</span> @@ -1771,12 +1770,15 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <iter> = as_completed(<coll_of_Futures>) <span class="hljs-comment"># `next(<iter>)` returns next completed Future.</span> </code></pre> <ul> -<li><strong>Map() and as_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called/blocking. Map() times from original call and as_completed() from first call to next(). As_completed() fails if next() is called too late, even if all threads have finished.</strong></li> +<li><strong>Map() and as_completed() also accept 'timeout'. It causes futures.TimeoutError when next() is called/blocking. Map() times from original call and as_completed() from first call to next(). As_completed() fails if next() is called too late, even if all threads are done.</strong></li> <li><strong>Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.</strong></li> <li><strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be <a href="#pickle">pickable</a>, queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via <code class="python hljs"><span class="hljs-string">'if __name__ == "__main__": ...'</span></code>.</strong></li> </ul> <div><h2 id="operator"><a href="#operator" name="operator">#</a>Operator</h2><p><strong>Module of functions that provide the functionality of operators. Functions are ordered by operator precedence, starting with least binding.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> operator <span class="hljs-keyword">as</span> op -<bool> = op.not_(<obj>) <span class="hljs-comment"># or, and, not (or/and missing)</span> +</code></pre></div> + + +<pre><code class="python language-python hljs"><bool> = op.not_(<obj>) <span class="hljs-comment"># or, and, not (or/and missing)</span> <bool> = op.eq/ne/lt/ge/is_/is_not/contains(<obj>, <obj>) <span class="hljs-comment"># ==, !=, <, >=, is, is not, in</span> <obj> = op.or_/xor/and_(<int/set>, <int/set>) <span class="hljs-comment"># |, ^, &</span> <int> = op.lshift/rshift(<int>, <int>) <span class="hljs-comment"># <<, >></span> @@ -1784,9 +1786,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <num> = op.neg/invert(<num>) <span class="hljs-comment"># -, ~</span> <num> = op.pow(<num>, <num>) <span class="hljs-comment"># **</span> <func> = op.itemgetter/attrgetter/methodcaller(<obj> [, ...]) <span class="hljs-comment"># [index/key], .name, .name([…])</span> -</code></pre></div> - - +</code></pre> <pre><code class="python language-python hljs">elementwise_sum = map(op.add, list_a, list_b) sorted_by_second = sorted(<coll.>, key=op.itemgetter(<span class="hljs-number">1</span>)) sorted_by_both = sorted(<coll.>, key=op.itemgetter(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>)) @@ -1805,8 +1805,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <div><h3 id="patterns">Patterns</h3><pre><code class="python language-python hljs"><value_pattern> = <span class="hljs-number">1</span>/<span class="hljs-string">'abc'</span>/<span class="hljs-keyword">True</span>/<span class="hljs-keyword">None</span>/math.pi <span class="hljs-comment"># Matches the literal or a dotted name.</span> -<class_pattern> = <type>() <span class="hljs-comment"># Matches any object of that type.</span> -<wildcard_patt> = _ <span class="hljs-comment"># Matches any object.</span> +<class_pattern> = <type>() <span class="hljs-comment"># Matches any object of that type (or ABC).</span> +<wildcard_patt> = _ <span class="hljs-comment"># Matches any object. Useful in last case.</span> <capture_patt> = <name> <span class="hljs-comment"># Matches any object and binds it to name.</span> <as_pattern> = <pattern> <span class="hljs-keyword">as</span> <name> <span class="hljs-comment"># Binds match to name. Also <type>(<name>).</span> <or_pattern> = <pattern> | <pattern> [| ...] <span class="hljs-comment"># Matches any of the patterns.</span> @@ -1818,7 +1818,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <ul> <li><strong>Sequence pattern can also be written as a tuple.</strong></li> <li><strong>Use <code class="python hljs"><span class="hljs-string">'*<name>'</span></code> and <code class="python hljs"><span class="hljs-string">'**<name>'</span></code> in sequence/mapping patterns to bind remaining items.</strong></li> -<li><strong>Sequence pattern must match all items, while mapping pattern does not.</strong></li> +<li><strong>Sequence pattern must match all items of the collection, while mapping pattern does not.</strong></li> <li><strong>Patterns can be surrounded with brackets to override precedence (<code class="python hljs"><span class="hljs-string">'|'</span></code> > <code class="python hljs"><span class="hljs-string">'as'</span></code> > <code class="python hljs"><span class="hljs-string">','</span></code>).</strong></li> <li><strong>Built-in types allow a single positional pattern that is matched against the entire object.</strong></li> <li><strong>All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement.</strong></li> @@ -1826,11 +1826,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <div><h3 id="example-2">Example</h3><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path <span class="hljs-meta">>>> </span><span class="hljs-keyword">match</span> Path(<span class="hljs-string">'/home/gto/python-cheatsheet/README.md'</span>): <span class="hljs-meta">... </span> <span class="hljs-keyword">case</span> Path( -<span class="hljs-meta">... </span> parts=[<span class="hljs-string">'/'</span>, <span class="hljs-string">'home'</span>, user, *_], -<span class="hljs-meta">... </span> stem=stem, -<span class="hljs-meta">... </span> suffix=(<span class="hljs-string">'.md'</span> | <span class="hljs-string">'.txt'</span>) <span class="hljs-keyword">as</span> suffix -<span class="hljs-meta">... </span> ) <span class="hljs-keyword">if</span> stem.lower() == <span class="hljs-string">'readme'</span>: -<span class="hljs-meta">... </span> print(<span class="hljs-string">f'<span class="hljs-subst">{stem}</span><span class="hljs-subst">{suffix}</span> is a readme file that belongs to user <span class="hljs-subst">{user}</span>.'</span>) +<span class="hljs-meta">... </span> parts=[<span class="hljs-string">'/'</span>, <span class="hljs-string">'home'</span>, user, *_] +<span class="hljs-meta">... </span> ) <span class="hljs-keyword">as</span> p <span class="hljs-keyword">if</span> p.name.lower().startswith(<span class="hljs-string">'readme'</span>) <span class="hljs-keyword">and</span> p.is_file(): +<span class="hljs-meta">... </span> print(<span class="hljs-string">f'<span class="hljs-subst">{p.name}</span> is a readme file that belongs to user <span class="hljs-subst">{user}</span>.'</span>) <span class="hljs-string">'README.md is a readme file that belongs to user gto.'</span> </code></pre></div> @@ -1838,9 +1836,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment </code></pre></div> <pre><code class="python language-python hljs">log.basicConfig(filename=<path>, level=<span class="hljs-string">'DEBUG'</span>) <span class="hljs-comment"># Configures the root logger (see Setup).</span> -log.debug/info/warning/error/critical(<str>) <span class="hljs-comment"># Logs to the root logger.</span> -<Logger> = log.getLogger(__name__) <span class="hljs-comment"># Logger named after the module.</span> -<Logger>.<level>(<str>) <span class="hljs-comment"># Logs to the logger.</span> +log.debug/info/warning/error/critical(<str>) <span class="hljs-comment"># Sends message to the root logger.</span> +<Logger> = log.getLogger(__name__) <span class="hljs-comment"># Returns logger named after the module.</span> +<Logger>.<level>(<str>) <span class="hljs-comment"># Sends message to the logger.</span> <Logger>.exception(<str>) <span class="hljs-comment"># Error() that appends caught exception.</span> </code></pre> <div><h3 id="setup">Setup</h3><pre><code class="python language-python hljs">log.basicConfig( @@ -1861,12 +1859,12 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment </code></pre> <ul> <li><strong>Parent logger can be specified by naming the child logger <code class="python hljs"><span class="hljs-string">'<parent>.<name>'</span></code>.</strong></li> -<li><strong>If logger doesn't have a set level it inherits it from the first ancestor that does.</strong></li> +<li><strong>If logger doesn't have a set level, it inherits it from the first ancestor that does.</strong></li> <li><strong>Formatter also accepts: pathname, filename, funcName, lineno, thread and process.</strong></li> -<li><strong>RotatingFileHandler creates and deletes files based on 'maxBytes' and 'backupCount' args.</strong></li> +<li><strong>RotatingFileHandler creates and deletes files based on 'maxBytes', 'backupCount' args.</strong></li> <li><strong>An object with <code class="python hljs"><span class="hljs-string">'filter(<LogRecord>)'</span></code> method (or the method itself) can be added to loggers and handlers via addFilter(). Message is dropped if filter() returns a false value.</strong></li> </ul> -<div><h4 id="createsaloggerthatwritesallmessagestofileandsendsthemtotherootshandlerthatprintswarningsorhigher">Creates a logger that writes all messages to file and sends them to the root's handler that prints warnings or higher:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>logger = log.getLogger(<span class="hljs-string">'my_module'</span>) +<div><h4 id="createsaloggerthatwritesallmessagestoafileandsendsthemtotherootshandlerthatprintswarningsorhigher">Creates a logger that writes all messages to a file and sends them to the root's handler that prints warnings or higher:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>logger = log.getLogger(<span class="hljs-string">'my_module'</span>) <span class="hljs-meta">>>> </span>handler = log.FileHandler(<span class="hljs-string">'test.log'</span>, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-meta">>>> </span>handler.setFormatter(log.Formatter(<span class="hljs-string">'%(asctime)s %(levelname)s:%(name)s:%(message)s'</span>)) <span class="hljs-meta">>>> </span>logger.addHandler(handler) @@ -1879,35 +1877,35 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment 2023-02-07 23:21:01,430 CRITICAL:my_module:Running out of disk space. </code></pre></div> -<div><h2 id="introspection"><a href="#introspection" name="introspection">#</a>Introspection</h2><pre><code class="python language-python hljs"><list> = dir() <span class="hljs-comment"># Names of local vars, functions, classes and modules.</span> -<dict> = vars() <span class="hljs-comment"># Dict of local vars, functions, etc. Also locals().</span> -<dict> = globals() <span class="hljs-comment"># Dict of global vars, etc. (including '__builtins__').</span> +<div><h2 id="introspection"><a href="#introspection" name="introspection">#</a>Introspection</h2><pre><code class="python language-python hljs"><list> = dir() <span class="hljs-comment"># List of of local names (including functions and classes).</span> +<dict> = vars() <span class="hljs-comment"># Dict of local names and their objects. Also locals().</span> +<dict> = globals() <span class="hljs-comment"># Dict of global names (for instance '__builtin__' module).</span> </code></pre></div> -<pre><code class="python language-python hljs"><list> = dir(<obj>) <span class="hljs-comment"># Names of all object's attributes (including methods).</span> -<dict> = vars(<obj>) <span class="hljs-comment"># Dict of writable attributes. Also <obj>.__dict__.</span> -<bool> = hasattr(<obj>, <span class="hljs-string">'<attr_name>'</span>) <span class="hljs-comment"># Checks if getattr() raises AttributeError.</span> -value = getattr(<obj>, <span class="hljs-string">'<attr_name>'</span>) <span class="hljs-comment"># Default value can be passed as the third argument.</span> -setattr(<obj>, <span class="hljs-string">'<attr_name>'</span>, value) <span class="hljs-comment"># Only works on objects with __dict__ attribute.</span> -delattr(<obj>, <span class="hljs-string">'<attr_name>'</span>) <span class="hljs-comment"># Same. Also `del <object>.<attr_name>`.</span> +<pre><code class="python language-python hljs"><list> = dir(<obj>) <span class="hljs-comment"># Returns names of all object's attributes (incl. methods).</span> +<dict> = vars(<obj>) <span class="hljs-comment"># Returns dict of writable attributes. Also <obj>.__dict__.</span> +<bool> = hasattr(<obj>, <span class="hljs-string">'<name>'</span>) <span class="hljs-comment"># Checks if object possesses attribute with passed name.</span> +value = getattr(<obj>, <span class="hljs-string">'<name>'</span>) <span class="hljs-comment"># Returns object's attribute or raises AttributeError.</span> +setattr(<obj>, <span class="hljs-string">'<name>'</span>, value) <span class="hljs-comment"># Sets attribute. Only works on objects with __dict__.</span> +delattr(<obj>, <span class="hljs-string">'<name>'</span>) <span class="hljs-comment"># Deletes attribute from __dict__. Also `del <obj>.<name>`.</span> </code></pre> -<pre><code class="python language-python hljs"><Sig> = inspect.signature(<function>) <span class="hljs-comment"># Returns function's Signature object.</span> -<dict> = <Sig>.parameters <span class="hljs-comment"># Dict of Parameters. Also <Sig>.return_annotation.</span> -<memb> = <Param>.kind <span class="hljs-comment"># Member of ParamKind enum (Parameter.KEYWORD_ONLY, …).</span> -<obj> = <Param>.default <span class="hljs-comment"># Parameter.empty if missing. Also <Param>.annotation.</span> +<pre><code class="python language-python hljs"><Sig> = inspect.signature(<func>) <span class="hljs-comment"># Returns function's Signature object. Can accept a class.</span> +<dict> = <Sig>.parameters <span class="hljs-comment"># Returns dict of Parameters. Also <Sig>.return_annotation.</span> +<memb> = <Param>.kind <span class="hljs-comment"># Returns ParameterKind member (Parameter.KEYWORD_ONLY, …).</span> +<type> = <Param>.annotation <span class="hljs-comment"># Returns Parameter.empty if missing. Also <Param>.default.</span> </code></pre> <div><h2 id="coroutines"><a href="#coroutines" name="coroutines">#</a>Coroutines</h2><ul> <li><strong>Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t use as much memory.</strong></li> <li><strong>Coroutine definition starts with <code class="python hljs"><span class="hljs-string">'async'</span></code> and its call with <code class="python hljs"><span class="hljs-string">'await'</span></code>.</strong></li> -<li><strong><code class="python hljs"><span class="hljs-string">'asyncio.run(<coroutine>)'</span></code> is the main entry point for asynchronous programs.</strong></li> +<li><strong>Use <code class="python hljs"><span class="hljs-string">'asyncio.run(<coroutine>)'</span></code> to start the first/main coroutine.</strong></li> </ul><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> asyncio <span class="hljs-keyword">as</span> aio </code></pre></div> <pre><code class="python language-python hljs"><coro> = <async_function>(<args>) <span class="hljs-comment"># Creates a coroutine by calling async def function.</span> -<obj> = <span class="hljs-keyword">await</span> <coroutine> <span class="hljs-comment"># Starts the coroutine and returns result.</span> +<obj> = <span class="hljs-keyword">await</span> <coroutine> <span class="hljs-comment"># Starts the coroutine and returns its result.</span> <task> = aio.create_task(<coroutine>) <span class="hljs-comment"># Schedules the coroutine for execution.</span> -<obj> = <span class="hljs-keyword">await</span> <task> <span class="hljs-comment"># Returns result. Also <task>.cancel().</span> +<obj> = <span class="hljs-keyword">await</span> <task> <span class="hljs-comment"># Returns coroutine's result. Also <task>.cancel().</span> </code></pre> <pre><code class="python language-python hljs"><coro> = aio.gather(<coro/task>, ...) <span class="hljs-comment"># Schedules coros. Returns list of results on await.</span> <coro> = aio.wait(<tasks>, …) <span class="hljs-comment"># `aio.ALL/FIRST_COMPLETED`. Returns (done, pending).</span> @@ -1926,7 +1924,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main_coroutine</span><span class="hljs-params">(screen)</span>:</span> moves = asyncio.Queue() - state = {<span class="hljs-string">'*'</span>: P(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>), **{id_: P(W//<span class="hljs-number">2</span>, H//<span class="hljs-number">2</span>) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)}} + state = {<span class="hljs-string">'*'</span>: P(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)} | {id_: P(W//<span class="hljs-number">2</span>, H//<span class="hljs-number">2</span>) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)} ai = [random_controller(id_, moves) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)] mvc = [human_controller(screen, moves), model(moves, state), view(state, screen)] tasks = [asyncio.create_task(coro) <span class="hljs-keyword">for</span> coro <span class="hljs-keyword">in</span> ai + mvc] @@ -1978,9 +1976,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <div><h2 id="plot"><a href="#plot" name="plot">#</a>Plot</h2><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install matplotlib</span> <span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt -plt.plot/bar/scatter(x_data, y_data [, label=<str>]) <span class="hljs-comment"># Or: plt.plot(y_data)</span> +plt.plot/bar/scatter(x_data, y_data [, label=<str>]) <span class="hljs-comment"># Also plt.plot(y_data).</span> plt.legend() <span class="hljs-comment"># Adds a legend.</span> -plt.title/xlabel/ylabel(<str>) <span class="hljs-comment"># Adds a title/label.</span> +plt.title/xlabel/ylabel(<str>) <span class="hljs-comment"># Adds a title or label.</span> plt.savefig(<path>) <span class="hljs-comment"># Saves the figure.</span> plt.show() <span class="hljs-comment"># Displays the figure.</span> plt.clf() <span class="hljs-comment"># Clears the figure.</span> @@ -2024,7 +2022,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <div><h2 id="guiapp"><a href="#guiapp" name="guiapp">#</a>GUI App</h2><div><h4 id="aweightconverterguiapplication">A weight converter GUI application:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install PySimpleGUI</span> <span class="hljs-keyword">import</span> PySimpleGUI <span class="hljs-keyword">as</span> sg -text_box = sg.Input(default_text=<span class="hljs-string">'100'</span>, enable_events=<span class="hljs-keyword">True</span>, key=<span class="hljs-string">'-VALUE-'</span>) +text_box = sg.Input(default_text=<span class="hljs-string">'100'</span>, enable_events=<span class="hljs-keyword">True</span>, key=<span class="hljs-string">'-QUANTITY-'</span>) dropdown = sg.InputCombo([<span class="hljs-string">'g'</span>, <span class="hljs-string">'kg'</span>, <span class="hljs-string">'t'</span>], <span class="hljs-string">'kg'</span>, readonly=<span class="hljs-keyword">True</span>, enable_events=<span class="hljs-keyword">True</span>, k=<span class="hljs-string">'-UNIT-'</span>) label = sg.Text(<span class="hljs-string">'100 kg is 220.462 lbs.'</span>, key=<span class="hljs-string">'-OUTPUT-'</span>) button = sg.Button(<span class="hljs-string">'Close'</span>) @@ -2035,13 +2033,13 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <span class="hljs-keyword">if</span> event <span class="hljs-keyword">in</span> [sg.WIN_CLOSED, <span class="hljs-string">'Close'</span>]: <span class="hljs-keyword">break</span> <span class="hljs-keyword">try</span>: - value = float(values[<span class="hljs-string">'-VALUE-'</span>]) + quantity = float(values[<span class="hljs-string">'-QUANTITY-'</span>]) <span class="hljs-keyword">except</span> ValueError: <span class="hljs-keyword">continue</span> unit = values[<span class="hljs-string">'-UNIT-'</span>] factors = {<span class="hljs-string">'g'</span>: <span class="hljs-number">0.001</span>, <span class="hljs-string">'kg'</span>: <span class="hljs-number">1</span>, <span class="hljs-string">'t'</span>: <span class="hljs-number">1000</span>} - lbs = value * factors[unit] / <span class="hljs-number">0.45359237</span> - window[<span class="hljs-string">'-OUTPUT-'</span>].update(value=<span class="hljs-string">f'<span class="hljs-subst">{value}</span> <span class="hljs-subst">{unit}</span> is <span class="hljs-subst">{lbs:g}</span> lbs.'</span>) + lbs = quantity * factors[unit] / <span class="hljs-number">0.45359237</span> + window[<span class="hljs-string">'-OUTPUT-'</span>].update(value=<span class="hljs-string">f'<span class="hljs-subst">{quantity}</span> <span class="hljs-subst">{unit}</span> is <span class="hljs-subst">{lbs:g}</span> lbs.'</span>) window.close() </code></pre></div></div> @@ -2065,31 +2063,31 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <div><h3 id="selenium">Selenium</h3><p><strong>Library for scraping websites with dynamic content.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install selenium</span> <span class="hljs-keyword">from</span> selenium <span class="hljs-keyword">import</span> webdriver -<Drv> = webdriver.Chrome/Firefox/Safari/Edge() <span class="hljs-comment"># Opens the browser. Also <Drv>.quit().</span> -<Drv>.get(<span class="hljs-string">'<url>'</span>) <span class="hljs-comment"># Also <Drv>.implicitly_wait(seconds).</span> -<El> = <Drv/El>.find_element(<span class="hljs-string">'css selector'</span>, <span class="hljs-string">'<css>'</span>) <span class="hljs-comment"># '<tag>#<id>.<class>[<attr>="<val>"]'.</span> -<list> = <Drv/El>.find_elements(<span class="hljs-string">'xpath'</span>, <span class="hljs-string">'<xpath>'</span>) <span class="hljs-comment"># '//<tag>[@<attr>="<val>"]'.</span> -<str> = <El>.get_attribute(<str>) <span class="hljs-comment"># Property if exists. Also <El>.text.</span> -<El>.click/clear() <span class="hljs-comment"># Also <El>.send_keys(<str>).</span> +<WebDrv> = webdriver.Chrome/Firefox/Safari/Edge() <span class="hljs-comment"># Opens a browser. Also <WebDrv>.quit().</span> +<WebDrv>.get(<span class="hljs-string">'<url>'</span>) <span class="hljs-comment"># Also <WebDrv>.implicitly_wait(seconds).</span> +<El> = <WebDrv/El>.find_element(<span class="hljs-string">'css selector'</span>, …) <span class="hljs-comment"># '<tag>#<id>.<class>[<attr>="<val>"]…'.</span> +<list> = <WebDrv/El>.find_elements(<span class="hljs-string">'xpath'</span>, …) <span class="hljs-comment"># '//<tag>[@<attr>="<val>"]…'. See XPath.</span> +<str> = <El>.get_attribute(<str>) <span class="hljs-comment"># Property if exists. Also <El>.text.</span> +<El>.click/clear() <span class="hljs-comment"># Also <El>.send_keys(<str>).</span> </code></pre></div> -<div><h4 id="xpathalsoavailableinlxmlscrapyandbrowsersconsoleviadxxpath">XPath — also available in lxml, Scrapy, and browser's console via <code class="python hljs"><span class="hljs-string">'$x(<xpath>)'</span></code>:</h4><pre><code class="python language-python hljs"><xpath> = //<element>[/ <span class="hljs-keyword">or</span> // <element>] <span class="hljs-comment"># /<child>, //<descendant>, /../<siblng></span> -<xpath> = //<element>/following::<element> <span class="hljs-comment"># Next element. Also preceding/parent/…</span> -<element> = <tag><conditions><index> <span class="hljs-comment"># `<tag> = */a/…`, `<index> = [1/2/…]`.</span> -<condition> = [<sub_cond> [<span class="hljs-keyword">and</span>/<span class="hljs-keyword">or</span> <sub_cond>]] <span class="hljs-comment"># For negation use `not(<sub_cond>)`.</span> -<sub_cond> = @<attr>[=<span class="hljs-string">"<val>"</span>] <span class="hljs-comment"># `text()=`, `.=` match (complete) text.</span> -<sub_cond> = contains(@<attr>, <span class="hljs-string">"<val>"</span>) <span class="hljs-comment"># Is <val> a substring of attr's value?</span> -<sub_cond> = [//]<element> <span class="hljs-comment"># Has matching child? Descendant if //.</span> +<div><h4 id="xpathalsoavailableinlxmlscrapyandbrowsersconsoleviadxxpath">XPath — also available in lxml, Scrapy, and browser's console via <code class="python hljs"><span class="hljs-string">'$x("<xpath>")'</span></code>:</h4><pre><code class="python language-python hljs"><xpath> = //<element>[/ <span class="hljs-keyword">or</span> // <element>] <span class="hljs-comment"># /<child>, //<descendant>, /../<sibling></span> +<xpath> = //<element>/following::<element> <span class="hljs-comment"># Next element. Also preceding/parent/…</span> +<element> = <tag><conditions><index> <span class="hljs-comment"># `<tag> = */a/…`, `<index> = [1/2/…]`.</span> +<condition> = [<sub_cond> [<span class="hljs-keyword">and</span>/<span class="hljs-keyword">or</span> <sub_cond>]] <span class="hljs-comment"># For negation use `not(<sub_cond>)`.</span> +<sub_cond> = @<attr>[=<span class="hljs-string">"<val>"</span>] <span class="hljs-comment"># `text()=`, `.=` match (complete) text.</span> +<sub_cond> = contains(@<attr>, <span class="hljs-string">"<val>"</span>) <span class="hljs-comment"># Is <val> a substring of attr's value?</span> +<sub_cond> = [//]<element> <span class="hljs-comment"># Has matching child? Descendant if //.</span> </code></pre></div> -<div><h2 id="web"><a href="#web" name="web">#</a>Web</h2><p><strong>Flask is a micro web framework/server. If you just want to open a html file in a web browser use <code class="python hljs"><span class="hljs-string">'webbrowser.open(<path>)'</span></code> instead.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install flask</span> -<span class="hljs-keyword">import</span> flask +<div><h2 id="webapp"><a href="#webapp" name="webapp">#</a>Web App</h2><p><strong>Flask is a micro web framework/server. If you just want to open a html file in a web browser use <code class="python hljs"><span class="hljs-string">'webbrowser.open(<path>)'</span></code> instead.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install flask</span> +<span class="hljs-keyword">import</span> flask <span class="hljs-keyword">as</span> fl </code></pre></div> -<pre><code class="python language-python hljs">app = flask.Flask(__name__) <span class="hljs-comment"># Returns app object. Put at the top.</span> -app.run(host=<span class="hljs-keyword">None</span>, port=<span class="hljs-keyword">None</span>, debug=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Or: $ flask --app FILE run [--ARG[=VAL]]</span> +<pre><code class="python language-python hljs">app = fl.Flask(__name__) <span class="hljs-comment"># Returns the app object. Put at the top.</span> +app.run(host=<span class="hljs-keyword">None</span>, port=<span class="hljs-keyword">None</span>, debug=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Or: $ flask --app FILE run [--ARG[=VAL] …]</span> </code></pre> <ul> <li><strong>Starts the app at <code class="python hljs"><span class="hljs-string">'http://localhost:5000'</span></code>. Use <code class="python hljs"><span class="hljs-string">'host="0.0.0.0"'</span></code> to run externally.</strong></li> @@ -2098,23 +2096,23 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment </ul> <div><h3 id="staticrequest">Static Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/img/<path:filename>')</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">serve_file</span><span class="hljs-params">(filename)</span>:</span> - <span class="hljs-keyword">return</span> flask.send_from_directory(<span class="hljs-string">'dirname/'</span>, filename) + <span class="hljs-keyword">return</span> fl.send_from_directory(<span class="hljs-string">'dirname/'</span>, filename) </code></pre></div> <div><h3 id="dynamicrequest">Dynamic Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.route('/<sport>')</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">serve_html</span><span class="hljs-params">(sport)</span>:</span> - <span class="hljs-keyword">return</span> flask.render_template_string(<span class="hljs-string">'<h1>{{title}}</h1>'</span>, title=sport) + <span class="hljs-keyword">return</span> fl.render_template_string(<span class="hljs-string">'<h1>{{title}}</h1>'</span>, title=sport) </code></pre></div> <ul> -<li><strong>Use <code class="python hljs"><span class="hljs-string">'render_template(filename, <kwargs>)'</span></code> to render file located in templates dir.</strong></li> -<li><strong>To return an error code use <code class="python hljs"><span class="hljs-string">'abort(<int>)'</span></code> and to redirect use <code class="python hljs"><span class="hljs-string">'redirect(<url>)'</span></code>.</strong></li> -<li><strong><code class="python hljs"><span class="hljs-string">'request.args[<str>]'</span></code> returns parameter from the query string (URL part after '?').</strong></li> -<li><strong><code class="python hljs"><span class="hljs-string">'session[<str>] = <obj>'</span></code> stores session data. Needs <code class="python hljs"><span class="hljs-string">'app.secret_key = <str>'</span></code>.</strong></li> +<li><strong><code class="python hljs"><span class="hljs-string">'fl.render_template(filename, <kwargs>)'</span></code> renders a file located in 'templates' dir.</strong></li> +<li><strong><code class="python hljs"><span class="hljs-string">'fl.abort(<int>)'</span></code> returns error code and <code class="python hljs"><span class="hljs-string">'return fl.redirect(<url>)'</span></code> redirects.</strong></li> +<li><strong><code class="python hljs"><span class="hljs-string">'fl.request.args[<str>]'</span></code> returns parameter from the query string (URL right of '?').</strong></li> +<li><strong><code class="python hljs"><span class="hljs-string">'fl.session[<str>] = <obj>'</span></code> stores session data. It requires secret key to be set at the startup with <code class="python hljs"><span class="hljs-string">'app.secret_key = <str>'</span></code>.</strong></li> </ul> <div><h3 id="restrequest">REST Request</h3><pre><code class="python language-python hljs"><span class="hljs-meta">@app.post('/<sport>/odds')</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">serve_json</span><span class="hljs-params">(sport)</span>:</span> - team = flask.request.form[<span class="hljs-string">'team'</span>] + team = fl.request.form[<span class="hljs-string">'team'</span>] <span class="hljs-keyword">return</span> {<span class="hljs-string">'team'</span>: team, <span class="hljs-string">'odds'</span>: [<span class="hljs-number">2.09</span>, <span class="hljs-number">3.74</span>, <span class="hljs-number">3.68</span>]} </code></pre></div> @@ -2122,8 +2120,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <span class="hljs-meta">>>> </span><span class="hljs-keyword">import</span> threading, requests <span class="hljs-meta">>>> </span>threading.Thread(target=app.run, daemon=<span class="hljs-keyword">True</span>).start() <span class="hljs-meta">>>> </span>url = <span class="hljs-string">'http://localhost:5000/football/odds'</span> -<span class="hljs-meta">>>> </span>request_data = {<span class="hljs-string">'team'</span>: <span class="hljs-string">'arsenal f.c.'</span>} -<span class="hljs-meta">>>> </span>response = requests.post(url, data=request_data) +<span class="hljs-meta">>>> </span>response = requests.post(url, data={<span class="hljs-string">'team'</span>: <span class="hljs-string">'arsenal f.c.'</span>}) <span class="hljs-meta">>>> </span>response.json() {<span class="hljs-string">'team'</span>: <span class="hljs-string">'arsenal f.c.'</span>, <span class="hljs-string">'odds'</span>: [<span class="hljs-number">2.09</span>, <span class="hljs-number">3.74</span>, <span class="hljs-number">3.68</span>]} </code></pre></div> @@ -2219,7 +2216,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <li><strong><code class="python hljs"><span class="hljs-string">'ix_([1, 2], [3, 4])'</span></code> returns <code class="python hljs"><span class="hljs-string">'[[1], [2]]'</span></code> and <code class="python hljs"><span class="hljs-string">'[[3, 4]]'</span></code>. Due to broadcasting rules, this is the same as using <code class="python hljs"><span class="hljs-string">'[[1, 1], [2, 2]]'</span></code> and <code class="python hljs"><span class="hljs-string">'[[3, 4], [3, 4]]'</span></code>.</strong></li> <li><strong>Any value that is broadcastable to the indexed shape can be assigned to the selection.</strong></li> </ul> -<div><h3 id="broadcasting">Broadcasting</h3><p><strong>Set of rules by which NumPy functions operate on arrays of different sizes and/or dimensions.</strong></p><pre><code class="python language-python hljs">left = [ <span class="hljs-number">0.1</span> , <span class="hljs-number">0.6</span> , <span class="hljs-number">0.8</span> ] <span class="hljs-comment"># Shape: (3,)</span> +<div><h3 id="broadcasting">Broadcasting</h3><p><strong>A set of rules by which NumPy functions operate on arrays of different shapes.</strong></p><pre><code class="python language-python hljs">left = [ <span class="hljs-number">0.1</span> , <span class="hljs-number">0.6</span> , <span class="hljs-number">0.8</span> ] <span class="hljs-comment"># Shape: (3,)</span> right = [[<span class="hljs-number">0.1</span>], [<span class="hljs-number">0.6</span>], [<span class="hljs-number">0.8</span>]] <span class="hljs-comment"># Shape: (3, 1)</span> </code></pre></div> @@ -2264,18 +2261,18 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <pre><code class="python language-python hljs"><Image> = Image.new(<span class="hljs-string">'<mode>'</span>, (width, height)) <span class="hljs-comment"># Creates new image. Also `color=<int/tuple>`.</span> <Image> = Image.open(<path>) <span class="hljs-comment"># Identifies format based on file's contents.</span> -<Image> = <Image>.convert(<span class="hljs-string">'<mode>'</span>) <span class="hljs-comment"># Converts image to the new mode.</span> +<Image> = <Image>.convert(<span class="hljs-string">'<mode>'</span>) <span class="hljs-comment"># Converts image to the new mode (see Modes).</span> <Image>.save(<path>) <span class="hljs-comment"># Selects format based on extension (PNG/JPG…).</span> <Image>.show() <span class="hljs-comment"># Opens image in the default preview app.</span> </code></pre> -<pre><code class="python language-python hljs"><int/tuple> = <Image>.getpixel((x, y)) <span class="hljs-comment"># Returns pixel's value (its color).</span> -<Image>.putpixel((x, y), <int/tuple>) <span class="hljs-comment"># Updates pixel's value.</span> -<ImagingCore> = <Image>.getdata() <span class="hljs-comment"># Returns a flattened view of pixel values.</span> -<Image>.putdata(<list/ImagingCore>) <span class="hljs-comment"># Updates pixels with a copy of the sequence.</span> +<pre><code class="python language-python hljs"><int/tup> = <Image>.getpixel((x, y)) <span class="hljs-comment"># Returns pixel's value (its color).</span> +<ImgCore> = <Image>.getdata() <span class="hljs-comment"># Returns a flattened view of pixel values.</span> +<Image>.putpixel((x, y), <int/tuple>) <span class="hljs-comment"># Updates pixel's value. Clips passed int/s.</span> +<Image>.putdata(<list/ImgCore>) <span class="hljs-comment"># Updates pixels with a copy of the sequence.</span> <Image>.paste(<Image>, (x, y)) <span class="hljs-comment"># Draws passed image at the specified location.</span> </code></pre> -<pre><code class="python language-python hljs"><Image> = <Image>.filter(<Filter>) <span class="hljs-comment"># `<Filter> = ImageFilter.<name>(<args>)`</span> -<Image> = <Enhance>.enhance(<float>) <span class="hljs-comment"># `<Enhance> = ImageEnhance.<name>(<Image>)`</span> +<pre><code class="python language-python hljs"><Image> = <Image>.filter(<Filter>) <span class="hljs-comment"># Use ImageFilter.<name>(<args>) for Filter.</span> +<Image> = <Enhance>.enhance(<float>) <span class="hljs-comment"># Use ImageEnhance.<name>(<Image>) for Enhance.</span> </code></pre> <pre><code class="python language-python hljs"><array> = np.array(<Image>) <span class="hljs-comment"># Creates a 2d/3d NumPy array from the image.</span> <Image> = Image.fromarray(np.uint8(<array>)) <span class="hljs-comment"># Use `<array>.clip(0, 255)` to clip values.</span> @@ -2283,7 +2280,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <div><h3 id="modes-1">Modes</h3><ul> <li><strong><code class="python hljs"><span class="hljs-string">'L'</span></code> - Lightness (greyscale image). Each pixel is an int between 0 and 255.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'RGB'</span></code> - Red, green, blue (true color image). Each pixel is a tuple of three ints.</strong></li> -<li><strong><code class="python hljs"><span class="hljs-string">'RGBA'</span></code> - RGB with alpha. Low alpha (i.e. forth int) makes pixel more transparent.</strong></li> +<li><strong><code class="python hljs"><span class="hljs-string">'RGBA'</span></code> - RGB with alpha. Low alpha (i.e. forth int) makes pixels more transparent.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'HSV'</span></code> - Hue, saturation, value. Three ints representing color in HSV color space.</strong></li> </ul><div><h3 id="examples">Examples</h3><div><h4 id="createsapngimageofarainbowgradient">Creates a PNG image of a rainbow gradient:</h4><pre><code class="python language-python hljs">WIDTH, HEIGHT = <span class="hljs-number">100</span>, <span class="hljs-number">100</span> n_pixels = WIDTH * HEIGHT @@ -2307,10 +2304,10 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <Draw> = ImageDraw.Draw(<Image>) <span class="hljs-comment"># Object for adding 2D graphics to the image.</span> <Draw>.point((x, y)) <span class="hljs-comment"># Draws a point. Truncates floats into ints.</span> <Draw>.line((x1, y1, x2, y2 [, ...])) <span class="hljs-comment"># To get anti-aliasing use Image's resize().</span> -<Draw>.arc((x1, y1, x2, y2), deg1, deg2) <span class="hljs-comment"># Always draws in clockwise direction.</span> +<Draw>.arc((x1, y1, x2, y2), deg1, deg2) <span class="hljs-comment"># Draws in clockwise dir. Also pieslice().</span> <Draw>.rectangle((x1, y1, x2, y2)) <span class="hljs-comment"># To rotate use Image's rotate() and paste().</span> <Draw>.polygon((x1, y1, x2, y2, ...)) <span class="hljs-comment"># Last point gets connected to the first.</span> -<Draw>.ellipse((x1, y1, x2, y2)) <span class="hljs-comment"># To rotate use Image's rotate() and paste().</span> +<Draw>.ellipse((x1, y1, x2, y2)) <span class="hljs-comment"># Also rounded_rectangle(), regular_polygon().</span> <Draw>.text((x, y), <str>, font=<Font>) <span class="hljs-comment"># `<Font> = ImageFont.truetype(<path>, size)`</span> </code></pre></div> @@ -2340,7 +2337,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <div><h2 id="audio"><a href="#audio" name="audio">#</a>Audio</h2><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> wave </code></pre></div> -<pre><code class="python language-python hljs"><Wave> = wave.open(<span class="hljs-string">'<path>'</span>, <span class="hljs-string">'rb'</span>) <span class="hljs-comment"># Opens the WAV file.</span> +<pre><code class="python language-python hljs"><Wave> = wave.open(<span class="hljs-string">'<path>'</span>) <span class="hljs-comment"># Opens the WAV file for reading.</span> <int> = <Wave>.getframerate() <span class="hljs-comment"># Returns number of frames per second.</span> <int> = <Wave>.getnchannels() <span class="hljs-comment"># Returns number of samples per frame.</span> <int> = <Wave>.getsampwidth() <span class="hljs-comment"># Returns number of bytes per sample.</span> @@ -2351,15 +2348,14 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <Wave>.setframerate(<int>) <span class="hljs-comment"># Pass 44100 for CD, 48000 for video.</span> <Wave>.setnchannels(<int>) <span class="hljs-comment"># Pass 1 for mono, 2 for stereo.</span> <Wave>.setsampwidth(<int>) <span class="hljs-comment"># Pass 2 for CD, 3 for hi-res sound.</span> -<Wave>.setparams(<tuple>) <span class="hljs-comment"># Sets all parameters.</span> +<Wave>.setparams(<tuple>) <span class="hljs-comment"># Tuple must contain all parameters.</span> <Wave>.writeframes(<bytes>) <span class="hljs-comment"># Appends frames to the file.</span> </code></pre> <ul> <li><strong>Bytes object contains a sequence of frames, each consisting of one or more samples.</strong></li> <li><strong>In a stereo signal, the first sample of a frame belongs to the left channel.</strong></li> <li><strong>Each sample consists of one or more bytes that, when converted to an integer, indicate the displacement of a speaker membrane at a given moment.</strong></li> -<li><strong>If sample width is one byte, then the integer should be encoded unsigned.</strong></li> -<li><strong>For all other sizes, the integer should be encoded signed with little-endian byte order.</strong></li> +<li><strong>If sample width is one byte, then the integer should be encoded unsigned. For all other sizes, the integer should be encoded signed with little-endian byte order.</strong></li> </ul> <div><h3 id="samplevalues">Sample Values</h3><pre><code class="python hljs">┏━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━┯━━━━━━━━━━━┓ ┃ sampwidth │ min │ zero │ max ┃ @@ -2372,26 +2368,26 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <div><h3 id="readfloatsamplesfromwavfile">Read Float Samples from WAV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_wav_file</span><span class="hljs-params">(filename)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_int</span><span class="hljs-params">(bytes_obj)</span>:</span> - an_int = int.from_bytes(bytes_obj, <span class="hljs-string">'little'</span>, signed=(sampwidth != <span class="hljs-number">1</span>)) - <span class="hljs-keyword">return</span> an_int - <span class="hljs-number">128</span> * (sampwidth == <span class="hljs-number">1</span>) - <span class="hljs-keyword">with</span> wave.open(filename, <span class="hljs-string">'rb'</span>) <span class="hljs-keyword">as</span> file: - sampwidth = file.getsampwidth() + an_int = int.from_bytes(bytes_obj, <span class="hljs-string">'little'</span>, signed=(p.sampwidth != <span class="hljs-number">1</span>)) + <span class="hljs-keyword">return</span> an_int - <span class="hljs-number">128</span> * (p.sampwidth == <span class="hljs-number">1</span>) + <span class="hljs-keyword">with</span> wave.open(filename) <span class="hljs-keyword">as</span> file: + p = file.getparams() frames = file.readframes(<span class="hljs-number">-1</span>) - bytes_samples = (frames[i : i+sampwidth] <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>, len(frames), sampwidth)) - <span class="hljs-keyword">return</span> [get_int(b) / pow(<span class="hljs-number">2</span>, sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>) <span class="hljs-keyword">for</span> b <span class="hljs-keyword">in</span> bytes_samples] + bytes_samples = (frames[i : i + p.sampwidth] <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>, len(frames), p.sampwidth)) + <span class="hljs-keyword">return</span> [get_int(b) / pow(<span class="hljs-number">2</span>, p.sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>) <span class="hljs-keyword">for</span> b <span class="hljs-keyword">in</span> bytes_samples], p </code></pre></div> -<div><h3 id="writefloatsamplestowavfile">Write Float Samples to WAV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_wav_file</span><span class="hljs-params">(filename, float_samples, nchannels=<span class="hljs-number">1</span>, sampwidth=<span class="hljs-number">2</span>, framerate=<span class="hljs-number">44100</span>)</span>:</span> +<div><h3 id="writefloatsamplestowavfile">Write Float Samples to WAV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_wav_file</span><span class="hljs-params">(filename, samples_f, p=<span class="hljs-keyword">None</span>, nchannels=<span class="hljs-number">1</span>, sampwidth=<span class="hljs-number">2</span>, framerate=<span class="hljs-number">44100</span>)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_bytes</span><span class="hljs-params">(a_float)</span>:</span> a_float = max(<span class="hljs-number">-1</span>, min(<span class="hljs-number">1</span> - <span class="hljs-number">2e-16</span>, a_float)) - a_float += sampwidth == <span class="hljs-number">1</span> - a_float *= pow(<span class="hljs-number">2</span>, sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>) - <span class="hljs-keyword">return</span> int(a_float).to_bytes(sampwidth, <span class="hljs-string">'little'</span>, signed=(sampwidth != <span class="hljs-number">1</span>)) + a_float += p.sampwidth == <span class="hljs-number">1</span> + a_float *= pow(<span class="hljs-number">2</span>, p.sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>) + <span class="hljs-keyword">return</span> int(a_float).to_bytes(p.sampwidth, <span class="hljs-string">'little'</span>, signed=(p.sampwidth != <span class="hljs-number">1</span>)) + <span class="hljs-keyword">if</span> p <span class="hljs-keyword">is</span> <span class="hljs-keyword">None</span>: + p = wave._wave_params(nchannels, sampwidth, framerate, <span class="hljs-number">0</span>, <span class="hljs-string">'NONE'</span>, <span class="hljs-string">'not compressed'</span>) <span class="hljs-keyword">with</span> wave.open(filename, <span class="hljs-string">'wb'</span>) <span class="hljs-keyword">as</span> file: - file.setnchannels(nchannels) - file.setsampwidth(sampwidth) - file.setframerate(framerate) - file.writeframes(<span class="hljs-string">b''</span>.join(get_bytes(f) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> float_samples)) + file.setparams(p) + file.writeframes(<span class="hljs-string">b''</span>.join(get_bytes(f) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> samples_f)) </code></pre></div> <div><h3 id="examples-1">Examples</h3><div><h4 id="savesa440hzsinewavetoamonowavfile">Saves a 440 Hz sine wave to a mono WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> pi, sin @@ -2400,15 +2396,15 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment </code></pre></div></div> -<div><h4 id="addsnoisetothemonowavfile">Adds noise to the mono WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> random -add_noise = <span class="hljs-keyword">lambda</span> value: value + (random() - <span class="hljs-number">0.5</span>) * <span class="hljs-number">0.03</span> -samples_f = (add_noise(f) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> read_wav_file(<span class="hljs-string">'test.wav'</span>)) -write_to_wav_file(<span class="hljs-string">'test.wav'</span>, samples_f) +<div><h4 id="addsnoisetothewavfile">Adds noise to the WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> random <span class="hljs-keyword">import</span> uniform +samples_f, params = read_wav_file(<span class="hljs-string">'test.wav'</span>) +samples_f = (f + uniform(<span class="hljs-number">-0.05</span>, <span class="hljs-number">0.05</span>) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> samples_f) +write_to_wav_file(<span class="hljs-string">'test.wav'</span>, samples_f, params) </code></pre></div> <div><h4 id="playsthewavfile">Plays the WAV file:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install simpleaudio</span> <span class="hljs-keyword">from</span> simpleaudio <span class="hljs-keyword">import</span> play_buffer -<span class="hljs-keyword">with</span> wave.open(<span class="hljs-string">'test.wav'</span>, <span class="hljs-string">'rb'</span>) <span class="hljs-keyword">as</span> file: +<span class="hljs-keyword">with</span> wave.open(<span class="hljs-string">'test.wav'</span>) <span class="hljs-keyword">as</span> file: p = file.getparams() frames = file.readframes(<span class="hljs-number">-1</span>) play_buffer(frames, p.nchannels, p.sampwidth, p.framerate).wait_done() @@ -2430,7 +2426,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment get_pause = <span class="hljs-keyword">lambda</span> seconds: it.repeat(<span class="hljs-number">0</span>, int(seconds * F)) sin_f = <span class="hljs-keyword">lambda</span> i, hz: math.sin(i * <span class="hljs-number">2</span> * math.pi * hz / F) get_wave = <span class="hljs-keyword">lambda</span> hz, seconds: (sin_f(i, hz) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(int(seconds * F))) -get_hz = <span class="hljs-keyword">lambda</span> note: <span class="hljs-number">8.176</span> * <span class="hljs-number">2</span> ** (int(note[:<span class="hljs-number">2</span>]) / <span class="hljs-number">12</span>) +get_hz = <span class="hljs-keyword">lambda</span> note: <span class="hljs-number">440</span> * <span class="hljs-number">2</span> ** ((int(note[:<span class="hljs-number">2</span>]) - <span class="hljs-number">69</span>) / <span class="hljs-number">12</span>) get_sec = <span class="hljs-keyword">lambda</span> note: <span class="hljs-number">1</span>/<span class="hljs-number">4</span> <span class="hljs-keyword">if</span> <span class="hljs-string">'♩'</span> <span class="hljs-keyword">in</span> note <span class="hljs-keyword">else</span> <span class="hljs-number">1</span>/<span class="hljs-number">8</span> get_samples = <span class="hljs-keyword">lambda</span> note: get_wave(get_hz(note), get_sec(note)) <span class="hljs-keyword">if</span> note <span class="hljs-keyword">else</span> get_pause(<span class="hljs-number">1</span>/<span class="hljs-number">8</span>) samples_f = it.chain.from_iterable(get_samples(n) <span class="hljs-keyword">for</span> n <span class="hljs-keyword">in</span> (P1+P2).split(<span class="hljs-string">','</span>)) @@ -2465,7 +2461,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <pre><code class="python language-python hljs"><bool> = <Rect>.collidepoint((x, y)) <span class="hljs-comment"># Checks if rectangle contains the point.</span> <bool> = <Rect>.colliderect(<Rect>) <span class="hljs-comment"># Checks if the two rectangles overlap.</span> <int> = <Rect>.collidelist(<list_of_Rect>) <span class="hljs-comment"># Returns index of first colliding Rect or -1.</span> -<list> = <Rect>.collidelistall(<list_of_Rect>) <span class="hljs-comment"># Returns indexes of all colliding rectangles.</span> +<list> = <Rect>.collidelistall(<list_of_Rect>) <span class="hljs-comment"># Returns indices of all colliding rectangles.</span> </code></pre> <div><h3 id="surface">Surface</h3><p><strong>Object for representing images.</strong></p><pre><code class="python language-python hljs"><Surf> = pg.display.set_mode((width, height)) <span class="hljs-comment"># Opens new window and returns its surface.</span> <Surf> = pg.Surface((width, height)) <span class="hljs-comment"># New RGB surface. RGBA if `flags=pg.SRCALPHA`.</span> @@ -2562,7 +2558,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment mario.facing_left = mario.spd.x < <span class="hljs-number">0</span> <span class="hljs-keyword">if</span> mario.spd.x <span class="hljs-keyword">else</span> mario.facing_left is_airborne = D.s <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> get_boundaries(mario.rect, tiles) image_index = <span class="hljs-number">4</span> <span class="hljs-keyword">if</span> is_airborne <span class="hljs-keyword">else</span> (next(mario.frame_cycle) <span class="hljs-keyword">if</span> mario.spd.x <span class="hljs-keyword">else</span> <span class="hljs-number">6</span>) - screen.blit(images[image_index + mario.facing_left * <span class="hljs-number">9</span>], mario.rect) + screen.blit(images[image_index + (mario.facing_left * <span class="hljs-number">9</span>)], mario.rect) <span class="hljs-keyword">for</span> t <span class="hljs-keyword">in</span> tiles: is_border = t.x <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span>, (W-<span class="hljs-number">1</span>)*<span class="hljs-number">16</span>] <span class="hljs-keyword">or</span> t.y <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span>, (H-<span class="hljs-number">1</span>)*<span class="hljs-number">16</span>] screen.blit(images[<span class="hljs-number">18</span> <span class="hljs-keyword">if</span> is_border <span class="hljs-keyword">else</span> <span class="hljs-number">19</span>], t) @@ -2576,7 +2572,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd, matplotlib.pyplot <span class="hljs-keyword">as</span> plt </code></pre></div> -<div><h3 id="series">Series</h3><p><strong>Ordered dictionary with a name.</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>pd.Series([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], index=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>], name=<span class="hljs-string">'a'</span>) +<div><h3 id="series">Series</h3><p><strong>Ordered dictionary with a name.</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>sr = pd.Series([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], index=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>], name=<span class="hljs-string">'a'</span>); sr x <span class="hljs-number">1</span> y <span class="hljs-number">2</span> Name: a, dtype: int64 @@ -2610,7 +2606,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <Sr> = <Sr>.fillna(<el>) <span class="hljs-comment"># Or: <Sr>.agg/transform/map(lambda <el>: <el>)</span> </code></pre></div> -<pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>sr = pd.Series([<span class="hljs-number">2</span>, <span class="hljs-number">3</span>], index=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>]) +<pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>sr = pd.Series([<span class="hljs-number">2</span>, <span class="hljs-number">3</span>], index=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>]); sr x <span class="hljs-number">2</span> y <span class="hljs-number">3</span> </code></pre> @@ -2635,7 +2631,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <li><strong>Methods ffill(), interpolate(), fillna() and dropna() accept <code class="python hljs"><span class="hljs-string">'inplace=True'</span></code>.</strong></li> <li><strong>Last result has a hierarchical index. Use <code class="python hljs"><span class="hljs-string">'<Sr>[key_1, key_2]'</span></code> to get its values.</strong></li> </ul> -<div><h3 id="dataframe">DataFrame</h3><p><strong>Table with labeled rows and columns.</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>pd.DataFrame([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]], index=[<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>], columns=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>]) +<div><h3 id="dataframe">DataFrame</h3><p><strong>Table with labeled rows and columns.</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>l = pd.DataFrame([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]], index=[<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>], columns=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>]); l x y a <span class="hljs-number">1</span> <span class="hljs-number">2</span> b <span class="hljs-number">3</span> <span class="hljs-number">4</span> @@ -2662,11 +2658,10 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <DF> = <DF>.sort_index(ascending=<span class="hljs-keyword">True</span>) <span class="hljs-comment"># Sorts rows by row keys. Use `axis=1` for cols.</span> <DF> = <DF>.sort_values(col_key/s) <span class="hljs-comment"># Sorts rows by passed column/s. Also `axis=1`.</span> </code></pre> -<div><h4 id="dataframemergejoinconcat">DataFrame — Merge, Join, Concat:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>l = pd.DataFrame([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]], index=[<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>], columns=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>]) - x y -a <span class="hljs-number">1</span> <span class="hljs-number">2</span> -b <span class="hljs-number">3</span> <span class="hljs-number">4</span> -<span class="hljs-meta">>>> </span>r = pd.DataFrame([[<span class="hljs-number">4</span>, <span class="hljs-number">5</span>], [<span class="hljs-number">6</span>, <span class="hljs-number">7</span>]], index=[<span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>], columns=[<span class="hljs-string">'y'</span>, <span class="hljs-string">'z'</span>]) +<pre><code class="python language-python hljs"><DF>.plot.line/area/bar/scatter(x=col_key, …) <span class="hljs-comment"># `y=col_key/s`. Also hist/box(by=col_key).</span> +plt.show() <span class="hljs-comment"># Displays the plot. Also plt.savefig(<path>).</span> +</code></pre> +<div><h4 id="dataframemergejoinconcat">DataFrame — Merge, Join, Concat:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>r = pd.DataFrame([[<span class="hljs-number">4</span>, <span class="hljs-number">5</span>], [<span class="hljs-number">6</span>, <span class="hljs-number">7</span>]], index=[<span class="hljs-string">'b'</span>, <span class="hljs-string">'c'</span>], columns=[<span class="hljs-string">'y'</span>, <span class="hljs-string">'z'</span>]); r y z b <span class="hljs-number">4</span> <span class="hljs-number">5</span> c <span class="hljs-number">6</span> <span class="hljs-number">7</span> @@ -2710,7 +2705,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <ul> <li><strong>All operations operate on columns by default. Pass <code class="python hljs"><span class="hljs-string">'axis=1'</span></code> to process the rows instead.</strong></li> </ul> -<pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>df = pd.DataFrame([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]], index=[<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>], columns=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>]) +<pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>df = pd.DataFrame([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]], index=[<span class="hljs-string">'a'</span>, <span class="hljs-string">'b'</span>], columns=[<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>]); df x y a <span class="hljs-number">1</span> <span class="hljs-number">2</span> b <span class="hljs-number">3</span> <span class="hljs-number">4</span> @@ -2735,72 +2730,70 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <ul> <li><strong>Use <code class="python hljs"><span class="hljs-string">'<DF>[col_key_1, col_key_2][row_key]'</span></code> to get the fifth result's values.</strong></li> </ul> -<div><h4 id="dataframeplotencodedecode">DataFrame — Plot, Encode, Decode:</h4><pre><code class="python language-python hljs"><DF>.plot.line/area/bar/scatter(x=col_key, …) <span class="hljs-comment"># `y=col_key/s`. Also hist/box(by=col_key).</span> -plt.show() <span class="hljs-comment"># Displays the plot. Also plt.savefig(<path>).</span> -</code></pre></div> - -<pre><code class="python language-python hljs"><DF> = pd.read_json/html(<span class="hljs-string">'<str/path/url>'</span>) <span class="hljs-comment"># Run `$ pip3 install beautifulsoup4 lxml`.</span> -<DF> = pd.read_csv(<span class="hljs-string">'<path/url>'</span>) <span class="hljs-comment"># `header/index_col/dtype/parse_dates/…=<obj>`.</span> +<div><h4 id="dataframeencodedecode">DataFrame — Encode, Decode:</h4><pre><code class="python language-python hljs"><DF> = pd.read_json/html(<span class="hljs-string">'<str/path/url>'</span>) <span class="hljs-comment"># Run `$ pip3 install beautifulsoup4 lxml`.</span> +<DF> = pd.read_csv(<span class="hljs-string">'<path/url>'</span>) <span class="hljs-comment"># `header/index_col/dtype/usecols/…=<obj>`.</span> <DF> = pd.read_pickle/excel(<span class="hljs-string">'<path/url>'</span>) <span class="hljs-comment"># Use `sheet_name=None` to get all Excel sheets.</span> <DF> = pd.read_sql(<span class="hljs-string">'<table/query>'</span>, <conn.>) <span class="hljs-comment"># SQLite3/SQLAlchemy connection (see #SQLite).</span> -</code></pre> +</code></pre></div> + <pre><code class="python language-python hljs"><dict> = <DF>.to_dict(<span class="hljs-string">'d/l/s/…'</span>) <span class="hljs-comment"># Returns columns as dicts, lists or series.</span> -<str> = <DF>.to_json/html/csv/latex() <span class="hljs-comment"># Saves output to file if path is passed.</span> +<str> = <DF>.to_json/html/csv/latex() <span class="hljs-comment"># Saves output to a file if path is passed.</span> <DF>.to_pickle/excel(<path>) <span class="hljs-comment"># Run `$ pip3 install "pandas[excel]" odfpy`.</span> <DF>.to_sql(<span class="hljs-string">'<table_name>'</span>, <connection>) <span class="hljs-comment"># Also `if_exists='fail/replace/append'`.</span> </code></pre> +<ul> +<li><strong>Read_csv() only parses dates of columns that were specified by 'parse_dates' argument. It automatically tries to detect the format, but it can be helped with 'date_format' or 'datefirst' arguments. Both dates and datetimes get stored as pd.Timestamp objects.</strong></li> +<li><strong>If there's a single invalid date then it returns the whole column as a series of strings, unlike <code class="python hljs"><span class="hljs-string">'<Sr> = pd.to_datetime(<Sr>, errors="coerce")'</span></code>, which uses pd.NaT.</strong></li> +<li><strong>To get specific attributes from a series of Timestamps use <code class="python hljs"><span class="hljs-string">'<Sr>.dt.year/date/…'</span></code>.</strong></li> +</ul> <div><h3 id="groupby">GroupBy</h3><p><strong>Object that groups together rows of a dataframe based on the value of the passed column.</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>df = pd.DataFrame([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>], [<span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">6</span>]], list(<span class="hljs-string">'abc'</span>), list(<span class="hljs-string">'xyz'</span>)) -<span class="hljs-meta">>>> </span>df.groupby(<span class="hljs-string">'z'</span>).get_group(<span class="hljs-number">6</span>) +<span class="hljs-meta">>>> </span>gb = df.groupby(<span class="hljs-string">'z'</span>); gb.apply(print) + x y z +a <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span> x y z b <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span> -c <span class="hljs-number">7</span> <span class="hljs-number">8</span> <span class="hljs-number">6</span> -</code></pre></div> +c <span class="hljs-number">7</span> <span class="hljs-number">8</span> <span class="hljs-number">6</span></code></pre></div> -<pre><code class="python language-python hljs"><GB> = <DF>.groupby(column_key/s) <span class="hljs-comment"># Splits DF into groups based on passed column.</span> +<pre><code class="python language-python hljs"><GB> = <DF>.groupby(col_key/s) <span class="hljs-comment"># Splits DF into groups based on passed column.</span> <DF> = <GB>.apply(<func>) <span class="hljs-comment"># Maps each group. Func can return DF, Sr or el.</span> -<GB> = <GB>[column_key] <span class="hljs-comment"># Single column GB. All operations return a Sr.</span> +<DF> = <GB>.get_group(<el>) <span class="hljs-comment"># Selects a group by grouping column's value.</span> <Sr> = <GB>.size() <span class="hljs-comment"># A Sr of group sizes. Same keys as get_group().</span> +<GB> = <GB>[col_key] <span class="hljs-comment"># Single column GB. All operations return a Sr.</span> </code></pre> <div><h4 id="groupbyaggregatetransformmap">GroupBy — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs"><DF> = <GB>.sum/max/mean/idxmax/all() <span class="hljs-comment"># Or: <GB>.agg(lambda <Sr>: <el>)</span> <DF> = <GB>.rank/diff/cumsum/ffill() <span class="hljs-comment"># Or: <GB>.transform(lambda <Sr>: <Sr>)</span> <DF> = <GB>.fillna(<el>) <span class="hljs-comment"># Or: <GB>.transform(lambda <Sr>: <Sr>)</span> </code></pre></div> -<pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>gb = df.groupby(<span class="hljs-string">'z'</span>); gb.apply(print) - x y z -a <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span> - x y z -b <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span> -c <span class="hljs-number">7</span> <span class="hljs-number">8</span> <span class="hljs-number">6</span></code></pre> -<pre><code class="python hljs">┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ -┃ │ <span class="hljs-string">'sum'</span> │ <span class="hljs-string">'rank'</span> │ [<span class="hljs-string">'rank'</span>] │ {<span class="hljs-string">'x'</span>: <span class="hljs-string">'rank'</span>} ┃ -┠─────────────────┼─────────────┼─────────────┼─────────────┼───────────────┨ -┃ gb.agg(…) │ x y │ │ x y │ ┃ -┃ │ z │ x y │ rank rank │ x ┃ -┃ │ <span class="hljs-number">3</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span> │ a <span class="hljs-number">1</span> <span class="hljs-number">1</span> │ a <span class="hljs-number">1</span> <span class="hljs-number">1</span> │ a <span class="hljs-number">1</span> ┃ -┃ │ <span class="hljs-number">6</span> <span class="hljs-number">11</span> <span class="hljs-number">13</span> │ b <span class="hljs-number">1</span> <span class="hljs-number">1</span> │ b <span class="hljs-number">1</span> <span class="hljs-number">1</span> │ b <span class="hljs-number">1</span> ┃ -┃ │ │ c <span class="hljs-number">2</span> <span class="hljs-number">2</span> │ c <span class="hljs-number">2</span> <span class="hljs-number">2</span> │ c <span class="hljs-number">2</span> ┃ -┠─────────────────┼─────────────┼─────────────┼─────────────┼───────────────┨ -┃ gb.transform(…) │ x y │ x y │ │ ┃ -┃ │ a <span class="hljs-number">1</span> <span class="hljs-number">2</span> │ a <span class="hljs-number">1</span> <span class="hljs-number">1</span> │ │ ┃ -┃ │ b <span class="hljs-number">11</span> <span class="hljs-number">13</span> │ b <span class="hljs-number">1</span> <span class="hljs-number">1</span> │ │ ┃ -┃ │ c <span class="hljs-number">11</span> <span class="hljs-number">13</span> │ c <span class="hljs-number">2</span> <span class="hljs-number">2</span> │ │ ┃ -┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ +<pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>gb.sum() + x y +z +<span class="hljs-number">3</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span> +<span class="hljs-number">6</span> <span class="hljs-number">11</span> <span class="hljs-number">13</span> </code></pre> +<ul> +<li><strong>Result has a named index that creates column <code class="python hljs"><span class="hljs-string">'z'</span></code> instead of <code class="python hljs"><span class="hljs-string">'index'</span></code> on reset_index().</strong></li> +</ul> <div><h3 id="rolling">Rolling</h3><p><strong>Object for rolling window calculations.</strong></p><pre><code class="python language-python hljs"><RSr/RDF/RGB> = <Sr/DF/GB>.rolling(win_size) <span class="hljs-comment"># Also: `min_periods=None, center=False`.</span> -<RSr/RDF/RGB> = <RDF/RGB>[column_key/s] <span class="hljs-comment"># Or: <RDF/RGB>.column_key</span> +<RSr/RDF/RGB> = <RDF/RGB>[col_key/s] <span class="hljs-comment"># Or: <RDF/RGB>.col_key</span> <Sr/DF> = <R>.mean/sum/max() <span class="hljs-comment"># Or: <R>.apply/agg(<agg_func/str>)</span> </code></pre></div> -<div><h2 id="plotly"><a href="#plotly" name="plotly">#</a>Plotly</h2><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pandas plotly kaleido</span> -<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd, plotly.express <span class="hljs-keyword">as</span> ex -<Figure> = ex.line(<DF>, x=<col_name>, y=<col_name>) <span class="hljs-comment"># Or: ex.line(x=<list>, y=<list>)</span> -<Figure>.update_layout(margin=dict(t=<span class="hljs-number">0</span>, r=<span class="hljs-number">0</span>, b=<span class="hljs-number">0</span>, l=<span class="hljs-number">0</span>), …) <span class="hljs-comment"># `paper_bgcolor='rgb(0, 0, 0)'`.</span> -<Figure>.write_html/json/image(<span class="hljs-string">'<path>'</span>) <span class="hljs-comment"># Also <Figure>.show().</span> +<div><h2 id="plotly"><a href="#plotly" name="plotly">#</a>Plotly</h2><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install plotly kaleido pandas</span> +<span class="hljs-keyword">import</span> plotly.express <span class="hljs-keyword">as</span> px, pandas <span class="hljs-keyword">as</span> pd </code></pre></div> +<pre><code class="python language-python hljs"><Fig> = px.line(<DF>, x=col_key, y=col_key) <span class="hljs-comment"># Or: px.line(x=<list>, y=<list>)</span> +<Fig>.update_layout(margin=dict(t=<span class="hljs-number">0</span>, r=<span class="hljs-number">0</span>, b=<span class="hljs-number">0</span>, l=<span class="hljs-number">0</span>)) <span class="hljs-comment"># Also `paper_bgcolor='rgb(0, 0, 0)'`.</span> +<Fig>.write_html/json/image(<span class="hljs-string">'<path>'</span>) <span class="hljs-comment"># Also <Fig>.show().</span> +</code></pre> +<pre><code class="python language-python hljs"><Fig> = px.area/bar/box(<DF>, x=col_key, y=col_key) <span class="hljs-comment"># Also `color=col_key`.</span> +<Fig> = px.scatter(<DF>, x=col_key, y=col_key) <span class="hljs-comment"># Also `color/size/symbol=col_key`.</span> +<Fig> = px.scatter_3d(<DF>, x=col_key, y=col_key, …) <span class="hljs-comment"># `z=col_key`. Also color/size/symbol.</span> +<Fig> = px.histogram(<DF>, x=col_key [, nbins=<int>]) <span class="hljs-comment"># Number of bins depends on DF size.</span> +</code></pre> <div><h4 id="displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">Displays a line chart of total coronavirus deaths per million grouped by continent:</h4><p></p><div id="2a950764-39fc-416d-97fe-0a6226a3095f" class="plotly-graph-div" style="height:312px; width:914px;"></div><pre><code class="python language-python hljs">covid = pd.read_csv(<span class="hljs-string">'https://raw.githubusercontent.com/owid/covid-19-data/8dde8ca49b'</span> <span class="hljs-string">'6e648c17dd420b2726ca0779402651/public/data/owid-covid-data.csv'</span>, usecols=[<span class="hljs-string">'iso_code'</span>, <span class="hljs-string">'date'</span>, <span class="hljs-string">'total_deaths'</span>, <span class="hljs-string">'population'</span>]) @@ -2811,7 +2804,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment df[<span class="hljs-string">'Total Deaths per Million'</span>] = df.total_deaths * <span class="hljs-number">1e6</span> / df.population df = df[df.date > <span class="hljs-string">'2020-03-14'</span>] df = df.rename({<span class="hljs-string">'date'</span>: <span class="hljs-string">'Date'</span>, <span class="hljs-string">'Continent_Name'</span>: <span class="hljs-string">'Continent'</span>}, axis=<span class="hljs-string">'columns'</span>) -ex.line(df, x=<span class="hljs-string">'Date'</span>, y=<span class="hljs-string">'Total Deaths per Million'</span>, color=<span class="hljs-string">'Continent'</span>).show() +px.line(df, x=<span class="hljs-string">'Date'</span>, y=<span class="hljs-string">'Total Deaths per Million'</span>, color=<span class="hljs-string">'Continent'</span>).show() </code></pre></div> @@ -2820,20 +2813,23 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main</span><span class="hljs-params">()</span>:</span> covid, bitcoin, gold, dow = scrape_data() - display_data(wrangle_data(covid, bitcoin, gold, dow)) + df = wrangle_data(covid, bitcoin, gold, dow) + display_data(df) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">scrape_data</span><span class="hljs-params">()</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_covid_cases</span><span class="hljs-params">()</span>:</span> url = <span class="hljs-string">'https://covid.ourworldindata.org/data/owid-covid-data.csv'</span> df = pd.read_csv(url, usecols=[<span class="hljs-string">'location'</span>, <span class="hljs-string">'date'</span>, <span class="hljs-string">'total_cases'</span>]) - <span class="hljs-keyword">return</span> df[df.location == <span class="hljs-string">'World'</span>].set_index(<span class="hljs-string">'date'</span>).total_cases + df = df[df.location == <span class="hljs-string">'World'</span>] + <span class="hljs-keyword">return</span> df.set_index(<span class="hljs-string">'date'</span>).total_cases <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_ticker</span><span class="hljs-params">(symbol)</span>:</span> url = (<span class="hljs-string">f'https://query1.finance.yahoo.com/v7/finance/download/<span class="hljs-subst">{symbol}</span>?'</span> <span class="hljs-string">'period1=1579651200&period2=9999999999&interval=1d&events=history'</span>) df = pd.read_csv(url, usecols=[<span class="hljs-string">'Date'</span>, <span class="hljs-string">'Close'</span>]) <span class="hljs-keyword">return</span> df.set_index(<span class="hljs-string">'Date'</span>).Close out = get_covid_cases(), get_ticker(<span class="hljs-string">'BTC-USD'</span>), get_ticker(<span class="hljs-string">'GC=F'</span>), get_ticker(<span class="hljs-string">'^DJI'</span>) - <span class="hljs-keyword">return</span> map(pd.Series.rename, out, [<span class="hljs-string">'Total Cases'</span>, <span class="hljs-string">'Bitcoin'</span>, <span class="hljs-string">'Gold'</span>, <span class="hljs-string">'Dow Jones'</span>]) + names = [<span class="hljs-string">'Total Cases'</span>, <span class="hljs-string">'Bitcoin'</span>, <span class="hljs-string">'Gold'</span>, <span class="hljs-string">'Dow Jones'</span>] + <span class="hljs-keyword">return</span> map(pd.Series.rename, out, names) <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrangle_data</span><span class="hljs-params">(covid, bitcoin, gold, dow)</span>:</span> df = pd.concat([bitcoin, gold, dow], axis=<span class="hljs-number">1</span>) <span class="hljs-comment"># Creates table by joining columns on dates.</span> @@ -2927,11 +2923,12 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <div><h2 id="index"><a href="#index" name="index">#</a>Index</h2><ul><li><strong>Only available in the <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">PDF</a>.</strong></li> <li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li> <li><strong>Searching <code class="python hljs"><span class="hljs-string">'#<title>'</span></code> will limit the search to the titles.</strong></li> +<li><strong>Click on the <code class="python hljs"><span class="hljs-string">'#'</span></code> symbol to get a link to specific section.</strong></li> </ul></div> <footer> - <aside>September 27, 2024</aside> + <aside>October 28, 2024</aside> <a href="https://gto76.github.io" rel="author">Jure Šorn</a> </footer> diff --git a/parse.js b/parse.js index af0bb1bdd..bb68554f1 100755 --- a/parse.js +++ b/parse.js @@ -30,9 +30,7 @@ const hljs = require('highlightjs'); const TOC = - '<br>' + - '<h2 id="toc">Contents</h2>\n' + - '<pre><code class="hljs bash" style="line-height: 1.327em;"><strong>ToC</strong> = {\n' + + '<pre style="border-left: none;padding-left: 1.9px;"><code class="hljs bash" style="line-height: 1.327em;"><strong>ToC</strong> = {\n' + ' <strong><span class="hljs-string">\'1. Collections\'</span></strong>: [<a href="#list">List</a>, <a href="#dictionary">Dictionary</a>, <a href="#set">Set</a>, <a href="#tuple">Tuple</a>, <a href="#range">Range</a>, <a href="#enumerate">Enumerate</a>, <a href="#iterator">Iterator</a>, <a href="#generator">Generator</a>],\n' + ' <strong><span class="hljs-string">\'2. Types\'</span></strong>: [<a href="#type">Type</a>, <a href="#string">String</a>, <a href="#regex">Regular_Exp</a>, <a href="#format">Format</a>, <a href="#numbers">Numbers</a>, <a href="#combinatorics">Combinatorics</a>, <a href="#datetime">Datetime</a>],\n' + ' <strong><span class="hljs-string">\'3. Syntax\'</span></strong>: [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>],\n' + @@ -50,12 +48,12 @@ const BIN_HEX = '<int> = int(<span class="hljs-string">\'±0b<bin>\'</span>, <span class="hljs-number">0</span>) <span class="hljs-comment"># Or: int(\'±0x<hex>\', 0)</span>\n' + '<str> = bin(<int>) <span class="hljs-comment"># Returns \'[-]0b<bin>\'. Also hex().</span>\n'; -const LRU_CACHE = - '<span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> lru_cache\n' + +const CACHE = + '<span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> cache\n' + '\n' + - '<span class="hljs-meta">@lru_cache(maxsize=None)</span>\n' + + '<span class="hljs-meta">@cache</span>\n' + '<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">fib</span><span class="hljs-params">(n)</span>:</span>\n' + - ' <span class="hljs-keyword">return</span> n <span class="hljs-keyword">if</span> n < <span class="hljs-number">2</span> <span class="hljs-keyword">else</span> fib(n-<span class="hljs-number">2</span>) + fib(n-<span class="hljs-number">1</span>)\n'; + ' <span class="hljs-keyword">return</span> n <span class="hljs-keyword">if</span> n < <span class="hljs-number">2</span> <span class="hljs-keyword">else</span> fib(n-<span class="hljs-number">2</span>) + fib(n-<span class="hljs-number">1</span>)'; const PARAMETRIZED_DECORATOR = '<span class="hljs-keyword">from</span> functools <span class="hljs-keyword">import</span> wraps\n' + @@ -114,11 +112,9 @@ const MATCH_EXAMPLE = '<span class="hljs-meta">>>> </span><span class="hljs-keyword">from</span> pathlib <span class="hljs-keyword">import</span> Path\n' + '<span class="hljs-meta">>>> </span><span class="hljs-keyword">match</span> Path(<span class="hljs-string">\'/home/gto/python-cheatsheet/README.md\'</span>):\n' + '<span class="hljs-meta">... </span> <span class="hljs-keyword">case</span> Path(\n' + - '<span class="hljs-meta">... </span> parts=[<span class="hljs-string">\'/\'</span>, <span class="hljs-string">\'home\'</span>, user, *_],\n' + - '<span class="hljs-meta">... </span> stem=stem,\n' + - '<span class="hljs-meta">... </span> suffix=(<span class="hljs-string">\'.md\'</span> | <span class="hljs-string">\'.txt\'</span>) <span class="hljs-keyword">as</span> suffix\n' + - '<span class="hljs-meta">... </span> ) <span class="hljs-keyword">if</span> stem.lower() == <span class="hljs-string">\'readme\'</span>:\n' + - '<span class="hljs-meta">... </span> print(<span class="hljs-string">f\'<span class="hljs-subst">{stem}</span><span class="hljs-subst">{suffix}</span> is a readme file that belongs to user <span class="hljs-subst">{user}</span>.\'</span>)\n' + + '<span class="hljs-meta">... </span> parts=[<span class="hljs-string">\'/\'</span>, <span class="hljs-string">\'home\'</span>, user, *_]\n' + + '<span class="hljs-meta">... </span> ) <span class="hljs-keyword">as</span> p <span class="hljs-keyword">if</span> p.name.lower().startswith(<span class="hljs-string">\'readme\'</span>) <span class="hljs-keyword">and</span> p.is_file():\n' + + '<span class="hljs-meta">... </span> print(<span class="hljs-string">f\'<span class="hljs-subst">{p.name}</span> is a readme file that belongs to user <span class="hljs-subst">{user}</span>.\'</span>)\n' + '<span class="hljs-string">\'README.md is a readme file that belongs to user gto.\'</span>\n'; const COROUTINES = @@ -135,7 +131,7 @@ const COROUTINES = '\n' + '<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">main_coroutine</span><span class="hljs-params">(screen)</span>:</span>\n' + ' moves = asyncio.Queue()\n' + - ' state = {<span class="hljs-string">\'*\'</span>: P(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>), **{id_: P(W//<span class="hljs-number">2</span>, H//<span class="hljs-number">2</span>) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)}}\n' + + ' state = {<span class="hljs-string">\'*\'</span>: P(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>)} | {id_: P(W//<span class="hljs-number">2</span>, H//<span class="hljs-number">2</span>) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)}\n' + ' ai = [random_controller(id_, moves) <span class="hljs-keyword">for</span> id_ <span class="hljs-keyword">in</span> range(<span class="hljs-number">10</span>)]\n' + ' mvc = [human_controller(screen, moves), model(moves, state), view(state, screen)]\n' + ' tasks = [asyncio.create_task(coro) <span class="hljs-keyword">for</span> coro <span class="hljs-keyword">in</span> ai + mvc]\n' + @@ -220,7 +216,20 @@ const LOGGING_EXAMPLE = '<span class="hljs-meta">>>> </span>print(open(<span class="hljs-string">\'test.log\'</span>).read())\n' + '2023-02-07 23:21:01,430 CRITICAL:my_module:Running out of disk space.\n'; -const AUDIO = +const AUDIO_1 = + '<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_wav_file</span><span class="hljs-params">(filename, samples_f, p=<span class="hljs-keyword">None</span>, nchannels=<span class="hljs-number">1</span>, sampwidth=<span class="hljs-number">2</span>, framerate=<span class="hljs-number">44100</span>)</span>:</span>\n' + + ' <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_bytes</span><span class="hljs-params">(a_float)</span>:</span>\n' + + ' a_float = max(<span class="hljs-number">-1</span>, min(<span class="hljs-number">1</span> - <span class="hljs-number">2e-16</span>, a_float))\n' + + ' a_float += p.sampwidth == <span class="hljs-number">1</span>\n' + + ' a_float *= pow(<span class="hljs-number">2</span>, p.sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>)\n' + + ' <span class="hljs-keyword">return</span> int(a_float).to_bytes(p.sampwidth, <span class="hljs-string">\'little\'</span>, signed=(p.sampwidth != <span class="hljs-number">1</span>))\n' + + ' <span class="hljs-keyword">if</span> p <span class="hljs-keyword">is</span> <span class="hljs-keyword">None</span>:\n' + + ' p = wave._wave_params(nchannels, sampwidth, framerate, <span class="hljs-number">0</span>, <span class="hljs-string">\'NONE\'</span>, <span class="hljs-string">\'not compressed\'</span>)\n' + + ' <span class="hljs-keyword">with</span> wave.open(filename, <span class="hljs-string">\'wb\'</span>) <span class="hljs-keyword">as</span> file:\n' + + ' file.setparams(p)\n' + + ' file.writeframes(<span class="hljs-string">b\'\'</span>.join(get_bytes(f) <span class="hljs-keyword">for</span> f <span class="hljs-keyword">in</span> samples_f))\n'; + +const AUDIO_2 = '<span class="hljs-keyword">from</span> math <span class="hljs-keyword">import</span> pi, sin\n' + 'samples_f = (sin(i * <span class="hljs-number">2</span> * pi * <span class="hljs-number">440</span> / <span class="hljs-number">44100</span>) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">100_000</span>))\n' + 'write_to_wav_file(<span class="hljs-string">\'test.wav\'</span>, samples_f)\n'; @@ -291,7 +300,7 @@ const MARIO = ' mario.facing_left = mario.spd.x < <span class="hljs-number">0</span> <span class="hljs-keyword">if</span> mario.spd.x <span class="hljs-keyword">else</span> mario.facing_left\n' + ' is_airborne = D.s <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> get_boundaries(mario.rect, tiles)\n' + ' image_index = <span class="hljs-number">4</span> <span class="hljs-keyword">if</span> is_airborne <span class="hljs-keyword">else</span> (next(mario.frame_cycle) <span class="hljs-keyword">if</span> mario.spd.x <span class="hljs-keyword">else</span> <span class="hljs-number">6</span>)\n' + - ' screen.blit(images[image_index + mario.facing_left * <span class="hljs-number">9</span>], mario.rect)\n' + + ' screen.blit(images[image_index + (mario.facing_left * <span class="hljs-number">9</span>)], mario.rect)\n' + ' <span class="hljs-keyword">for</span> t <span class="hljs-keyword">in</span> tiles:\n' + ' is_border = t.x <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span>, (W-<span class="hljs-number">1</span>)*<span class="hljs-number">16</span>] <span class="hljs-keyword">or</span> t.y <span class="hljs-keyword">in</span> [<span class="hljs-number">0</span>, (H-<span class="hljs-number">1</span>)*<span class="hljs-number">16</span>]\n' + ' screen.blit(images[<span class="hljs-number">18</span> <span class="hljs-keyword">if</span> is_border <span class="hljs-keyword">else</span> <span class="hljs-number">19</span>], t)\n' + @@ -301,6 +310,7 @@ const MARIO = ' main()\n'; const GROUPBY = + '<span class="hljs-meta">>>> </span>df = pd.DataFrame([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>], [<span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">6</span>]], list(<span class="hljs-string">\'abc\'</span>), list(<span class="hljs-string">\'xyz\'</span>))\n' + '<span class="hljs-meta">>>> </span>gb = df.groupby(<span class="hljs-string">\'z\'</span>); gb.apply(print)\n' + ' x y z\n' + 'a <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span>\n' + @@ -325,7 +335,8 @@ const CYTHON_3 = const INDEX = '<li><strong>Only available in the <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">PDF</a>.</strong></li>\n' + '<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>\n' + - '<li><strong>Searching <code class="python hljs"><span class="hljs-string">\'#<title>\'</span></code> will limit the search to the titles.</strong></li>\n'; + '<li><strong>Searching <code class="python hljs"><span class="hljs-string">\'#<title>\'</span></code> will limit the search to the titles.</strong></li>\n' + + '<li><strong>Click on the <code class="python hljs"><span class="hljs-string">\'#\'</span></code> symbol to get a link to specific section.</strong></li>\n'; const DIAGRAM_1_A = @@ -487,19 +498,19 @@ const DIAGRAM_9_B = "┗━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┛\n"; const DIAGRAM_95_A = - '+------------+--------------+----------+----------------------------------+\n' + - '| Dialect | pip3 install | import | Dependencies |\n' + - '+------------+--------------+----------+----------------------------------+\n'; + '+-----------------+--------------+----------------------------------+\n' + + '| Dialect | pip3 install | Dependencies |\n' + + '+-----------------+--------------+----------------------------------+\n'; const DIAGRAM_95_B = - '┏━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n' + - '┃ Dialect │ pip3 install │ import │ Dependencies ┃\n' + - '┠────────────┼──────────────┼──────────┼──────────────────────────────────┨\n' + - '┃ mysql │ mysqlclient │ MySQLdb │ www.pypi.org/project/mysqlclient ┃\n' + - '┃ postgresql │ psycopg2 │ psycopg2 │ www.pypi.org/project/psycopg2 ┃\n' + - '┃ mssql │ pyodbc │ pyodbc │ www.pypi.org/project/pyodbc ┃\n' + - '┃ oracle │ oracledb │ oracledb │ www.pypi.org/project/oracledb ┃\n' + - '┗━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n'; + '┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n' + + '┃ Dialect │ pip3 install │ Dependencies ┃\n' + + '┠─────────────────┼──────────────┼──────────────────────────────────┨\n' + + '┃ mysql │ mysqlclient │ www.pypi.org/project/mysqlclient ┃\n' + + '┃ postgresql │ psycopg2 │ www.pypi.org/project/psycopg2 ┃\n' + + '┃ mssql │ pyodbc │ www.pypi.org/project/pyodbc ┃\n' + + '┃ oracle+oracledb │ oracledb │ www.pypi.org/project/oracledb ┃\n' + + '┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n'; const DIAGRAM_10_A = '+-------------+-------------+\n' + @@ -763,6 +774,7 @@ function insertLinks() { function unindentBanner() { const montyImg = $('img').first(); montyImg.parent().addClass('banner'); + montyImg.parent().css({"margin-bottom": "20px", "padding-bottom": "7px"}) const downloadPraragrapth = $('p').first(); downloadPraragrapth.addClass('banner'); } @@ -825,7 +837,7 @@ function fixClasses() { function fixHighlights() { $(`code:contains(<int> = ±0b<bin>)`).html(BIN_HEX); - $(`code:contains(@lru_cache(maxsize=None))`).html(LRU_CACHE); + $(`code:contains( + fib(n)`).html(CACHE); $(`code:contains(@debug(print_result=True))`).html(PARAMETRIZED_DECORATOR); $(`code:contains(print/str/repr([<obj>]))`).html(REPR_USE_CASES); $(`code:contains((self, a=None):)`).html(CONSTRUCTOR_OVERLOADING); @@ -839,7 +851,8 @@ function fixHighlights() { $(`code:contains(import curses, os)`).html(CURSES); $(`code:contains(pip3 install tqdm)`).html(PROGRESS_BAR); $(`code:contains(>>> log.basicConfig()`).html(LOGGING_EXAMPLE); - $(`code:contains(samples_f = (sin(i *)`).html(AUDIO); + $(`code:contains(a_float = max()`).html(AUDIO_1); + $(`code:contains(samples_f = (sin(i *)`).html(AUDIO_2); $(`code:contains(collections, dataclasses, enum, io, itertools)`).html(MARIO); $(`code:contains(>>> gb = df.groupby)`).html(GROUPBY); $(`code:contains(cdef <ctype> <var_name> = <obj>)`).html(CYTHON_1); diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html index a22309427..54f6747f0 100644 --- a/pdf/index_for_pdf.html +++ b/pdf/index_for_pdf.html @@ -17,7 +17,7 @@ <h3 id="b">B</h3> <strong>bitwise operators, <a href="#bitwiseoperators">8</a>, <a href="#operator">31</a></strong><br> <strong>bytes, <a href="#open">22</a>-<a href="#modes">23</a>, <a href="#pickle">25</a>, <a href="#bytes">28</a>-<a href="#memoryview">29</a></strong> </p> <h3 id="c">C</h3> -<p><strong>cache, <a href="#lrucache">13</a></strong><br> +<p><strong>cache, <a href="#cache">13</a></strong><br> <strong>callable, <a href="#callable">17</a></strong><br> <strong>class, <a href="#type">4</a>, <a href="#class">14</a>-<a href="#inline-1">20</a></strong><br> <strong>closure, <a href="#closure">12</a>-<a href="#decorator">13</a></strong><br> @@ -30,9 +30,9 @@ <h3 id="c">C</h3> <strong>copy function, <a href="#copy">15</a></strong><br> <strong>coroutine, <a href="#coroutines">33</a></strong><br> <strong>counter, <a href="#counter">2</a>, <a href="#generator">4</a>, <a href="#nonlocal">12</a>, <a href="#iterator-1">17</a></strong><br> -<strong>csv, <a href="#csv">26</a>, <a href="#printsacsvspreadsheettotheconsole">34</a>, <a href="#dataframeplotencodedecode">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a></strong><br> +<strong>csv, <a href="#csv">26</a>, <a href="#printsacsvspreadsheettotheconsole">34</a>, <a href="#dataframeencodedecode">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a></strong><br> <strong>curses module, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a>, <a href="#consoleapp">34</a></strong><br> -<strong>cython, <a href="#cython">49</a></strong> </p> +<strong>cython, <a href="#typeannotations">15</a>, <a href="#cython">49</a></strong> </p> <h3 id="d">D</h3> <p><strong>dataclasses module, <a href="#namedtupleenumdataclass">12</a>, <a href="#dataclass">15</a></strong><br> <strong>datetime module, <a href="#datetime">8</a>-<a href="#now">9</a></strong><br> @@ -43,13 +43,13 @@ <h3 id="d">D</h3> <h3 id="e">E</h3> <p><strong>enum module, <a href="#enum">19</a>-<a href="#inline-1">20</a></strong><br> <strong>enumerate function, <a href="#enumerate">3</a></strong><br> -<strong>excel, <a href="#dataframeplotencodedecode">46</a></strong><br> +<strong>excel, <a href="#dataframeencodedecode">46</a></strong><br> <strong>exceptions, <a href="#exceptions">20</a>-<a href="#exceptionobject">21</a>, <a href="#exceptions-1">23</a>, <a href="#logging">32</a></strong><br> <strong>exit function, <a href="#exit">21</a></strong> </p> <h3 id="f">F</h3> -<p><strong>files, <a href="#print">22</a>-<a href="#memoryview">29</a>, <a href="#runsabasicfileexplorerintheconsole">34</a>, <a href="#dataframeplotencodedecode">46</a></strong><br> +<p><strong>files, <a href="#print">22</a>-<a href="#memoryview">29</a>, <a href="#runsabasicfileexplorerintheconsole">34</a>, <a href="#dataframeencodedecode">46</a></strong><br> <strong>filter function, <a href="#mapfilterreduce">11</a></strong><br> -<strong>flask library, <a href="#web">36</a></strong><br> +<strong>flask library, <a href="#webapp">36</a></strong><br> <strong>floats, <a href="#abstractbaseclasses">4</a>, <a href="#floats">6</a>, <a href="#numbers">7</a></strong><br> <strong>format, <a href="#format">6</a>-<a href="#comparisonofpresentationtypes">7</a></strong><br> <strong>functools module, <a href="#mapfilterreduce">11</a>, <a href="#partial">12</a>, <a href="#debuggerexample">13</a>, <a href="#sortable">16</a></strong> </p> @@ -73,7 +73,7 @@ <h3 id="i">I</h3> <strong>iterator, <a href="#enumerate">3</a>-<a href="#generator">4</a>, <a href="#comprehensions">11</a>, <a href="#iterator-1">17</a></strong><br> <strong>itertools module, <a href="#itertools">3</a>, <a href="#combinatorics">8</a></strong> </p> <h3 id="j">J</h3> -<p><strong>json, <a href="#json">25</a>, <a href="#restrequest">36</a>, <a href="#dataframeplotencodedecode">46</a></strong> </p> +<p><strong>json, <a href="#json">25</a>, <a href="#restrequest">36</a>, <a href="#dataframeencodedecode">46</a></strong> </p> <h3 id="l">L</h3> <p><strong>lambda, <a href="#lambda">11</a></strong><br> <strong>lists, <a href="#list">1</a>-<a href="#list">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br> @@ -82,7 +82,7 @@ <h3 id="l">L</h3> <h3 id="m">M</h3> <p><strong>main function, <a href="#main">1</a>, <a href="#basicscripttemplate">49</a></strong><br> <strong>match statement, <a href="#matchstatement">31</a></strong><br> -<strong>matplotlib library, <a href="#plot">34</a>, <a href="#series">44</a>, <a href="#dataframeplotencodedecode">46</a></strong><br> +<strong>matplotlib library, <a href="#plot">34</a>, <a href="#series">44</a>, <a href="#dataframeencodedecode">46</a></strong><br> <strong>map function, <a href="#mapfilterreduce">11</a>, <a href="#operator">31</a></strong><br> <strong>math module, <a href="#numbers">7</a></strong><br> <strong>memoryviews, <a href="#memoryview">29</a></strong><br> @@ -102,7 +102,7 @@ <h3 id="p">P</h3> <strong>paths, <a href="#paths">23</a>-<a href="#oscommands">24</a>, <a href="#runsabasicfileexplorerintheconsole">34</a></strong><br> <strong>pickle module, <a href="#pickle">25</a></strong><br> <strong>pillow library, <a href="#image">39</a>-<a href="#animation">40</a></strong><br> -<strong>plotting, <a href="#plot">34</a>, <a href="#series">44</a>, <a href="#dataframeplotencodedecode">46</a>, <a href="#plotly">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br> +<strong>plotting, <a href="#plot">34</a>, <a href="#series">44</a>, <a href="#dataframeencodedecode">46</a>, <a href="#plotly">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br> <strong>print function, <a href="#class">14</a>, <a href="#print">22</a></strong><br> <strong>profiling, <a href="#profiling">36</a>-<a href="#profilingbyline">37</a></strong><br> <strong>progress bar, <a href="#progressbar">34</a></strong><br> @@ -113,26 +113,26 @@ <h3 id="q">Q</h3> <h3 id="r">R</h3> <p><strong>random module, <a href="#random">8</a></strong><br> <strong>ranges, <a href="#range">3</a>, <a href="#abstractbaseclasses">4</a></strong><br> -<strong>recursion, <a href="#lrucache">13</a>, <a href="#builtinexceptions">21</a></strong><br> +<strong>recursion, <a href="#cache">13</a>, <a href="#builtinexceptions">21</a></strong><br> <strong>reduce function, <a href="#mapfilterreduce">11</a>, <a href="#operator">31</a></strong><br> <strong>regular expressions, <a href="#regex">5</a>-<a href="#specialsequences">6</a></strong><br> <strong>requests library, <a href="#scrapespythonsurlandlogofromitswikipediapage">35</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong> </p> <h3 id="s">S</h3> <p><strong>scope, <a href="#insidefunctiondefinition">10</a>, <a href="#nonlocal">12</a>, <a href="#complexexample">20</a></strong><br> -<strong>scraping, <a href="#scraping">35</a>, <a href="#basicmariobrothersexample">43</a>, <a href="#dataframeplotencodedecode">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br> +<strong>scraping, <a href="#scraping">35</a>, <a href="#basicmariobrothersexample">43</a>, <a href="#dataframeencodedecode">46</a>, <a href="#displaysalinechartoftotalcoronavirusdeathspermilliongroupedbycontinent">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br> <strong>sequence, <a href="#abstractbaseclasses">4</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a></strong><br> <strong>sets, <a href="#set">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br> <strong>shell commands, <a href="#shellcommands">25</a></strong><br> <strong>sleep function, <a href="#progressbar">34</a></strong><br> <strong>sortable, <a href="#list">1</a>, <a href="#sortable">16</a></strong><br> <strong>splat operator, <a href="#splatoperator">10</a>-<a href="#otheruses">11</a>, <a href="#readrowsfromcsvfile">26</a></strong><br> -<strong>sql, <a href="#sqlite">27</a>, <a href="#dataframeplotencodedecode">46</a></strong><br> +<strong>sql, <a href="#sqlite">27</a>, <a href="#dataframeencodedecode">46</a></strong><br> <strong>statistics, <a href="#statistics">7</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#pandas">44</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br> <strong>strings, <a href="#abstractbaseclasses">4</a>-<a href="#comparisonofpresentationtypes">7</a>, <a href="#class">14</a></strong><br> <strong>struct module, <a href="#struct">28</a>-<a href="#integertypesuseacapitalletterforunsignedtypeminimumandstandardsizesareinbrackets">29</a></strong><br> <strong>subprocess module, <a href="#sends11tothebasiccalculatorandcapturesitsoutput">25</a></strong><br> <strong>super function, <a href="#inheritance">14</a></strong><br> -<strong>sys module, <a href="#lrucache">13</a>, <a href="#exit">21</a>-<a href="#commandlinearguments">22</a></strong> </p> +<strong>sys module, <a href="#cache">13</a>, <a href="#exit">21</a>-<a href="#commandlinearguments">22</a></strong> </p> <h3 id="t">T</h3> <p><strong>table, <a href="#csv">26</a>, <a href="#example-1">27</a>, <a href="#table">34</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#dataframe">45</a>-<a href="#dataframeaggregatetransformmap">46</a></strong><br> <strong>template, <a href="#format">6</a>, <a href="#dynamicrequest">36</a></strong><br> @@ -143,5 +143,5 @@ <h3 id="t">T</h3> <strong>type annotations, <a href="#typeannotations">15</a>, <a href="#introspection">32</a></strong> </p> <h3 id="w">W</h3> <p><strong>wave module, <a href="#audio">40</a>-<a href="#writefloatsamplestowavfile">41</a></strong><br> -<strong>web, <a href="#web">36</a></strong> </p> +<strong>web, <a href="#webapp">36</a></strong> </p> </div> \ No newline at end of file diff --git a/pdf/index_for_pdf_print.html b/pdf/index_for_pdf_print.html index 735664176..e7bdcfeb7 100644 --- a/pdf/index_for_pdf_print.html +++ b/pdf/index_for_pdf_print.html @@ -32,7 +32,7 @@ <h3 id="c">C</h3> <strong>counter, 2, 4, 12, 17</strong><br> <strong>csv, 26, 34, 46, 47</strong><br> <strong>curses module, 33, 34</strong><br> -<strong>cython, 49</strong> </p> +<strong>cython, 15, 49</strong> </p> <h3 id="d">D</h3> <p><strong>dataclasses module, 12, 15</strong><br> <strong>datetime module, 8-9</strong><br> diff --git a/web/faq.html b/web/faq.html index 349678c06..6192ebd30 100644 --- a/web/faq.html +++ b/web/faq.html @@ -1,25 +1,22 @@ <details open><summary><strong>Which Python version is this for?</strong></summary><br> -    Everything should work in the latest Python version, which is 3.12. Every feature that requires version higher than 3.8 has that mentioned in comments or brackets. There are only six such features, four requiring 3.9, and two requiring 3.10.<br><br> -    As of 12th March 2024, the only libraries whose latest version requires Python version higher than 3.8 are: numpy, pandas and matplotlib. They all require Python 3.9. This cheatsheet covers pandas library version 2.0 or higher which was released on 3rd April 2023. +    Everything should work in the latest Python version, which is 3.12. Every feature that requires version higher than 3.9 has that mentioned in comments or brackets. There are only two such features, both requiring 3.10.<br><br> +    As of 12th March 2024, the only libraries whose latest version requires Python version higher than 3.8 are: numpy, pandas and matplotlib. They all require Python 3.9. This cheatsheet covers numpy version 2.0 (or higher) that was released on 16th June, 2024 and pandas version 2.0 (or higher) that was released on 3rd April 2023. </details><br> <details open><summary><strong>How to use it?</strong></summary><br>     This cheatsheet consists of minimal text and short examples so things are easy to find with <code>Ctrl+F</code> / <code>⌘F</code>. If you're on the webpage, searching for <code>'#<name>'</code> will only search for the titles. To get a link to a specific section click the grey hashtag next to the section's title before copying the address. To search for titles in the text editor use <code>^<name></code> with enabled regular expressions option.<br><br>     I also keep the Python console open at all times to test little snippets of code, to check out the available functions of a module using code completion and above all, to use <code>help(<module/object/function/type/str>)</code> command. If something is still unclear, then I search the Python docs by googling <code>'python docs <module/function>'</code>.<br><br> -    Recently I started using the ptpython REPL (Python console). It supports multiline editing, syntax validation, IDE-like autocompletion and syntax highlighting. It can be installed with <code>pip3 install ptpython</code>. +    Recently I started using the ptpython REPL (Python console). It supports multiline editing, syntax validation, IDE-like autocompletion and syntax highlighting. It can be installed with <code>pip3 install ptpython</code>. Even more recently I switched to ipython REPL, which is very similar to ptpython only more responsive. It can be installed with <code>pip3 install ipython</code>. </details><br> <details open><summary><strong>What does the '<type>' signify?</strong></summary><br> -    It is a placeholder for an object. It needs to be replaced by an expression, literal or a variable that returns/is of that type. +    It is a placeholder for an object. It needs to be replaced by an expression, literal or a variable that returns/is of that type. However, if it is located on the left side of an assignment (<code>=</code>) then it signifies what type of object is produced/returned by the expression on the right side of the assignment. </details><br> <details open><summary><strong>Why the '<type>' semantics?</strong></summary><br>     It makes examples much less ambiguous. </details><br> -<details open><summary><strong>Why are some basics like <code>'<list> = [<el_1>, <el_2>, ...]'</code> and <code>'<el> = <list>[<int>]'</code> missing?</strong></summary><br> -    This cheatsheet is not intended for complete beginners. This way it can save some valuable space. Nonetheless, it tries to be simple enough to be useful for somebody who completed the introductory course. A nice one-page cheatsheet that can help you get started can be found <a href="https://github.com/kickstartcoding/cheatsheets/blob/master/build/topical/python.pdf">here</a>.</details><br> - <details open><summary><strong>What exactly is <code><el></code>?</strong></summary><br>     El is short for element and can be any object, but it usually denotes an object that is an item of a collection. </details><br> @@ -52,4 +49,4 @@ <details open><summary><strong>Why are descriptors not covered?</strong></summary><br>     Because property decorator is sufficient for everyday use. -</details><br> +</details><br> \ No newline at end of file diff --git a/web/image_social_4.png b/web/image_social_4.png new file mode 100644 index 000000000..c5d8ff0a9 Binary files /dev/null and b/web/image_social_4.png differ diff --git a/web/script_2.js b/web/script_2.js index 6a64ea5ee..7484625a2 100644 --- a/web/script_2.js +++ b/web/script_2.js @@ -50,22 +50,45 @@ var isMobile = false; // Device detection: if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0,4))) { - isMobile = true; + isMobile = true; } var TOC_SCREEN_WIDTH_CUTOFF = 667 var TOC_EM = '2em' var TOC_EM_DESKTOP = '1.327em' +var PLOTLY_WIDTH_DESKTOP = 914 + + +function switch_to_mobile_view() { + $(`code:contains(ToC)`).html(TOC_MOBILE).css("line-height", TOC_EM); + const body = document.querySelector("body"); + body.style["width"] = `${TOC_SCREEN_WIDTH_CUTOFF+9}px`; + const plotlyDivs = document.querySelectorAll(".plotly-graph-div"); + plotlyDivs.forEach((div) => { + div.style["width"] = `${TOC_SCREEN_WIDTH_CUTOFF}px`; + }); +} + + +function switch_to_desktop_view() { + $(`code:contains(ToC)`).html(TOC).css("line-height", TOC_EM_DESKTOP); + const body = document.querySelector("body"); + body.style["width"] = ""; + const plotlyDivs = document.querySelectorAll(".plotly-graph-div"); + plotlyDivs.forEach((div) => { + div.style["width"] = `${PLOTLY_WIDTH_DESKTOP}px`; + }); +} if (isMobile && window.screen.width < TOC_SCREEN_WIDTH_CUTOFF) { - $(`code:contains(ToC)`).html(TOC_MOBILE).css("line-height", TOC_EM); + switch_to_mobile_view() } function updateToc() { if (isMobile && window.screen.width < TOC_SCREEN_WIDTH_CUTOFF) { - $(`code:contains(ToC)`).html(TOC_MOBILE).css("line-height", TOC_EM); + switch_to_mobile_view(); } else { - $(`code:contains(ToC)`).html(TOC).css("line-height", TOC_EM_DESKTOP); + switch_to_desktop_view(); } } window.addEventListener("orientationchange", updateToc, false); diff --git a/web/template.html b/web/template.html index 04c4f4062..ed249d980 100644 --- a/web/template.html +++ b/web/template.html @@ -35,18 +35,19 @@ <meta name="twitter:card" content="summary_large_image"> <meta name="twitter:title" content="Comprehensive Python Cheatsheet"> <meta name="twitter:description" content="Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language."> - <meta name="twitter:image" content="https://gto76.github.io/python-cheatsheet/web/image_social_3.png"> + <meta name="twitter:image" content="https://gto76.github.io/python-cheatsheet/web/image_social_4.png"> <meta property="og:url" content="https://gto76.github.io/python-cheatsheet/"> <meta property="og:title" content="Comprehensive Python Cheatsheet"> <meta property="og:description" content="Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language."> <meta property="og:site_name" content="gto76.github.io"> - <meta property="og:image" content="https://gto76.github.io/python-cheatsheet/web/image_social_3.png"> + <meta property="og:image" content="https://gto76.github.io/python-cheatsheet/web/image_social_4.png"> + <meta property="og:type" content="article"> <meta itemprop="url" content="https://gto76.github.io/python-cheatsheet/"> <meta itemprop="name" content="Comprehensive Python Cheatsheet"> <meta itemprop="description" content="Exhaustive, simple, beautiful and concise. A truly Pythonic cheat sheet about Python programming language."> - <meta itemprop="image" content="https://gto76.github.io/python-cheatsheet/web/image_social_3.png"> + <meta itemprop="image" content="https://gto76.github.io/python-cheatsheet/web/image_social_4.png"> <meta name="google-site-verification" content="w3rvuG0D1kUm_w20qsJecSEZh59Am8jK4eSPVU83e_M"> <meta name="viewport" id="viewport-meta">