diff --git a/README.md b/README.md index e905c08c2..3f6f13bb7 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ Contents **   ** **3. Syntax:** **         ** **[`Args`](#arguments)**__,__ **[`Inline`](#inline)**__,__ **[`Import`](#imports)**__,__ **[`Decorator`](#decorator)**__,__ **[`Class`](#class)**__,__ **[`Duck_Types`](#duck-types)**__,__ **[`Enum`](#enum)**__,__ **[`Exception`](#exceptions)**__.__ **   ** **4. System:** **        ** **[`Exit`](#exit)**__,__ **[`Print`](#print)**__,__ **[`Input`](#input)**__,__ **[`Command_Line_Arguments`](#command-line-arguments)**__,__ **[`Open`](#open)**__,__ **[`Path`](#paths)**__,__ **[`OS_Commands`](#os-commands)**__.__ **   ** **5. Data:** **             ** **[`JSON`](#json)**__,__ **[`Pickle`](#pickle)**__,__ **[`CSV`](#csv)**__,__ **[`SQLite`](#sqlite)**__,__ **[`Bytes`](#bytes)**__,__ **[`Struct`](#struct)**__,__ **[`Array`](#array)**__,__ **[`Memory_View`](#memory-view)**__,__ **[`Deque`](#deque)**__.__ -**   ** **6. Advanced:** **   ** **[`Threading`](#threading)**__,__ **[`Operator`](#operator)**__,__ **[`Match_Stmt`](#match-statement)**__,__ **[`Logging`](#logging)**__,__ **[`Introspection`](#introspection)**__,__ **[`Coroutines`](#coroutines)**__.__ -**   ** **7. Libraries:** **      ** **[`Progress_Bar`](#progress-bar)**__,__ **[`Plot`](#plot)**__,__ **[`Table`](#table)**__,__ **[`Console_App`](#console-app)**__,__ **[`GUI`](#gui-app)**__,__ **[`Scraping`](#scraping)**__,__ **[`Web`](#web)**__,__ **[`Profile`](#profiling)**__.__ +**   ** **6. Advanced:** **   ** **[`Operator`](#operator)**__,__ **[`Match_Stmt`](#match-statement)**__,__ **[`Logging`](#logging)**__,__ **[`Introspection`](#introspection)**__,__ **[`Threading`](#threading)**__,__ **[`Coroutines`](#coroutines)**__.__ +**   ** **7. Libraries:** **      ** **[`Progress_Bar`](#progress-bar)**__,__ **[`Plot`](#plot)**__,__ **[`Table`](#table)**__,__ **[`Console_App`](#console-app)**__,__ **[`GUI`](#gui-app)**__,__ **[`Scraping`](#scraping)**__,__ **[`Web`](#web-app)**__,__ **[`Profile`](#profiling)**__.__ **   ** **8. Multimedia:** **  ** **[`NumPy`](#numpy)**__,__ **[`Image`](#image)**__,__ **[`Animation`](#animation)**__,__ **[`Audio`](#audio)**__,__ **[`Synthesizer`](#synthesizer)**__,__ **[`Pygame`](#pygame)**__,__ **[`Pandas`](#pandas)**__,__ **[`Plotly`](#plotly)**__.__ @@ -50,19 +50,22 @@ List ``` ```python -sum_of_elements = sum() + = max() # Returns largest element. Also min(, ...). + = sum() # Returns sum of elements. Also math.prod(). +``` + +```python elementwise_sum = [sum(pair) for pair in zip(list_a, list_b)] sorted_by_second = sorted(, key=lambda el: el[1]) sorted_by_both = sorted(, key=lambda el: (el[1], el[0])) flatter_list = list(itertools.chain.from_iterable()) -product_of_elems = functools.reduce(lambda out, el: out * el, ) -list_of_chars = list() ``` -* **For details about sorted(), min() and max() see [sortable](#sortable).** -* **Module [operator](#operator) provides functions itemgetter() and mul() that offer the same functionality as [lambda](#lambda) expressions above.** +* **For details about sort(), sorted(), min() and max() see [sortable](#sortable).** +* **Module [operator](#operator) has function itemgetter() that can replace listed [lambdas](#lambda).** +* **This text uses the term 'collection' instead of 'iterable'. For rationale see [collection](#collection).** ```python - = len() # Returns number of items. Also works on other collections. + = len() # Returns number of items. Also works on dict, set and string. = .count() # Returns number of occurrences. Also `if in : ...`. = .index() # Returns index of the first occurrence or raises ValueError. = .pop() # Removes and returns item from the end or at index if passed. @@ -79,8 +82,8 @@ Dictionary ``` ```python - = .keys() # Coll. of keys that reflects changes. - = .values() # Coll. of values that reflects changes. + = .keys() # Collection of keys that reflects changes. + = .values() # Collection of values that reflects changes. = .items() # Coll. of key-value tuples that reflects chgs. ``` @@ -388,9 +391,7 @@ import re '\w' == '[a-zA-Z0-9_]' # Also [ª²³…]. Matches an alphanumeric or _. '\s' == '[ \t\n\r\f\v]' # Also [\x1c-\x1f…]. Matches a whitespace. ``` - -* **By default, decimal characters, alphanumerics and whitespaces from all alphabets are matched unless `'flags=re.ASCII'` argument is used.** -* **It restricts special sequence matches to `'[\x00-\x7f]'` (the first 128 characters) and also prevents `'\s'` from accepting `'[\x1c-\x1f]'` (file, table, row, and field separators).** +* **By default, decimal characters and alphanumerics from all alphabets are matched unless `'flags=re.ASCII'` is used. It restricts special sequence matches to the first 128 Unicode characters and also prevents `'\s'` from accepting `'\x1c'`, `'\x1d'`, `'\x1e'` and `'\x1f'` (non-printable characters that divide text into files, tables, rows and fields, respectively).** * **Use a capital letter for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).** @@ -493,7 +494,7 @@ Format Numbers ------- ```python - = int() # Or: math.floor() + = int() # Or: math.trunc() = float() # Or: = complex(real=0, imag=0) # Or: ± j = fractions.Fraction(0, 1) # Or: Fraction(numerator=0, denominator=1) @@ -605,7 +606,7 @@ import zoneinfo, dateutil.tz
= datetime(year, month, day, hour=0) # Also: `minute=0, second=0, microsecond=0, …`. = timedelta(weeks=0, days=0, hours=0) # Also: `minutes=0, seconds=0, microseconds=0`. ``` -* **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!** +* **Aware times and datetimes have defined timezone, while naive don't. If object is naive, it is presumed to be in the system's timezone!** * **`'fold=1'` means the second pass in case of time jumping back for one hour.** * **Timedelta normalizes arguments to ±days, seconds (< 86 400) and microseconds (< 1M). Its str() method returns `'[±D, ]H:MM:SS[.…]'` and total_seconds() a float of all seconds.** * **Use `'.weekday()'` to get the day of the week as an int, with Monday being 0.** @@ -931,7 +932,7 @@ from functools import cache def fib(n): return n if n < 2 else fib(n-2) + fib(n-1) ``` -* **Potential problem with cache is that it can grow indefinitely. To clear its stored values run `'fib.cache_clear()'`, or use `'@lru_cache(maxsize=)'` decorator instead.** +* **Potential problem with cache is that it can grow indefinitely. To clear stored values run `'fib.cache_clear()'`, or use `'@lru_cache(maxsize=)'` decorator instead.** * **CPython interpreter limits recursion depth to 3000 by default. To increase it run `'sys.setrecursionlimit()'`.** ### Parametrized Decorator @@ -974,15 +975,15 @@ class MyClass: def get_class_name(cls): return cls.__name__ ``` -* **Return value of str() should be readable and of repr() unambiguous.** -* **If only repr() is defined, it will also be used for str().** -* **Methods decorated with `'@staticmethod'` do not receive 'self' nor 'cls' as their first arg.** ```python >>> obj = MyClass(1) >>> obj.a, str(obj), repr(obj) (1, '1', 'MyClass(1)') ``` +* **Return value of str() should be readable and of repr() unambiguous.** +* **If only repr() is defined, it will also be used for str().** +* **Methods decorated with `'@staticmethod'` do not receive 'self' nor 'cls' as their first argument.** #### Expressions that call the str() method: ```python @@ -1055,9 +1056,9 @@ class : * **For attributes of arbitrary type use `'typing.Any'`.** ```python - = make_dataclass('', ) - = make_dataclass('', ) - = ('', [, ]) +Point = make_dataclass('Point', ['x', 'y']) +Point = make_dataclass('Point', [('x', float), ('y', float)]) +Point = make_dataclass('Point', [('x', float, 0), ('y', float, 0)]) ``` ### Property @@ -1293,7 +1294,7 @@ class MySequence: ``` #### Discrepancies between glossary definitions and abstract base classes: -* **Glossary on Python's website defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.** +* **Python's glossary defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.** * **Passing ABC Iterable to isinstance() or issubclass() checks whether object/class has method iter(), while ABC Collection checks for iter(), contains() and len().** ### ABC Sequence @@ -1582,7 +1583,7 @@ Open * **`'w+'` - Read and write. Deletes existing contents.** * **`'r+'` - Read and write from the start.** * **`'a+'` - Read and write from the end.** -* **`'b'` - Binary mode (`'rb'`, `'wb'`, `'xb'`, …)** +* **`'b'` - Binary mode (`'rb'`, `'wb'`, `'xb'`, …).** ### Exceptions * **`'FileNotFoundError'` can be raised when reading with `'r'` or `'r+'`.** @@ -1660,7 +1661,7 @@ from pathlib import Path ```python = os.stat() # Or: .stat() - = .st_mtime/st_size/… # Modification time, size in bytes, ... + = .st_mtime/st_size/… # Modification time, size in bytes, etc. ``` ### DirEntry @@ -1740,9 +1741,9 @@ shutil.rmtree() # Deletes the directory. ### Shell Commands ```python - = os.popen('') # Executes command in sh/cmd. Returns its stdout pipe. + = os.popen('') # Executes commands in sh/cmd. Returns combined stdout. = .read(size=-1) # Reads 'size' chars or until EOF. Also readline/s(). - = .close() # Closes the pipe. Returns None on success (returncode 0). + = .close() # Returns None if last command exited with returncode 0. ``` #### Sends '1 + 1' to the basic calculator and captures its output: @@ -1768,22 +1769,22 @@ JSON ```python import json - = json.dumps() # Converts object to JSON string. - = json.loads() # Converts JSON string to object. + = json.dumps() # Converts collection to JSON string. + = json.loads() # Converts JSON string to collection. ``` -### Read Object from JSON File +### Read Collection from JSON File ```python def read_json_file(filename): with open(filename, encoding='utf-8') as file: return json.load(file) ``` -### Write Object to JSON File +### Write Collection to JSON File ```python -def write_to_json_file(filename, an_object): +def write_to_json_file(filename, list_or_dict): with open(filename, 'w', encoding='utf-8') as file: - json.dump(an_object, file, ensure_ascii=False, indent=2) + json.dump(list_or_dict, file, ensure_ascii=False, indent=2) ``` @@ -1883,41 +1884,41 @@ def write_to_csv_file(filename, rows, mode='w', **csv_params): SQLite ------ -**A server-less database engine that stores each database into a separate file.** +**A server-less database engine that stores each database into its own file.** ```python import sqlite3 - = sqlite3.connect() # Opens existing or new file. Also ':memory:'. -.close() # Closes connection. Discards uncommitted data. + = sqlite3.connect() # Opens existing or new file. Also ':memory:'. +.close() # Closes connection. Discards uncommitted data. ``` ### Read ```python - = .execute('') # Can raise a subclass of sqlite3.Error. - = .fetchone() # Returns next row. Also next(). - = .fetchall() # Returns remaining rows. Also list(). + = .execute('') # Can raise a subclass of sqlite3.Error. + = .fetchone() # Returns next row. Also next(). + = .fetchall() # Returns remaining rows. Also list(). ``` ### Write ```python -.execute('') # Can raise a subclass of sqlite3.Error. -.commit() # Saves all changes since the last commit. -.rollback() # Discards all changes since the last commit. +.execute('') # Can raise a subclass of sqlite3.Error. +.commit() # Saves all changes since the last commit. +.rollback() # Discards all changes since the last commit. ``` #### Or: ```python -with : # Exits the block with commit() or rollback(), - .execute('') # depending on whether any exception occurred. +with : # Exits the block with commit() or rollback(), + .execute('') # depending on whether any exception occurred. ``` ### Placeholders ```python -.execute('', ) # Replaces '?'s in query with values. -.execute('', ) # Replaces ':'s with values. -.executemany('', ) # Runs execute() multiple times. +.execute('', ) # Replaces '?'s in query with values. +.execute('', ) # Replaces ':'s with values. +.executemany('', ) # Runs execute() multiple times. ``` -* **Passed values can be of type str, int, float, bytes, None or bool (stored as 1 or 0).** +* **Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).** ### Example **Values are not actually saved in this example because `'conn.commit()'` is omitted!** @@ -1935,10 +1936,10 @@ with : # Exits the block with commit() ```python # $ pip3 install sqlalchemy from sqlalchemy import create_engine, text - = create_engine('') # Url: 'dialect://user:password@host/dbname'. - = .connect() # Creates a connection. Also .close(). - = .execute(text(''), …) # Replaces ':'s with keyword arguments. -with .begin(): ... # Exits the block with commit or rollback. + = create_engine('') # Url: 'dialect://user:password@host/dbname'. + = .connect() # Creates a connection. Also .close(). + = .execute(text(''), …) # Replaces ':'s with keyword arguments. +with .begin(): ... # Exits the block with commit or rollback. ``` ```text @@ -2045,15 +2046,15 @@ from array import array ``` ```python - = array('', ) # Array from collection of numbers. - = array('', ) # Copies bytes to array's memory. - = array('', ) # Treats array as a sequence of numbers. -.fromfile(, n_items) # Appends items from the binary file. + = array('', ) # Creates array from collection of numbers. + = array('', ) # Writes passed bytes to array's memory. + = array('', ) # Treats passed array as a sequence of numbers. +.fromfile(, n_items) # Appends file's contents to array's memory. ``` ```python = bytes() # Returns a copy of array's memory. -.write() # Writes array's memory to binary file. +.write() # Writes array's memory to the binary file. ``` @@ -2085,7 +2086,7 @@ Memory View Deque ----- -**A thread-safe list with efficient appends and pops from either side. Pronounced "deck".** +**List with efficient appends and pops from either side. Pronounced "deck".** ```python from collections import deque @@ -2100,74 +2101,9 @@ from collections import deque ``` -Threading ---------- -**CPython interpreter can only run a single thread at a time. Using multiple threads won't result in a faster execution, unless at least one of the threads contains an I/O operation.** -```python -from threading import Thread, Lock, RLock, Semaphore, Event, Barrier -from concurrent.futures import ThreadPoolExecutor, as_completed -``` - -### Thread -```python - = Thread(target=) # Use `args=` to set the arguments. -.start() # Starts the thread. Also .is_alive(). -.join() # Waits for the thread to finish. -``` -* **Use `'kwargs='` to pass keyword arguments to the function.** -* **Use `'daemon=True'`, or the program will not be able to exit while the thread is alive.** - -### Lock -```python - = Lock/RLock() # RLock can only be released by acquirer. -.acquire() # Waits for the lock to be available. -.release() # Makes the lock available again. -``` - -#### Or: -```python -with : # Enters the block by calling acquire() and - ... # exits it with release(), even on error. -``` - -### Semaphore, Event, Barrier -```python - = Semaphore(value=1) # Lock that can be acquired by 'value' threads. - = Event() # Method wait() blocks until set() is called. - = Barrier(n_times) # Wait() blocks until it's called n_times. -``` - -### Queue -```python - = queue.Queue(maxsize=0) # A thread-safe first-in-first-out queue. -.put() # Blocks until queue stops being full. -.put_nowait() # Raises queue.Full exception if full. - = .get() # Blocks until queue stops being empty. - = .get_nowait() # Raises queue.Empty exception if empty. -``` - -### Thread Pool Executor -```python - = ThreadPoolExecutor(max_workers=None) # Or: `with ThreadPoolExecutor() as : ...` - = .map(, , ...) # Multithreaded and non-lazy map(). Keeps order. - = .submit(, , ...) # Creates a thread and returns its Future obj. -.shutdown() # Blocks until all threads finish executing. -``` - -```python - = .done() # Checks if the thread has finished executing. - = .result(timeout=None) # Waits for thread to finish and returns result. - = .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 are done.** -* **Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.** -* **ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be [pickable](#pickle), queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via `'if __name__ == "__main__": ...'`.** - - Operator -------- -**Module of functions that provide the functionality of operators. Functions are ordered by operator precedence, starting with least binding.** +**Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence—from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.** ```python import operator as op ``` @@ -2185,9 +2121,8 @@ import operator as op ```python elementwise_sum = map(op.add, list_a, list_b) -sorted_by_second = sorted(, key=op.itemgetter(1)) -sorted_by_both = sorted(, key=op.itemgetter(1, 0)) -product_of_elems = functools.reduce(op.mul, ) +sorted_by_second = sorted(, key=op.itemgetter(1)) +sorted_by_both = sorted(, key=op.itemgetter(1, 0)) first_element = op.methodcaller('pop', 0)() ``` * **Most operators call the object's special method that is named after them (second object is passed as an argument), while logical operators call their own code that relies on bool().** @@ -2294,28 +2229,93 @@ CRITICAL:my_module:Running out of disk space. Introspection ------------- ```python - = dir() # List of of local names (including functions and classes). + = dir() # List of local names (variables, funcs, classes, modules). = vars() # Dict of local names and their objects. Also locals(). - = globals() # Dict of global names (for instance '__builtin__' module). + = globals() # Dict of global names and their objects, e.g. __builtin__. ``` ```python - = dir() # Returns names of all object's attributes (incl. methods). + = dir() # Returns names of object's attributes (including 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__. +setattr(, '', value) # Sets attribute. Only works on objects with __dict__ attr. delattr(, '') # Deletes attribute from __dict__. Also `del .`. ``` ```python - = inspect.signature() # Returns function's Signature object. Can accept a class. + = inspect.signature() # Returns a Signature object of the passed function. = .parameters # Returns dict of Parameters. Also .return_annotation. = .kind # Returns ParameterKind member (Parameter.KEYWORD_ONLY, …). = .annotation # Returns Parameter.empty if missing. Also .default. ``` +Threading +--------- +**CPython interpreter can only run a single thread at a time. Using multiple threads won't result in a faster execution, unless at least one of the threads contains an I/O operation.** +```python +from threading import Thread, Lock, RLock, Semaphore, Event, Barrier +from concurrent.futures import ThreadPoolExecutor, as_completed +``` + +### Thread +```python + = Thread(target=) # Use `args=` to set the arguments. +.start() # Starts the thread. Also .is_alive(). +.join() # Waits for the thread to finish. +``` +* **Use `'kwargs='` to pass keyword arguments to the function.** +* **Use `'daemon=True'`, or the program will not be able to exit while the thread is alive.** + +### Lock +```python + = Lock/RLock() # RLock can only be released by acquirer. +.acquire() # Waits for the lock to be available. +.release() # Makes the lock available again. +``` + +#### Or: +```python +with : # Enters the block by calling acquire() and + ... # exits it with release(), even on error. +``` + +### Semaphore, Event, Barrier +```python + = Semaphore(value=1) # Lock that can be acquired by 'value' threads. + = Event() # Method wait() blocks until set() is called. + = Barrier(n_times) # Wait() blocks until it's called n_times. +``` + +### Queue +```python + = queue.Queue(maxsize=0) # A thread-safe first-in-first-out queue. +.put() # Blocks until queue stops being full. +.put_nowait() # Raises queue.Full exception if full. + = .get() # Blocks until queue stops being empty. + = .get_nowait() # Raises queue.Empty exception if empty. +``` + +### Thread Pool Executor +```python + = ThreadPoolExecutor(max_workers=None) # Or: `with ThreadPoolExecutor() as : ...` + = .map(, , ...) # Multithreaded and non-lazy map(). Keeps order. + = .submit(, , ...) # Creates a thread and returns its Future obj. +.shutdown() # Blocks until all threads finish executing. +``` + +```python + = .done() # Checks if the thread has finished executing. + = .result(timeout=None) # Waits for thread to finish and returns result. + = .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 are done.** +* **Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.** +* **ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be [pickable](#pickle), queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via `'if __name__ == "__main__": ...'`.** + + Coroutines ---------- * **Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t use as much memory.** @@ -2419,9 +2419,9 @@ import matplotlib.pyplot as plt 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 or label. -plt.savefig() # Saves the figure. -plt.show() # Displays the figure. -plt.clf() # Clears the figure. +plt.savefig() # Saves the plot. +plt.show() # Displays the plot. +plt.clf() # Clears the plot. ``` @@ -2553,7 +2553,7 @@ import flask as fl ```python app = fl.Flask(__name__) # Returns the app object. Put at the top. -app.run(host=None, port=None, debug=None) # Or: $ flask --app FILE run [--ARG[=VAL] …] +app.run(host=None, port=None, debug=None) # Or: $ flask --app FILE run [--ARG[=VAL]]… ``` * **Starts the app at `'http://localhost:5000'`. Use `'host="0.0.0.0"'` to run externally.** * **Install a WSGI server like [Waitress](https://flask.palletsprojects.com/en/latest/deploying/waitress/) and a HTTP server such as [Nginx](https://flask.palletsprojects.com/en/latest/deploying/nginx/) for better security.** @@ -2777,7 +2777,7 @@ from PIL import Image = Image.open() # Identifies format based on file's contents. = .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. +.show() # Displays image in default preview app. ``` ```python @@ -2795,7 +2795,7 @@ from PIL import Image ```python = np.array() # Creates a 2d/3d NumPy array from the image. - = Image.fromarray(np.uint8()) # Use `.clip(0, 255)` to clip values. + = Image.fromarray(np.uint8()) # Use .clip(0, 255) to clip the values. ``` ### Modes @@ -2832,10 +2832,10 @@ from PIL import ImageDraw .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) # Draws in clockwise dir. Also pieslice(). -.rectangle((x1, y1, x2, y2)) # To rotate use Image's rotate() and paste(). +.rectangle((x1, y1, x2, y2)) # Also rounded_rectangle(), regular_polygon(). .polygon((x1, y1, x2, y2, ...)) # Last point gets connected to the first. -.ellipse((x1, y1, x2, y2)) # Also rounded_rectangle(), regular_polygon(). -.text((x, y), , font=) # ` = ImageFont.truetype(, size)` +.ellipse((x1, y1, x2, y2)) # To rotate use Image's rotate() and paste(). +.text((x, y), , font=) # ` = ImageFont.truetype(, size)`. ``` * **Use `'fill='` to set the primary color.** * **Use `'width='` to set the width of lines or contours.** @@ -2876,7 +2876,7 @@ import wave = .getnchannels() # Returns number of samples per frame. = .getsampwidth() # Returns number of bytes per sample. = .getparams() # Returns namedtuple of all parameters. - = .readframes(nframes) # Returns next n frames. All if -1. + = .readframes(nframes) # Returns next n frames (-1 returns all). ``` ```python @@ -2913,7 +2913,7 @@ def read_wav_file(filename): p = file.getparams() frames = file.readframes(-1) bytes_samples = (frames[i : i + p.sampwidth] for i in range(0, len(frames), p.sampwidth)) - return [get_int(b) / pow(2, p.sampwidth * 8 - 1) for b in bytes_samples], p + return [get_int(b) / pow(2, (p.sampwidth * 8) - 1) for b in bytes_samples], p ``` ### Write Float Samples to WAV File @@ -2922,7 +2922,7 @@ def write_to_wav_file(filename, samples_f, p=None, nchannels=1, sampwidth=2, fra def get_bytes(a_float): a_float = max(-1, min(1 - 2e-16, a_float)) a_float += p.sampwidth == 1 - a_float *= pow(2, p.sampwidth * 8 - 1) + a_float *= pow(2, (p.sampwidth * 8) - 1) return int(a_float).to_bytes(p.sampwidth, 'little', signed=(p.sampwidth != 1)) if p is None: p = wave._wave_params(nchannels, sampwidth, framerate, 0, 'NONE', 'not compressed') @@ -3146,6 +3146,8 @@ if __name__ == '__main__': Pandas ------ +**Data analysis library. For examples see [Plotly](#plotly).** + ```python # $ pip3 install pandas matplotlib import pandas as pd, matplotlib.pyplot as plt @@ -3155,80 +3157,75 @@ import pandas as pd, matplotlib.pyplot as plt **Ordered dictionary with a name.** ```python ->>> sr = pd.Series([1, 2], index=['x', 'y'], name='a'); sr +>>> s = pd.Series([1, 2], index=['x', 'y'], name='a'); s x 1 y 2 Name: a, dtype: int64 ``` ```python - = pd.Series() # Assigns RangeIndex starting at 0. - = pd.Series() # Takes dictionary's keys for index. - = pd.Series(, index=) # Only keeps items with keys specified in index. + = pd.Series() # Creates index from list's indices. + = pd.Series() # Creates index from dictionary's keys. + = pd.Series(, index=) # Only keeps items with keys specified in index. ``` ```python - = .loc[key] # Or: .iloc[i] - = .loc[coll_of_keys] # Or: .iloc[coll_of_i] - = .loc[from_key : to_key_inc] # Or: .iloc[from_i : to_i_exc] + = .loc[key] # Or: .iloc[i] + = .loc[coll_of_keys] # Or: .iloc[coll_of_i] + = .loc[from_key : to_key_inc] # Or: .iloc[from_i : to_i_exc] ``` ```python - = [key/i] # Or: . - = [coll_of_keys/coll_of_i] # Or: [key/i : key/i] - = [bools] # Or: .loc/iloc[bools] + = [key/i] # Or: . + = [coll_of_keys/coll_of_i] # Or: [key/i : key/i] + = [bools] # Or: .loc/iloc[bools] ``` ```python - = > # Returns a Series of bools. - = + # Items with non-matching keys get value NaN. + = > # Returns S of bools. Pairs items by keys. + = + # Items with non-matching keys get value NaN. ``` ```python - = pd.concat() # Concats multiple series into one long Series. - = .combine_first() # Adds items that are not yet present. -.update() # Updates items that are already present. + = pd.concat() # Concats multiple series into one long Series. + = .combine_first() # Adds items that are not yet present. +.update() # Updates items that are already present. ``` ```python -.plot.line/area/bar/pie/hist() # Generates a Matplotlib plot. +.plot.line/area/bar/pie/hist() # Generates a plot. Accepts `title=`. plt.show() # Displays the plot. Also plt.savefig(). ``` +* **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`!** +* **Pandas uses NumPy types like `'np.int64'`. Series is converted to `'float64'` if we assign np.nan to any item. Use `'.astype()'` to get converted Series.** #### Series — Aggregate, Transform, Map: ```python - = .sum/max/mean/idxmax/all() # Or: .agg(lambda : ) - = .rank/diff/cumsum/ffill/interpo…() # Or: .agg/transform(lambda : ) - = .fillna() # Or: .agg/transform/map(lambda : ) -``` - -```python ->>> sr = pd.Series([2, 3], index=['x', 'y']); sr -x 2 -y 3 + = .sum/max/mean/idxmax/all() # Or: .agg(lambda : ) + = .rank/diff/cumsum/ffill/interpol…() # Or: .agg/transform(lambda : ) + = .isna/fillna/isin([]) # Or: .agg/transform/map(lambda : ) ``` ```text -+---------------+-------------+-------------+---------------+ -| | 'sum' | ['sum'] | {'s': 'sum'} | -+---------------+-------------+-------------+---------------+ -| sr.apply(…) | 5 | sum 5 | s 5 | -| sr.agg(…) | | | | -+---------------+-------------+-------------+---------------+ ++--------------+-------------+-------------+---------------+ +| | 'sum' | ['sum'] | {'s': 'sum'} | ++--------------+-------------+-------------+---------------+ +| s.apply(…) | 3 | sum 3 | s 3 | +| s.agg(…) | | | | ++--------------+-------------+-------------+---------------+ ``` ```text -+---------------+-------------+-------------+---------------+ -| | 'rank' | ['rank'] | {'r': 'rank'} | -+---------------+-------------+-------------+---------------+ -| sr.apply(…) | | rank | | -| sr.agg(…) | x 1 | x 1 | r x 1 | -| | y 2 | y 2 | y 2 | -+---------------+-------------+-------------+---------------+ ++--------------+-------------+-------------+---------------+ +| | 'rank' | ['rank'] | {'r': 'rank'} | ++--------------+-------------+-------------+---------------+ +| s.apply(…) | | rank | | +| s.agg(…) | x 1.0 | x 1.0 | r x 1.0 | +| | y 2.0 | y 2.0 | y 2.0 | ++--------------+-------------+-------------+---------------+ ``` -* **Indexing objects can't be tuples because `'obj[x, y]'` is converted to `'obj[(x, y)]'`!** * **Methods ffill(), interpolate(), fillna() and dropna() accept `'inplace=True'`.** -* **Last result has a hierarchical index. Use `'[key_1, key_2]'` to get its values.** +* **Last result has a multi-index. Use `'[key_1, key_2]'` to get its values.** ### DataFrame **Table with labeled rows and columns.** @@ -3241,33 +3238,39 @@ b 3 4 ``` ```python - = pd.DataFrame() # Rows can be either lists, dicts or series. - = pd.DataFrame() # Columns can be either lists, dicts or series. + = pd.DataFrame() # Rows can be either lists, dicts or series. + = pd.DataFrame() # Columns can be either lists, dicts or series. +``` + +```python + = .loc[row_key, col_key] # Or: .iloc[row_i, col_i] + = .loc[row_key/s] # Or: .iloc[row_i/s] + = .loc[:, col_key/s] # Or: .iloc[:, col_i/s] + = .loc[row_bools, col_bools] # Or: .iloc[row_bools, col_bools] ``` ```python - = .loc[row_key, col_key] # Or: .iloc[row_i, col_i] - = .loc[row_key/s] # Or: .iloc[row_i/s] - = .loc[:, col_key/s] # Or: .iloc[:, col_i/s] - = .loc[row_bools, col_bools] # Or: .iloc[row_bools, col_bools] + = [col_key/s] # Or: . + = [row_bools] # Keeps rows as specified by bools. + = [] # Assigns NaN to items that are False in bools. ``` ```python - = [col_key/s] # Or: . - = [row_bools] # Keeps rows as specified by bools. - = [] # Assigns NaN to items that are False in bools. + = > # Returns DF of bools. S is treated as a row. + = + # Items with non-matching keys get value NaN. ``` ```python - = > # Returns DF of bools. Sr is treated as a row. - = + # Items with non-matching keys get value NaN. + = .set_index(col_key) # Replaces row keys with column's values. + = .reset_index(drop=False) # Drops or moves row keys to column named index. + = .sort_index(ascending=True) # Sorts rows by row keys. Use `axis=1` for cols. + = .sort_values(col_key/s) # Sorts rows by passed column/s. Also `axis=1`. ``` ```python - = .set_index(col_key) # Replaces row keys with column's values. - = .reset_index(drop=False) # Drops or moves row keys to column named index. - = .sort_index(ascending=True) # Sorts rows by row keys. Use `axis=1` for cols. - = .sort_values(col_key/s) # Sorts rows by passed column/s. Also `axis=1`. + = .head/tail/sample() # Returns first, last, or random n rows. + = .describe() # Describes columns. Also info(), corr(), shape. + = .query('') # Filters rows with e.g. 'col_1 == val_1 and …'. ``` ```python @@ -3301,58 +3304,54 @@ c 6 7 | axis=0, | a 1 2 . | 2 | | Uses 'outer' by default. | | join=…) | b 3 4 . | 4 | | A Series is treated as a | | | b . 4 5 | 4 | | column. To add a row use | -| | c . 6 7 | 6 | | pd.concat([l, DF([sr])]).| +| | c . 6 7 | 6 | | pd.concat([l, DF([s])]). | +------------------------+---------------+------------+------------+--------------------------+ | pd.concat([l, r], | x y y z | | | Adds columns at the | | axis=1, | a 1 2 . . | x y y z | | right end. Uses 'outer' | | join=…) | b 3 4 4 5 | 3 4 4 5 | | by default. A Series is | | | c . . 6 7 | | | treated as a column. | +------------------------+---------------+------------+------------+--------------------------+ -| l.combine_first(r) | x y z | | | Adds missing rows and | -| | a 1 2 . | | | columns. Also updates | -| | b 3 4 5 | | | items that contain NaN. | -| | c . 6 7 | | | Argument r must be a DF. | -+------------------------+---------------+------------+------------+--------------------------+ ``` #### DataFrame — Aggregate, Transform, Map: ```python - = .sum/max/mean/idxmax/all() # Or: .apply/agg(lambda : ) - = .rank/diff/cumsum/ffill/interpo…() # Or: .apply/agg/transfo…(lambda : ) - = .fillna() # Or: .applymap(lambda : ) + = .sum/max/mean/idxmax/all() # Or: .apply/agg(lambda : ) + = .rank/diff/cumsum/ffill/interpo…() # Or: .apply/agg/transform(lambda : ) + = .isna/fillna/isin([]) # Or: .agg/transform/map(lambda : ) ``` -* **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 - x y -a 1 2 -b 3 4 +```text ++----------------+---------------+---------------+---------------+ +| | 'sum' | ['sum'] | {'x': 'sum'} | ++----------------+---------------+---------------+---------------+ +| l.apply(…) | x 4 | x y | x 4 | +| l.agg(…) | y 6 | sum 4 6 | | ++----------------+---------------+---------------+---------------+ ``` ```text -+-----------------+-------------+-------------+---------------+ -| | 'sum' | ['sum'] | {'x': 'sum'} | -+-----------------+-------------+-------------+---------------+ -| df.apply(…) | x 4 | x y | x 4 | -| df.agg(…) | y 6 | sum 4 6 | | -+-----------------+-------------+-------------+---------------+ ++----------------+---------------+---------------+---------------+ +| | 'rank' | ['rank'] | {'x': 'rank'} | ++----------------+---------------+---------------+---------------+ +| l.apply(…) | | x y | | +| l.agg(…) | x y | rank rank | x | +| l.transform(…) | a 1.0 1.0 | a 1.0 1.0 | a 1.0 | +| | b 2.0 2.0 | b 2.0 2.0 | b 2.0 | ++----------------+---------------+---------------+---------------+ ``` +* **All methods operate on columns by default. Pass `'axis=1'` to process the rows instead.** +* **Fifth result's columns are indexed with a multi-index. This means we need a tuple of column keys to specify a column: `'.loc[row_key, (col_key_1, col_key_2)]'`.** -```text -+-----------------+-------------+-------------+---------------+ -| | 'rank' | ['rank'] | {'x': 'rank'} | -+-----------------+-------------+-------------+---------------+ -| df.apply(…) | | x y | | -| df.agg(…) | x y | rank rank | x | -| df.transform(…) | a 1 1 | a 1 1 | a 1 | -| | b 2 2 | b 2 2 | b 2 | -+-----------------+-------------+-------------+---------------+ +#### DataFrame — Multi-Index: +```python + = .xs(row_key, level=) # Rows with key on passed level of multi-index. + = .xs(row_keys, level=) # Rows that have first key on first level, etc. + = .set_index(col_keys) # Combines multiple columns into a multi-index. + = .stack/unstack(level=-1) # Combines col keys with row keys or vice versa. + = .pivot_table(index=col_key/s) # `columns=key/s, values=key/s, aggfunc='mean'`. ``` -* **Use `'[col_key_1, col_key_2][row_key]'` to get the fifth result's values.** #### DataFrame — Encode, Decode: - ```python = pd.read_json/html('') # Run `$ pip3 install beautifulsoup4 lxml`. = pd.read_csv('') # `header/index_col/dtype/usecols/…=`. @@ -3367,53 +3366,50 @@ b 3 4 .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/…'`.** +* **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')) ->>> 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(col_key/s) # Splits DF into groups based on passed column. - = .apply() # Maps each group. Func can return DF, Sr or el. + = .apply() # Maps each group. Func can return DF, S or el. + = .filter() # Drops a group if function returns False. = .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. + = .size() # S of group sizes. Same keys as get_group(). + = [col_key] # Single column GB. All operations return S. ``` -#### GroupBy — Aggregate, Transform, Map: ```python - = .sum/max/mean/idxmax/all() # Or: .agg(lambda : ) - = .rank/diff/cumsum/ffill() # Or: .transform(lambda : ) - = .fillna() # Or: .transform(lambda : ) + = .sum/max/mean/idxmax/all() # Or: .agg(lambda : ) + = .rank/diff/cumsum/ffill() # Or: .transform(lambda : ) + = .fillna() # Or: .transform(lambda : ) ``` +#### Divides rows into groups and sums their columns. Result has a named index that creates column `'z'` on reset_index(): ```python +>>> df = pd.DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 6]], list('abc'), list('xyz')) +>>> 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 >>> 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`. - = [col_key/s] # Or: .col_key - = .mean/sum/max() # Or: .apply/agg() + = .rolling(win_size) # Also: `min_periods=None, center=False`. + = [col_key/s] # Or: .col_key + = .mean/sum/max() # Or: .apply/agg() ``` @@ -3427,7 +3423,7 @@ 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(). +.write_html/json/image('') # .show() displays the plot. ``` ```python @@ -3590,4 +3586,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.** +* **Click on the title's `'🔗'` to get a link to its section.** diff --git a/index.html b/index.html index a297efed2..cc20b6047 100644 --- a/index.html +++ b/index.html @@ -55,7 +55,7 @@ <body> <header> - <aside>October 28, 2024</aside> + <aside>November 29, 2024</aside> <a href="https://gto76.github.io" rel="author">Jure Šorn</a> </header> @@ -86,8 +86,8 @@ <strong><span class="hljs-string"><span class="hljs-string">'3. Syntax'</span></span></strong>: [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>], <strong><span class="hljs-string"><span class="hljs-string">'4. System'</span></span></strong>: [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">Command_Line_Arguments</a>, <a href="#open">Open</a>, <a href="#paths">Path</a>, <a href="#oscommands">OS_Commands</a>], <strong><span class="hljs-string"><span class="hljs-string">'5. Data'</span></span></strong>: [<a href="#json">JSON</a>, <a href="#pickle">Pickle</a>, <a href="#csv">CSV</a>, <a href="#sqlite">SQLite</a>, <a href="#bytes">Bytes</a>, <a href="#struct">Struct</a>, <a href="#array">Array</a>, <a href="#memoryview">Memory_View</a>, <a href="#deque">Deque</a>], - <strong><span class="hljs-string"><span class="hljs-string">'6. Advanced'</span></span></strong>: [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>], - <strong><span class="hljs-string"><span class="hljs-string">'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">'6. Advanced'</span></span></strong>: [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>], + <strong><span class="hljs-string"><span class="hljs-string">'7. Libraries'</span></span></strong>: [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>, <a href="#consoleapp">Console_App</a>, <a href="#guiapp">GUI</a>, <a href="#scraping">Scraping</a>, <a href="#webapp">Web</a>, <a href="#profiling">Profile</a>], <strong><span class="hljs-string"><span class="hljs-string">'8. Multimedia'</span></span></strong>: [<a href="#numpy">NumPy</a>, <a href="#image">Image</a>, <a href="#animation">Animation</a>, <a href="#audio">Audio</a>, <a href="#synthesizer">Synthesizer</a>, <a href="#pygame">Pygame</a>, <a href="#pandas">Pandas</a>, <a href="#plotly">Plotly</a>] } </code></pre></div> @@ -114,19 +114,20 @@ <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)] +<pre><code class="python language-python hljs"><el> = max(<collection>) <span class="hljs-comment"># Returns largest element. Also min(<el_1>, ...).</span> +<num> = sum(<collection>) <span class="hljs-comment"># Returns sum of elements. Also math.prod(<coll>).</span> +</code></pre> +<pre><code class="python language-python hljs">elementwise_sum = [sum(pair) <span class="hljs-keyword">for</span> pair <span class="hljs-keyword">in</span> zip(list_a, list_b)] sorted_by_second = sorted(<collection>, key=<span class="hljs-keyword">lambda</span> el: el[<span class="hljs-number">1</span>]) sorted_by_both = sorted(<collection>, key=<span class="hljs-keyword">lambda</span> el: (el[<span class="hljs-number">1</span>], el[<span class="hljs-number">0</span>])) flatter_list = list(itertools.chain.from_iterable(<list>)) -product_of_elems = functools.reduce(<span class="hljs-keyword">lambda</span> out, el: out * el, <collection>) -list_of_chars = list(<str>) </code></pre> <ul> -<li><strong>For details about sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong></li> -<li><strong>Module <a href="#operator">operator</a> provides functions itemgetter() and mul() that offer the same functionality as <a href="#lambda">lambda</a> expressions above.</strong></li> +<li><strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong></li> +<li><strong>Module <a href="#operator">operator</a> has function itemgetter() that can replace listed <a href="#lambda">lambdas</a>.</strong></li> +<li><strong>This text uses the term 'collection' instead of 'iterable'. For rationale see <a href="#collection">collection</a>.</strong></li> </ul> -<pre><code class="python language-python hljs"><int> = len(<list>) <span class="hljs-comment"># Returns number of items. Also works on other collections.</span> +<pre><code class="python language-python hljs"><int> = len(<list>) <span class="hljs-comment"># Returns number of items. Also works on dict, set and string.</span> <int> = <list>.count(<el>) <span class="hljs-comment"># Returns number of occurrences. Also `if <el> in <coll>: ...`.</span> <int> = <list>.index(<el>) <span class="hljs-comment"># Returns index of the first occurrence or raises ValueError.</span> <el> = <list>.pop() <span class="hljs-comment"># Removes and returns item from the end or at index if passed.</span> @@ -137,8 +138,8 @@ <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> +<pre><code class="python language-python hljs"><view> = <dict>.keys() <span class="hljs-comment"># Collection of keys that reflects changes.</span> +<view> = <dict>.values() <span class="hljs-comment"># Collection 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> @@ -359,8 +360,7 @@ </code></pre></div> <ul> -<li><strong>By default, decimal characters, alphanumerics and whitespaces from all alphabets are matched unless <code class="python hljs"><span class="hljs-string">'flags=re.ASCII'</span></code> argument is used.</strong></li> -<li><strong>It restricts special sequence matches to <code class="python hljs"><span class="hljs-string">'[\x00-\x7f]'</span></code> (the first 128 characters) and also prevents <code class="python hljs"><span class="hljs-string">'\s'</span></code> from accepting <code class="python hljs"><span class="hljs-string">'[\x1c-\x1f]'</span></code> (file, table, row, and field separators).</strong></li> +<li><strong>By default, decimal characters and alphanumerics from all alphabets are matched unless <code class="python hljs"><span class="hljs-string">'flags=re.ASCII'</span></code> is used. It restricts special sequence matches to the first 128 Unicode characters and also prevents <code class="python hljs"><span class="hljs-string">'\s'</span></code> from accepting <code class="python hljs"><span class="hljs-string">'\x1c'</span></code>, <code class="python hljs"><span class="hljs-string">'\x1d'</span></code>, <code class="python hljs"><span class="hljs-string">'\x1e'</span></code> and <code class="python hljs"><span class="hljs-string">'\x1f'</span></code> (non-printable characters that divide text into files, tables, rows and fields, respectively).</strong></li> <li><strong>Use a capital letter for negation (all non-ASCII characters will be matched when used in combination with ASCII flag).</strong></li> </ul> <div><h2 id="format"><a href="#format" name="format">#</a>Format</h2><pre><code class="python hljs"><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> @@ -444,7 +444,7 @@ {<span class="hljs-number">90</span>:X} <span class="hljs-comment"># '5A'. Number 90 in uppercase hexadecimal.</span> </code></pre></div> -<div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs"><int> = int(<float/str/bool>) <span class="hljs-comment"># Or: math.floor(<float>)</span> +<div><h2 id="numbers"><a href="#numbers" name="numbers">#</a>Numbers</h2><pre><code class="python language-python hljs"><int> = int(<float/str/bool>) <span class="hljs-comment"># Or: math.trunc(<float>)</span> <float> = float(<int/str/bool>) <span class="hljs-comment"># Or: <int/float>e±<int></span> <complex> = complex(real=<span class="hljs-number">0</span>, imag=<span class="hljs-number">0</span>) <span class="hljs-comment"># Or: <int/float> ± <int/float>j</span> <Fraction> = fractions.Fraction(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>) <span class="hljs-comment"># Or: Fraction(numerator=0, denominator=1)</span> @@ -527,7 +527,7 @@ <TD> = timedelta(weeks=<span class="hljs-number">0</span>, days=<span class="hljs-number">0</span>, hours=<span class="hljs-number">0</span>) <span class="hljs-comment"># Also: `minutes=0, seconds=0, microseconds=0`.</span> </code></pre> <ul> -<li><strong>Aware <code class="apache hljs"><span class="hljs-section"><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>Aware times and datetimes have defined timezone, while naive don't. If object is naive, it is presumed to be in the system's timezone!</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'fold=1'</span></code> means the second pass in case of time jumping back for one hour.</strong></li> <li><strong>Timedelta normalizes arguments to ±days, seconds (< 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> @@ -778,7 +778,7 @@ <ul> -<li><strong>Potential problem with cache is that it can grow indefinitely. To clear its stored values run <code class="python hljs"><span class="hljs-string">'fib.cache_clear()'</span></code>, or use <code class="python hljs"><span class="hljs-string">'@lru_cache(maxsize=<int>)'</span></code> decorator instead.</strong></li> +<li><strong>Potential problem with cache is that it can grow indefinitely. To clear stored values run <code class="python hljs"><span class="hljs-string">'fib.cache_clear()'</span></code>, or use <code class="python hljs"><span class="hljs-string">'@lru_cache(maxsize=<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 @@ -817,15 +817,15 @@ </code></pre></div> -<ul> -<li><strong>Return value of str() should be readable and of repr() unambiguous.</strong></li> -<li><strong>If only repr() is defined, it will also be used for str().</strong></li> -<li><strong>Methods decorated with <code class="python hljs"><span class="hljs-string">'@staticmethod'</span></code> do not receive 'self' nor 'cls' as their first arg.</strong></li> -</ul> <pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>obj = MyClass(<span class="hljs-number">1</span>) <span class="hljs-meta">>>> </span>obj.a, str(obj), repr(obj) (<span class="hljs-number">1</span>, <span class="hljs-string">'1'</span>, <span class="hljs-string">'MyClass(1)'</span>) </code></pre> +<ul> +<li><strong>Return value of str() should be readable and of repr() unambiguous.</strong></li> +<li><strong>If only repr() is defined, it will also be used for str().</strong></li> +<li><strong>Methods decorated with <code class="python hljs"><span class="hljs-string">'@staticmethod'</span></code> do not receive 'self' nor 'cls' as their first argument.</strong></li> +</ul> <div><h4 id="expressionsthatcallthestrmethod">Expressions that call the str() method:</h4><pre><code class="python language-python hljs">print(<obj>) <span class="hljs-string">f'<span class="hljs-subst">{<obj>}</span>'</span> logging.warning(<obj>) @@ -886,9 +886,10 @@ <li><strong>Function field() is needed because <code class="python hljs"><span class="hljs-string">'<attr_name>: list = []'</span></code> would make a list that is shared among all instances. Its 'default_factory' argument can be any <a href="#callable">callable</a>.</strong></li> <li><strong>For attributes of arbitrary type use <code class="python hljs"><span class="hljs-string">'typing.Any'</span></code>.</strong></li> </ul> -<pre><code class="python language-python hljs"><class> = make_dataclass(<span class="hljs-string">'<class_name>'</span>, <coll_of_attribute_names>) -<class> = make_dataclass(<span class="hljs-string">'<class_name>'</span>, <coll_of_tuples>) -<tuple> = (<span class="hljs-string">'<attr_name>'</span>, <type> [, <default_value>])</code></pre> +<pre><code class="python language-python hljs">Point = make_dataclass(<span class="hljs-string">'Point'</span>, [<span class="hljs-string">'x'</span>, <span class="hljs-string">'y'</span>]) +Point = make_dataclass(<span class="hljs-string">'Point'</span>, [(<span class="hljs-string">'x'</span>, float), (<span class="hljs-string">'y'</span>, float)]) +Point = make_dataclass(<span class="hljs-string">'Point'</span>, [(<span class="hljs-string">'x'</span>, float, <span class="hljs-number">0</span>), (<span class="hljs-string">'y'</span>, float, <span class="hljs-number">0</span>)]) +</code></pre> <div><h3 id="property">Property</h3><p><strong>Pythonic way of implementing getters and setters.</strong></p><pre><code class="python language-python hljs"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span>:</span> <span class="hljs-meta"> @property</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">name</span><span class="hljs-params">(self)</span>:</span> @@ -1098,7 +1099,7 @@ <div><h4 id="discrepanciesbetweenglossarydefinitionsandabstractbaseclasses">Discrepancies between glossary definitions and abstract base classes:</h4><ul> -<li><strong>Glossary on Python's website defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.</strong></li> +<li><strong>Python's glossary defines iterable as any object with iter() or getitem() and sequence as any object with getitem() and len(). It does not define collection.</strong></li> <li><strong>Passing ABC Iterable to isinstance() or issubclass() checks whether object/class has method iter(), while ABC Collection checks for iter(), contains() and len().</strong></li> </ul></div> @@ -1339,7 +1340,7 @@ <li><strong><code class="python hljs"><span class="hljs-string">'w+'</span></code> - Read and write. Deletes existing contents.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'r+'</span></code> - Read and write from the start.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'a+'</span></code> - Read and write from the end.</strong></li> -<li><strong><code class="python hljs"><span class="hljs-string">'b'</span></code> - Binary mode (<code class="python hljs"><span class="hljs-string">'rb'</span></code>, <code class="python hljs"><span class="hljs-string">'wb'</span></code>, <code class="python hljs"><span class="hljs-string">'xb'</span></code>, …)</strong></li> +<li><strong><code class="python hljs"><span class="hljs-string">'b'</span></code> - Binary mode (<code class="python hljs"><span class="hljs-string">'rb'</span></code>, <code class="python hljs"><span class="hljs-string">'wb'</span></code>, <code class="python hljs"><span class="hljs-string">'xb'</span></code>, …).</strong></li> </ul><div><h3 id="exceptions-1">Exceptions</h3><ul> <li><strong><code class="python hljs"><span class="hljs-string">'FileNotFoundError'</span></code> can be raised when reading with <code class="python hljs"><span class="hljs-string">'r'</span></code> or <code class="python hljs"><span class="hljs-string">'r+'</span></code>.</strong></li> <li><strong><code class="python hljs"><span class="hljs-string">'FileExistsError'</span></code> can be raised when writing with <code class="python hljs"><span class="hljs-string">'x'</span></code>.</strong></li> @@ -1398,7 +1399,7 @@ <bool> = os.path.isdir(<path>) <span class="hljs-comment"># Or: <DirEntry/Path>.is_dir()</span> </code></pre> <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> +<num> = <stat>.st_mtime/st_size/… <span class="hljs-comment"># Modification time, size in bytes, etc.</span> </code></pre> <div><h3 id="direntry">DirEntry</h3><p><strong>Unlike listdir(), scandir() returns DirEntry objects that cache isfile, isdir, and on Windows also stat information, thus significantly increasing the performance of code that requires it.</strong></p><pre><code class="python language-python hljs"><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> @@ -1452,9 +1453,9 @@ <li><strong>Paths can be either strings, Paths, or DirEntry objects.</strong></li> <li><strong>Functions report OS related errors by raising either OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong></li> </ul> -<div><h3 id="shellcommands">Shell Commands</h3><pre><code class="python language-python hljs"><pipe> = os.popen(<span class="hljs-string">'<command>'</span>) <span class="hljs-comment"># Executes command in sh/cmd. Returns its stdout pipe.</span> +<div><h3 id="shellcommands">Shell Commands</h3><pre><code class="python language-python hljs"><pipe> = os.popen(<span class="hljs-string">'<commands>'</span>) <span class="hljs-comment"># Executes commands in sh/cmd. Returns combined stdout.</span> <str> = <pipe>.read(size=<span class="hljs-number">-1</span>) <span class="hljs-comment"># Reads 'size' chars or until EOF. Also readline/s().</span> -<int> = <pipe>.close() <span class="hljs-comment"># Closes the pipe. Returns None on success (returncode 0).</span> +<int> = <pipe>.close() <span class="hljs-comment"># Returns None if last command exited with returncode 0.</span> </code></pre></div> <div><h4 id="sends11tothebasiccalculatorandcapturesitsoutput">Sends '1 + 1' to the basic calculator and captures its output:</h4><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>subprocess.run(<span class="hljs-string">'bc'</span>, input=<span class="hljs-string">'1 + 1\n'</span>, capture_output=<span class="hljs-keyword">True</span>, text=<span class="hljs-keyword">True</span>) @@ -1470,19 +1471,19 @@ </code></pre></div> <div><h2 id="json"><a href="#json" name="json">#</a>JSON</h2><p><strong>Text file format for storing collections of strings and numbers.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> json -<str> = json.dumps(<object>) <span class="hljs-comment"># Converts object to JSON string.</span> -<object> = json.loads(<str>) <span class="hljs-comment"># Converts JSON string to object.</span> +<str> = json.dumps(<list/dict>) <span class="hljs-comment"># Converts collection to JSON string.</span> +<coll> = json.loads(<str>) <span class="hljs-comment"># Converts JSON string to collection.</span> </code></pre></div> -<div><h3 id="readobjectfromjsonfile">Read Object from JSON File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_json_file</span><span class="hljs-params">(filename)</span>:</span> +<div><h3 id="readcollectionfromjsonfile">Read Collection from JSON File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">read_json_file</span><span class="hljs-params">(filename)</span>:</span> <span class="hljs-keyword">with</span> open(filename, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> file: <span class="hljs-keyword">return</span> json.load(file) </code></pre></div> -<div><h3 id="writeobjecttojsonfile">Write Object to JSON File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_json_file</span><span class="hljs-params">(filename, an_object)</span>:</span> +<div><h3 id="writecollectiontojsonfile">Write Collection to JSON File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_json_file</span><span class="hljs-params">(filename, list_or_dict)</span>:</span> <span class="hljs-keyword">with</span> open(filename, <span class="hljs-string">'w'</span>, encoding=<span class="hljs-string">'utf-8'</span>) <span class="hljs-keyword">as</span> file: - json.dump(an_object, file, ensure_ascii=<span class="hljs-keyword">False</span>, indent=<span class="hljs-number">2</span>) + json.dump(list_or_dict, file, ensure_ascii=<span class="hljs-keyword">False</span>, indent=<span class="hljs-number">2</span>) </code></pre></div> <div><h2 id="pickle"><a href="#pickle" name="pickle">#</a>Pickle</h2><p><strong>Binary file format for storing Python objects.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> pickle @@ -1560,33 +1561,33 @@ writer.writerows(rows) </code></pre></div> -<div><h2 id="sqlite"><a href="#sqlite" name="sqlite">#</a>SQLite</h2><p><strong>A server-less database engine that stores each database into a separate file.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> sqlite3 -<conn> = sqlite3.connect(<path>) <span class="hljs-comment"># Opens existing or new file. Also ':memory:'.</span> -<conn>.close() <span class="hljs-comment"># Closes connection. Discards uncommitted data.</span> +<div><h2 id="sqlite"><a href="#sqlite" name="sqlite">#</a>SQLite</h2><p><strong>A server-less database engine that stores each database into its own file.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> sqlite3 +<conn> = sqlite3.connect(<path>) <span class="hljs-comment"># Opens existing or new file. Also ':memory:'.</span> +<conn>.close() <span class="hljs-comment"># Closes connection. Discards uncommitted data.</span> </code></pre></div> -<div><h3 id="read-1">Read</h3><pre><code class="python language-python hljs"><cursor> = <conn>.execute(<span class="hljs-string">'<query>'</span>) <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span> -<tuple> = <cursor>.fetchone() <span class="hljs-comment"># Returns next row. Also next(<cursor>).</span> -<list> = <cursor>.fetchall() <span class="hljs-comment"># Returns remaining rows. Also list(<cursor>).</span> +<div><h3 id="read-1">Read</h3><pre><code class="python language-python hljs"><cursor> = <conn>.execute(<span class="hljs-string">'<query>'</span>) <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span> +<tuple> = <cursor>.fetchone() <span class="hljs-comment"># Returns next row. Also next(<cursor>).</span> +<list> = <cursor>.fetchall() <span class="hljs-comment"># Returns remaining rows. Also list(<cursor>).</span> </code></pre></div> -<div><h3 id="write-1">Write</h3><pre><code class="python language-python hljs"><conn>.execute(<span class="hljs-string">'<query>'</span>) <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span> -<conn>.commit() <span class="hljs-comment"># Saves all changes since the last commit.</span> -<conn>.rollback() <span class="hljs-comment"># Discards all changes since the last commit.</span> +<div><h3 id="write-1">Write</h3><pre><code class="python language-python hljs"><conn>.execute(<span class="hljs-string">'<query>'</span>) <span class="hljs-comment"># Can raise a subclass of sqlite3.Error.</span> +<conn>.commit() <span class="hljs-comment"># Saves all changes since the last commit.</span> +<conn>.rollback() <span class="hljs-comment"># Discards all changes since the last commit.</span> </code></pre></div> -<div><h4 id="or">Or:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">with</span> <conn>: <span class="hljs-comment"># Exits the block with commit() or rollback(),</span> - <conn>.execute(<span class="hljs-string">'<query>'</span>) <span class="hljs-comment"># depending on whether any exception occurred.</span> +<div><h4 id="or">Or:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">with</span> <conn>: <span class="hljs-comment"># Exits the block with commit() or rollback(),</span> + <conn>.execute(<span class="hljs-string">'<query>'</span>) <span class="hljs-comment"># depending on whether any exception occurred.</span> </code></pre></div> -<div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs"><conn>.execute(<span class="hljs-string">'<query>'</span>, <list/tuple>) <span class="hljs-comment"># Replaces '?'s in query with values.</span> -<conn>.execute(<span class="hljs-string">'<query>'</span>, <dict/namedtuple>) <span class="hljs-comment"># Replaces ':<key>'s with values.</span> -<conn>.executemany(<span class="hljs-string">'<query>'</span>, <coll_of_above>) <span class="hljs-comment"># Runs execute() multiple times.</span> +<div><h3 id="placeholders">Placeholders</h3><pre><code class="python language-python hljs"><conn>.execute(<span class="hljs-string">'<query>'</span>, <list/tuple>) <span class="hljs-comment"># Replaces '?'s in query with values.</span> +<conn>.execute(<span class="hljs-string">'<query>'</span>, <dict/namedtuple>) <span class="hljs-comment"># Replaces ':<key>'s with values.</span> +<conn>.executemany(<span class="hljs-string">'<query>'</span>, <coll_of_coll>) <span class="hljs-comment"># Runs execute() multiple times.</span> </code></pre></div> <ul> -<li><strong>Passed values can be of type str, int, float, bytes, None or bool (stored as 1 or 0).</strong></li> +<li><strong>Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).</strong></li> </ul> <div><h3 id="example-1">Example</h3><p><strong>Values are not actually saved in this example because <code class="python hljs"><span class="hljs-string">'conn.commit()'</span></code> is omitted!</strong></p><pre><code class="python language-python hljs"><span class="hljs-meta">>>> </span>conn = sqlite3.connect(<span class="hljs-string">'test.db'</span>) <span class="hljs-meta">>>> </span>conn.execute(<span class="hljs-string">'CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height)'</span>) @@ -1599,10 +1600,10 @@ <div><h3 id="sqlalchemy">SQLAlchemy</h3><p><strong>Library for interacting with various DB systems via SQL, method chaining, or ORM.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install sqlalchemy</span> <span class="hljs-keyword">from</span> sqlalchemy <span class="hljs-keyword">import</span> create_engine, text -<engine> = create_engine(<span class="hljs-string">'<url>'</span>) <span class="hljs-comment"># Url: 'dialect://user:password@host/dbname'.</span> -<conn> = <engine>.connect() <span class="hljs-comment"># Creates a connection. Also <conn>.close().</span> -<cursor> = <conn>.execute(text(<span class="hljs-string">'<query>'</span>), …) <span class="hljs-comment"># Replaces ':<key>'s with keyword arguments.</span> -<span class="hljs-keyword">with</span> <conn>.begin(): ... <span class="hljs-comment"># Exits the block with commit or rollback.</span> +<engine> = create_engine(<span class="hljs-string">'<url>'</span>) <span class="hljs-comment"># Url: 'dialect://user:password@host/dbname'.</span> +<conn> = <engine>.connect() <span class="hljs-comment"># Creates a connection. Also <conn>.close().</span> +<cursor> = <conn>.execute(text(<span class="hljs-string">'<query>'</span>), …) <span class="hljs-comment"># Replaces ':<key>'s with keyword arguments.</span> +<span class="hljs-keyword">with</span> <conn>.begin(): ... <span class="hljs-comment"># Exits the block with commit or rollback.</span> </code></pre></div> @@ -1688,13 +1689,13 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment </code></pre></div> -<pre><code class="python language-python hljs"><array> = array(<span class="hljs-string">'<typecode>'</span>, <coll_of_nums>) <span class="hljs-comment"># Array from collection of numbers.</span> -<array> = array(<span class="hljs-string">'<typecode>'</span>, <bytes>) <span class="hljs-comment"># Copies bytes to array's memory.</span> -<array> = array(<span class="hljs-string">'<typecode>'</span>, <array>) <span class="hljs-comment"># Treats array as a sequence of numbers.</span> -<array>.fromfile(<file>, n_items) <span class="hljs-comment"># Appends items from the binary file.</span> +<pre><code class="python language-python hljs"><array> = array(<span class="hljs-string">'<typecode>'</span>, <coll_of_nums>) <span class="hljs-comment"># Creates array from collection of numbers.</span> +<array> = array(<span class="hljs-string">'<typecode>'</span>, <bytes>) <span class="hljs-comment"># Writes passed bytes to array's memory.</span> +<array> = array(<span class="hljs-string">'<typecode>'</span>, <array>) <span class="hljs-comment"># Treats passed array as a sequence of numbers.</span> +<array>.fromfile(<file>, n_items) <span class="hljs-comment"># Appends file's contents to array's memory.</span> </code></pre> <pre><code class="python language-python hljs"><bytes> = bytes(<array>) <span class="hljs-comment"># Returns a copy of array's memory.</span> -<file>.write(<array>) <span class="hljs-comment"># Writes array's memory to binary file.</span> +<file>.write(<array>) <span class="hljs-comment"># Writes array's memory to the binary file.</span> </code></pre> <div><h2 id="memoryview"><a href="#memoryview" name="memoryview">#</a>Memory View</h2><p><strong>A sequence object that points to the memory of another bytes-like object. Each element can reference a single or multiple consecutive bytes, depending on format. Order and number of elements can be changed with slicing.</strong></p><pre><code class="python language-python hljs"><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 or float. Bytes if format is 'c'.</span> @@ -1713,7 +1714,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <str> = str(<mview>, <span class="hljs-string">'utf-8'</span>) <span class="hljs-comment"># Treats memoryview as a bytes object.</span> <str> = <mview>.hex() <span class="hljs-comment"># Returns hex pairs. Accepts `sep=<str>`.</span> </code></pre> -<div><h2 id="deque"><a href="#deque" name="deque">#</a>Deque</h2><p><strong>A thread-safe list with efficient appends and pops from either side. Pronounced "deck".</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> deque +<div><h2 id="deque"><a href="#deque" name="deque">#</a>Deque</h2><p><strong>List with efficient appends and pops from either side. Pronounced "deck".</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> collections <span class="hljs-keyword">import</span> deque </code></pre></div> @@ -1723,58 +1724,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <deque>.rotate(n=<span class="hljs-number">1</span>) <span class="hljs-comment"># Last element becomes first.</span> <el> = <deque>.popleft() <span class="hljs-comment"># Raises IndexError if deque is empty.</span> </code></pre> -<div><h2 id="threading"><a href="#threading" name="threading">#</a>Threading</h2><p><strong>CPython interpreter can only run a single thread at a time. Using multiple threads won't result in a faster execution, unless at least one of the threads contains an I/O operation.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> threading <span class="hljs-keyword">import</span> Thread, Lock, RLock, Semaphore, Event, Barrier -<span class="hljs-keyword">from</span> concurrent.futures <span class="hljs-keyword">import</span> ThreadPoolExecutor, as_completed -</code></pre></div> - - -<div><h3 id="thread">Thread</h3><pre><code class="python language-python hljs"><Thread> = Thread(target=<function>) <span class="hljs-comment"># Use `args=<collection>` to set the arguments.</span> -<Thread>.start() <span class="hljs-comment"># Starts the thread. Also <Thread>.is_alive().</span> -<Thread>.join() <span class="hljs-comment"># Waits for the thread to finish.</span> -</code></pre></div> - -<ul> -<li><strong>Use <code class="python hljs"><span class="hljs-string">'kwargs=<dict>'</span></code> to pass keyword arguments to the function.</strong></li> -<li><strong>Use <code class="python hljs"><span class="hljs-string">'daemon=True'</span></code>, or the program will not be able to exit while the thread is alive.</strong></li> -</ul> -<div><h3 id="lock">Lock</h3><pre><code class="python language-python hljs"><lock> = Lock/RLock() <span class="hljs-comment"># RLock can only be released by acquirer.</span> -<lock>.acquire() <span class="hljs-comment"># Waits for the lock to be available.</span> -<lock>.release() <span class="hljs-comment"># Makes the lock available again.</span> -</code></pre></div> - -<div><h4 id="or-1">Or:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">with</span> <lock>: <span class="hljs-comment"># Enters the block by calling acquire() and</span> - ... <span class="hljs-comment"># exits it with release(), even on error.</span> -</code></pre></div> - -<div><h3 id="semaphoreeventbarrier">Semaphore, Event, Barrier</h3><pre><code class="python language-python hljs"><Semaphore> = Semaphore(value=<span class="hljs-number">1</span>) <span class="hljs-comment"># Lock that can be acquired by 'value' threads.</span> -<Event> = Event() <span class="hljs-comment"># Method wait() blocks until set() is called.</span> -<Barrier> = Barrier(n_times) <span class="hljs-comment"># Wait() blocks until it's called n_times.</span> -</code></pre></div> - -<div><h3 id="queue">Queue</h3><pre><code class="python language-python hljs"><Queue> = queue.Queue(maxsize=<span class="hljs-number">0</span>) <span class="hljs-comment"># A thread-safe first-in-first-out queue.</span> -<Queue>.put(<el>) <span class="hljs-comment"># Blocks until queue stops being full.</span> -<Queue>.put_nowait(<el>) <span class="hljs-comment"># Raises queue.Full exception if full.</span> -<el> = <Queue>.get() <span class="hljs-comment"># Blocks until queue stops being empty.</span> -<el> = <Queue>.get_nowait() <span class="hljs-comment"># Raises queue.Empty exception if empty.</span> -</code></pre></div> - -<div><h3 id="threadpoolexecutor">Thread Pool Executor</h3><pre><code class="python language-python hljs"><Exec> = ThreadPoolExecutor(max_workers=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Or: `with ThreadPoolExecutor() as <name>: ...`</span> -<iter> = <Exec>.map(<func>, <args_1>, ...) <span class="hljs-comment"># Multithreaded and non-lazy map(). Keeps order.</span> -<Futr> = <Exec>.submit(<func>, <arg_1>, ...) <span class="hljs-comment"># Creates a thread and returns its Future obj.</span> -<Exec>.shutdown() <span class="hljs-comment"># Blocks until all threads finish executing.</span> -</code></pre></div> - -<pre><code class="python language-python hljs"><bool> = <Future>.done() <span class="hljs-comment"># Checks if the thread has finished executing.</span> -<obj> = <Future>.result(timeout=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Waits for thread to finish and returns result.</span> -<bool> = <Future>.cancel() <span class="hljs-comment"># Cancels or returns False if running/finished.</span> -<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 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 +<div><h2 id="operator"><a href="#operator" name="operator">#</a>Operator</h2><p><strong>Module of functions that provide the functionality of operators. Functions are ordered and grouped by operator precedence—from least to most binding. Logical and arithmetic operators in rows 1, 3 and 5 are also ordered by precedence within a group.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">import</span> operator <span class="hljs-keyword">as</span> op </code></pre></div> @@ -1788,9 +1738,8 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <func> = op.itemgetter/attrgetter/methodcaller(<obj> [, ...]) <span class="hljs-comment"># [index/key], .name, .name([…])</span> </code></pre> <pre><code class="python language-python hljs">elementwise_sum = map(op.add, list_a, list_b) -sorted_by_second = sorted(<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>)) -product_of_elems = functools.reduce(op.mul, <collection>) +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>)) first_element = op.methodcaller(<span class="hljs-string">'pop'</span>, <span class="hljs-number">0</span>)(<list>) </code></pre> <ul> @@ -1877,23 +1826,74 @@ <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"># List of of local names (including functions and classes).</span> +<div><h2 id="introspection"><a href="#introspection" name="introspection">#</a>Introspection</h2><pre><code class="python language-python hljs"><list> = dir() <span class="hljs-comment"># List of local names (variables, funcs, classes, modules).</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> +<dict> = globals() <span class="hljs-comment"># Dict of global names and their objects, e.g. __builtin__.</span> </code></pre></div> -<pre><code class="python language-python hljs"><list> = dir(<obj>) <span class="hljs-comment"># Returns names of all object's attributes (incl. methods).</span> +<pre><code class="python language-python hljs"><list> = dir(<obj>) <span class="hljs-comment"># Returns names of object's attributes (including 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> +setattr(<obj>, <span class="hljs-string">'<name>'</span>, value) <span class="hljs-comment"># Sets attribute. Only works on objects with __dict__ attr.</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(<func>) <span class="hljs-comment"># Returns function's Signature object. Can accept a class.</span> +<pre><code class="python language-python hljs"><Sig> = inspect.signature(<func>) <span class="hljs-comment"># Returns a Signature object of the passed function.</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="threading"><a href="#threading" name="threading">#</a>Threading</h2><p><strong>CPython interpreter can only run a single thread at a time. Using multiple threads won't result in a faster execution, unless at least one of the threads contains an I/O operation.</strong></p><pre><code class="python language-python hljs"><span class="hljs-keyword">from</span> threading <span class="hljs-keyword">import</span> Thread, Lock, RLock, Semaphore, Event, Barrier +<span class="hljs-keyword">from</span> concurrent.futures <span class="hljs-keyword">import</span> ThreadPoolExecutor, as_completed +</code></pre></div> + + +<div><h3 id="thread">Thread</h3><pre><code class="python language-python hljs"><Thread> = Thread(target=<function>) <span class="hljs-comment"># Use `args=<collection>` to set the arguments.</span> +<Thread>.start() <span class="hljs-comment"># Starts the thread. Also <Thread>.is_alive().</span> +<Thread>.join() <span class="hljs-comment"># Waits for the thread to finish.</span> +</code></pre></div> + +<ul> +<li><strong>Use <code class="python hljs"><span class="hljs-string">'kwargs=<dict>'</span></code> to pass keyword arguments to the function.</strong></li> +<li><strong>Use <code class="python hljs"><span class="hljs-string">'daemon=True'</span></code>, or the program will not be able to exit while the thread is alive.</strong></li> +</ul> +<div><h3 id="lock">Lock</h3><pre><code class="python language-python hljs"><lock> = Lock/RLock() <span class="hljs-comment"># RLock can only be released by acquirer.</span> +<lock>.acquire() <span class="hljs-comment"># Waits for the lock to be available.</span> +<lock>.release() <span class="hljs-comment"># Makes the lock available again.</span> +</code></pre></div> + +<div><h4 id="or-1">Or:</h4><pre><code class="python language-python hljs"><span class="hljs-keyword">with</span> <lock>: <span class="hljs-comment"># Enters the block by calling acquire() and</span> + ... <span class="hljs-comment"># exits it with release(), even on error.</span> +</code></pre></div> + +<div><h3 id="semaphoreeventbarrier">Semaphore, Event, Barrier</h3><pre><code class="python language-python hljs"><Semaphore> = Semaphore(value=<span class="hljs-number">1</span>) <span class="hljs-comment"># Lock that can be acquired by 'value' threads.</span> +<Event> = Event() <span class="hljs-comment"># Method wait() blocks until set() is called.</span> +<Barrier> = Barrier(n_times) <span class="hljs-comment"># Wait() blocks until it's called n_times.</span> +</code></pre></div> + +<div><h3 id="queue">Queue</h3><pre><code class="python language-python hljs"><Queue> = queue.Queue(maxsize=<span class="hljs-number">0</span>) <span class="hljs-comment"># A thread-safe first-in-first-out queue.</span> +<Queue>.put(<el>) <span class="hljs-comment"># Blocks until queue stops being full.</span> +<Queue>.put_nowait(<el>) <span class="hljs-comment"># Raises queue.Full exception if full.</span> +<el> = <Queue>.get() <span class="hljs-comment"># Blocks until queue stops being empty.</span> +<el> = <Queue>.get_nowait() <span class="hljs-comment"># Raises queue.Empty exception if empty.</span> +</code></pre></div> + +<div><h3 id="threadpoolexecutor">Thread Pool Executor</h3><pre><code class="python language-python hljs"><Exec> = ThreadPoolExecutor(max_workers=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Or: `with ThreadPoolExecutor() as <name>: ...`</span> +<iter> = <Exec>.map(<func>, <args_1>, ...) <span class="hljs-comment"># Multithreaded and non-lazy map(). Keeps order.</span> +<Futr> = <Exec>.submit(<func>, <arg_1>, ...) <span class="hljs-comment"># Creates a thread and returns its Future obj.</span> +<Exec>.shutdown() <span class="hljs-comment"># Blocks until all threads finish executing.</span> +</code></pre></div> + +<pre><code class="python language-python hljs"><bool> = <Future>.done() <span class="hljs-comment"># Checks if the thread has finished executing.</span> +<obj> = <Future>.result(timeout=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Waits for thread to finish and returns result.</span> +<bool> = <Future>.cancel() <span class="hljs-comment"># Cancels or returns False if running/finished.</span> +<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 are done.</strong></li> +<li><strong>Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns exception object or None.</strong></li> +<li><strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be <a href="#pickle">pickable</a>, queues must be sent using executor's 'initargs' and 'initializer' parameters, and executor should only be reachable via <code class="python hljs"><span class="hljs-string">'if __name__ == "__main__": ...'</span></code>.</strong></li> +</ul> <div><h2 id="coroutines"><a href="#coroutines" name="coroutines">#</a>Coroutines</h2><ul> <li><strong>Coroutines have a lot in common with threads, but unlike threads, they only give up control when they call another coroutine and they don’t use as much memory.</strong></li> <li><strong>Coroutine definition starts with <code class="python hljs"><span class="hljs-string">'async'</span></code> and its call with <code class="python hljs"><span class="hljs-string">'await'</span></code>.</strong></li> @@ -1979,9 +1979,9 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment 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 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> +plt.savefig(<path>) <span class="hljs-comment"># Saves the plot.</span> +plt.show() <span class="hljs-comment"># Displays the plot.</span> +plt.clf() <span class="hljs-comment"># Clears the plot.</span> </code></pre></div> <div><h2 id="table"><a href="#table" name="table">#</a>Table</h2><div><h4 id="printsacsvspreadsheettotheconsole">Prints a CSV spreadsheet to the console:</h4><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install tabulate</span> @@ -2087,7 +2087,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <pre><code class="python language-python hljs">app = fl.Flask(__name__) <span class="hljs-comment"># Returns the app object. Put at the top.</span> -app.run(host=<span class="hljs-keyword">None</span>, port=<span class="hljs-keyword">None</span>, debug=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Or: $ flask --app FILE run [--ARG[=VAL] …]</span> +app.run(host=<span class="hljs-keyword">None</span>, port=<span class="hljs-keyword">None</span>, debug=<span class="hljs-keyword">None</span>) <span class="hljs-comment"># Or: $ flask --app FILE run [--ARG[=VAL]]…</span> </code></pre> <ul> <li><strong>Starts the app at <code class="python hljs"><span class="hljs-string">'http://localhost:5000'</span></code>. Use <code class="python hljs"><span class="hljs-string">'host="0.0.0.0"'</span></code> to run externally.</strong></li> @@ -2263,7 +2263,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <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 (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> +<Image>.show() <span class="hljs-comment"># Displays image in default preview app.</span> </code></pre> <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> @@ -2275,7 +2275,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <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> +<Image> = Image.fromarray(np.uint8(<array>)) <span class="hljs-comment"># Use <array>.clip(0, 255) to clip the values.</span> </code></pre> <div><h3 id="modes-1">Modes</h3><ul> <li><strong><code class="python hljs"><span class="hljs-string">'L'</span></code> - Lightness (greyscale image). Each pixel is an int between 0 and 255.</strong></li> @@ -2305,10 +2305,10 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <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"># 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>.rectangle((x1, y1, x2, y2)) <span class="hljs-comment"># Also rounded_rectangle(), regular_polygon().</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"># Also rounded_rectangle(), regular_polygon().</span> -<Draw>.text((x, y), <str>, font=<Font>) <span class="hljs-comment"># `<Font> = ImageFont.truetype(<path>, size)`</span> +<Draw>.ellipse((x1, y1, x2, y2)) <span class="hljs-comment"># To rotate use Image's rotate() and paste().</span> +<Draw>.text((x, y), <str>, font=<Font>) <span class="hljs-comment"># `<Font> = ImageFont.truetype(<path>, size)`.</span> </code></pre></div> <ul> @@ -2342,7 +2342,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <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> <tuple> = <Wave>.getparams() <span class="hljs-comment"># Returns namedtuple of all parameters.</span> -<bytes> = <Wave>.readframes(nframes) <span class="hljs-comment"># Returns next n frames. All if -1.</span> +<bytes> = <Wave>.readframes(nframes) <span class="hljs-comment"># Returns next n frames (-1 returns all).</span> </code></pre> <pre><code class="python language-python hljs"><Wave> = wave.open(<span class="hljs-string">'<path>'</span>, <span class="hljs-string">'wb'</span>) <span class="hljs-comment"># Creates/truncates a file for writing.</span> <Wave>.setframerate(<int>) <span class="hljs-comment"># Pass 44100 for CD, 48000 for video.</span> @@ -2374,14 +2374,14 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment p = file.getparams() frames = file.readframes(<span class="hljs-number">-1</span>) bytes_samples = (frames[i : i + p.sampwidth] <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">0</span>, len(frames), p.sampwidth)) - <span class="hljs-keyword">return</span> [get_int(b) / pow(<span class="hljs-number">2</span>, p.sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>) <span class="hljs-keyword">for</span> b <span class="hljs-keyword">in</span> bytes_samples], p + <span class="hljs-keyword">return</span> [get_int(b) / pow(<span class="hljs-number">2</span>, (p.sampwidth * <span class="hljs-number">8</span>) - <span class="hljs-number">1</span>) <span class="hljs-keyword">for</span> b <span class="hljs-keyword">in</span> bytes_samples], p </code></pre></div> <div><h3 id="writefloatsamplestowavfile">Write Float Samples to WAV File</h3><pre><code class="python language-python hljs"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">write_to_wav_file</span><span class="hljs-params">(filename, samples_f, p=<span class="hljs-keyword">None</span>, nchannels=<span class="hljs-number">1</span>, sampwidth=<span class="hljs-number">2</span>, framerate=<span class="hljs-number">44100</span>)</span>:</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_bytes</span><span class="hljs-params">(a_float)</span>:</span> a_float = max(<span class="hljs-number">-1</span>, min(<span class="hljs-number">1</span> - <span class="hljs-number">2e-16</span>, a_float)) a_float += p.sampwidth == <span class="hljs-number">1</span> - a_float *= pow(<span class="hljs-number">2</span>, p.sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>) + a_float *= pow(<span class="hljs-number">2</span>, (p.sampwidth * <span class="hljs-number">8</span>) - <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span> int(a_float).to_bytes(p.sampwidth, <span class="hljs-string">'little'</span>, signed=(p.sampwidth != <span class="hljs-number">1</span>)) <span class="hljs-keyword">if</span> p <span class="hljs-keyword">is</span> <span class="hljs-keyword">None</span>: p = wave._wave_params(nchannels, sampwidth, framerate, <span class="hljs-number">0</span>, <span class="hljs-string">'NONE'</span>, <span class="hljs-string">'not compressed'</span>) @@ -2568,68 +2568,68 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment main() </code></pre></div> -<div><h2 id="pandas"><a href="#pandas" name="pandas">#</a>Pandas</h2><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pandas matplotlib</span> +<div><h2 id="pandas"><a href="#pandas" name="pandas">#</a>Pandas</h2><p><strong>Data analysis library. For examples see <a href="#plotly">Plotly</a>.</strong></p><pre><code class="python language-python hljs"><span class="hljs-comment"># $ pip3 install pandas matplotlib</span> <span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd, matplotlib.pyplot <span class="hljs-keyword">as</span> plt </code></pre></div> -<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 + +<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>s = 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>); s x <span class="hljs-number">1</span> y <span class="hljs-number">2</span> Name: a, dtype: int64 </code></pre></div> -<pre><code class="python language-python hljs"><Sr> = pd.Series(<list>) <span class="hljs-comment"># Assigns RangeIndex starting at 0.</span> -<Sr> = pd.Series(<dict>) <span class="hljs-comment"># Takes dictionary's keys for index.</span> -<Sr> = pd.Series(<dict/Series>, index=<list>) <span class="hljs-comment"># Only keeps items with keys specified in index.</span> +<pre><code class="python language-python hljs"><S> = pd.Series(<list>) <span class="hljs-comment"># Creates index from list's indices.</span> +<S> = pd.Series(<dict>) <span class="hljs-comment"># Creates index from dictionary's keys.</span> +<S> = pd.Series(<dict/Series>, index=<list>) <span class="hljs-comment"># Only keeps items with keys specified in index.</span> </code></pre> -<pre><code class="python language-python hljs"><el> = <Sr>.loc[key] <span class="hljs-comment"># Or: <Sr>.iloc[i]</span> -<Sr> = <Sr>.loc[coll_of_keys] <span class="hljs-comment"># Or: <Sr>.iloc[coll_of_i]</span> -<Sr> = <Sr>.loc[from_key : to_key_inc] <span class="hljs-comment"># Or: <Sr>.iloc[from_i : to_i_exc]</span> +<pre><code class="python language-python hljs"><el> = <S>.loc[key] <span class="hljs-comment"># Or: <S>.iloc[i]</span> +<S> = <S>.loc[coll_of_keys] <span class="hljs-comment"># Or: <S>.iloc[coll_of_i]</span> +<S> = <S>.loc[from_key : to_key_inc] <span class="hljs-comment"># Or: <S>.iloc[from_i : to_i_exc]</span> </code></pre> -<pre><code class="python language-python hljs"><el> = <Sr>[key/i] <span class="hljs-comment"># Or: <Sr>.<key></span> -<Sr> = <Sr>[coll_of_keys/coll_of_i] <span class="hljs-comment"># Or: <Sr>[key/i : key/i]</span> -<Sr> = <Sr>[bools] <span class="hljs-comment"># Or: <Sr>.loc/iloc[bools]</span> +<pre><code class="python language-python hljs"><el> = <S>[key/i] <span class="hljs-comment"># Or: <S>.<key></span> +<S> = <S>[coll_of_keys/coll_of_i] <span class="hljs-comment"># Or: <S>[key/i : key/i]</span> +<S> = <S>[bools] <span class="hljs-comment"># Or: <S>.loc/iloc[bools]</span> </code></pre> -<pre><code class="python language-python hljs"><Sr> = <Sr> > <el/Sr> <span class="hljs-comment"># Returns a Series of bools.</span> -<Sr> = <Sr> + <el/Sr> <span class="hljs-comment"># Items with non-matching keys get value NaN.</span> +<pre><code class="python language-python hljs"><S> = <S> > <el/S> <span class="hljs-comment"># Returns S of bools. Pairs items by keys.</span> +<S> = <S> + <el/S> <span class="hljs-comment"># Items with non-matching keys get value NaN.</span> </code></pre> -<pre><code class="python language-python hljs"><Sr> = pd.concat(<coll_of_Sr>) <span class="hljs-comment"># Concats multiple series into one long Series.</span> -<Sr> = <Sr>.combine_first(<Sr>) <span class="hljs-comment"># Adds items that are not yet present.</span> -<Sr>.update(<Sr>) <span class="hljs-comment"># Updates items that are already present.</span> +<pre><code class="python language-python hljs"><S> = pd.concat(<coll_of_S>) <span class="hljs-comment"># Concats multiple series into one long Series.</span> +<S> = <S>.combine_first(<S>) <span class="hljs-comment"># Adds items that are not yet present.</span> +<S>.update(<S>) <span class="hljs-comment"># Updates items that are already present.</span> </code></pre> -<pre><code class="python language-python hljs"><Sr>.plot.line/area/bar/pie/hist() <span class="hljs-comment"># Generates a Matplotlib plot.</span> +<pre><code class="python language-python hljs"><S>.plot.line/area/bar/pie/hist() <span class="hljs-comment"># Generates a plot. Accepts `title=<str>`.</span> plt.show() <span class="hljs-comment"># Displays the plot. Also plt.savefig(<path>).</span> </code></pre> -<div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs"><el> = <Sr>.sum/max/mean/idxmax/all() <span class="hljs-comment"># Or: <Sr>.agg(lambda <Sr>: <el>)</span> -<Sr> = <Sr>.rank/diff/cumsum/ffill/interpo…() <span class="hljs-comment"># Or: <Sr>.agg/transform(lambda <Sr>: <Sr>)</span> -<Sr> = <Sr>.fillna(<el>) <span class="hljs-comment"># Or: <Sr>.agg/transform/map(lambda <el>: <el>)</span> +<ul> +<li><strong>Indexing objects can't be tuples because <code class="python hljs"><span class="hljs-string">'obj[x, y]'</span></code> is converted to <code class="python hljs"><span class="hljs-string">'obj[(x, y)]'</span></code>!</strong></li> +<li><strong>Pandas uses NumPy types like <code class="python hljs"><span class="hljs-string">'np.int64'</span></code>. Series is converted to <code class="python hljs"><span class="hljs-string">'float64'</span></code> if we assign np.nan to any item. Use <code class="python hljs"><span class="hljs-string">'<S>.astype(<str/type>)'</span></code> to get converted Series.</strong></li> +</ul> +<div><h4 id="seriesaggregatetransformmap">Series — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs"><el> = <S>.sum/max/mean/idxmax/all() <span class="hljs-comment"># Or: <S>.agg(lambda <S>: <el>)</span> +<S> = <S>.rank/diff/cumsum/ffill/interpol…() <span class="hljs-comment"># Or: <S>.agg/transform(lambda <S>: <S>)</span> +<S> = <S>.isna/fillna/isin([<el/coll>]) <span class="hljs-comment"># Or: <S>.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>]); sr -x <span class="hljs-number">2</span> -y <span class="hljs-number">3</span> -</code></pre> -<pre><code class="python hljs">┏━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ -┃ │ <span class="hljs-string">'sum'</span> │ [<span class="hljs-string">'sum'</span>] │ {<span class="hljs-string">'s'</span>: <span class="hljs-string">'sum'</span>} ┃ -┠───────────────┼─────────────┼─────────────┼───────────────┨ -┃ sr.apply(…) │ <span class="hljs-number">5</span> │ sum <span class="hljs-number">5</span> │ s <span class="hljs-number">5</span> ┃ -┃ sr.agg(…) │ │ │ ┃ -┗━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ +<pre><code class="python hljs">┏━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ +┃ │ <span class="hljs-string">'sum'</span> │ [<span class="hljs-string">'sum'</span>] │ {<span class="hljs-string">'s'</span>: <span class="hljs-string">'sum'</span>} ┃ +┠──────────────┼─────────────┼─────────────┼───────────────┨ +┃ s.apply(…) │ <span class="hljs-number">3</span> │ sum <span class="hljs-number">3</span> │ s <span class="hljs-number">3</span> ┃ +┃ s.agg(…) │ │ │ ┃ +┗━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ -┏━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ -┃ │ <span class="hljs-string">'rank'</span> │ [<span class="hljs-string">'rank'</span>] │ {<span class="hljs-string">'r'</span>: <span class="hljs-string">'rank'</span>} ┃ -┠───────────────┼─────────────┼─────────────┼───────────────┨ -┃ sr.apply(…) │ │ rank │ ┃ -┃ sr.agg(…) │ x <span class="hljs-number">1</span> │ x <span class="hljs-number">1</span> │ r x <span class="hljs-number">1</span> ┃ -┃ │ y <span class="hljs-number">2</span> │ y <span class="hljs-number">2</span> │ y <span class="hljs-number">2</span> ┃ -┗━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ +┏━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ +┃ │ <span class="hljs-string">'rank'</span> │ [<span class="hljs-string">'rank'</span>] │ {<span class="hljs-string">'r'</span>: <span class="hljs-string">'rank'</span>} ┃ +┠──────────────┼─────────────┼─────────────┼───────────────┨ +┃ s.apply(…) │ │ rank │ ┃ +┃ s.agg(…) │ x <span class="hljs-number">1.0</span> │ x <span class="hljs-number">1.0</span> │ r x <span class="hljs-number">1.0</span> ┃ +┃ │ y <span class="hljs-number">2.0</span> │ y <span class="hljs-number">2.0</span> │ y <span class="hljs-number">2.0</span> ┃ +┗━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ </code></pre> <ul> -<li><strong>Indexing objects can't be tuples because <code class="python hljs"><span class="hljs-string">'obj[x, y]'</span></code> is converted to <code class="python hljs"><span class="hljs-string">'obj[(x, y)]'</span></code>!</strong></li> <li><strong>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> +<li><strong>Last result has a multi-index. Use <code class="python hljs"><span class="hljs-string">'<S>[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>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 @@ -2638,25 +2638,29 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment </code></pre></div> -<pre><code class="python language-python hljs"><DF> = pd.DataFrame(<list_of_rows>) <span class="hljs-comment"># Rows can be either lists, dicts or series.</span> -<DF> = pd.DataFrame(<dict_of_columns>) <span class="hljs-comment"># Columns can be either lists, dicts or series.</span> +<pre><code class="python language-python hljs"><DF> = pd.DataFrame(<list_of_rows>) <span class="hljs-comment"># Rows can be either lists, dicts or series.</span> +<DF> = pd.DataFrame(<dict_of_columns>) <span class="hljs-comment"># Columns can be either lists, dicts or series.</span> +</code></pre> +<pre><code class="python language-python hljs"><el> = <DF>.loc[row_key, col_key] <span class="hljs-comment"># Or: <DF>.iloc[row_i, col_i]</span> +<S/DF> = <DF>.loc[row_key/s] <span class="hljs-comment"># Or: <DF>.iloc[row_i/s]</span> +<S/DF> = <DF>.loc[:, col_key/s] <span class="hljs-comment"># Or: <DF>.iloc[:, col_i/s]</span> +<DF> = <DF>.loc[row_bools, col_bools] <span class="hljs-comment"># Or: <DF>.iloc[row_bools, col_bools]</span> </code></pre> -<pre><code class="python language-python hljs"><el> = <DF>.loc[row_key, col_key] <span class="hljs-comment"># Or: <DF>.iloc[row_i, col_i]</span> -<Sr/DF> = <DF>.loc[row_key/s] <span class="hljs-comment"># Or: <DF>.iloc[row_i/s]</span> -<Sr/DF> = <DF>.loc[:, col_key/s] <span class="hljs-comment"># Or: <DF>.iloc[:, col_i/s]</span> -<DF> = <DF>.loc[row_bools, col_bools] <span class="hljs-comment"># Or: <DF>.iloc[row_bools, col_bools]</span> +<pre><code class="python language-python hljs"><S/DF> = <DF>[col_key/s] <span class="hljs-comment"># Or: <DF>.<col_key></span> +<DF> = <DF>[row_bools] <span class="hljs-comment"># Keeps rows as specified by bools.</span> +<DF> = <DF>[<DF_of_bools>] <span class="hljs-comment"># Assigns NaN to items that are False in bools.</span> </code></pre> -<pre><code class="python language-python hljs"><Sr/DF> = <DF>[col_key/s] <span class="hljs-comment"># Or: <DF>.<col_key></span> -<DF> = <DF>[row_bools] <span class="hljs-comment"># Keeps rows as specified by bools.</span> -<DF> = <DF>[<DF_of_bools>] <span class="hljs-comment"># Assigns NaN to items that are False in bools.</span> +<pre><code class="python language-python hljs"><DF> = <DF> > <el/S/DF> <span class="hljs-comment"># Returns DF of bools. S is treated as a row.</span> +<DF> = <DF> + <el/S/DF> <span class="hljs-comment"># Items with non-matching keys get value NaN.</span> </code></pre> -<pre><code class="python language-python hljs"><DF> = <DF> > <el/Sr/DF> <span class="hljs-comment"># Returns DF of bools. Sr is treated as a row.</span> -<DF> = <DF> + <el/Sr/DF> <span class="hljs-comment"># Items with non-matching keys get value NaN.</span> +<pre><code class="python language-python hljs"><DF> = <DF>.set_index(col_key) <span class="hljs-comment"># Replaces row keys with column's values.</span> +<DF> = <DF>.reset_index(drop=<span class="hljs-keyword">False</span>) <span class="hljs-comment"># Drops or moves row keys to column named index.</span> +<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> -<pre><code class="python language-python hljs"><DF> = <DF>.set_index(col_key) <span class="hljs-comment"># Replaces row keys with column's values.</span> -<DF> = <DF>.reset_index(drop=<span class="hljs-keyword">False</span>) <span class="hljs-comment"># Drops or moves row keys to column named index.</span> -<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> +<pre><code class="python language-python hljs"><DF> = <DF>.head/tail/sample(<int>) <span class="hljs-comment"># Returns first, last, or random n rows.</span> +<DF> = <DF>.describe() <span class="hljs-comment"># Describes columns. Also info(), corr(), shape.</span> +<DF> = <DF>.query(<span class="hljs-string">'<query>'</span>) <span class="hljs-comment"># Filters rows with e.g. 'col_1 == val_1 and …'.</span> </code></pre> <pre><code class="python language-python hljs"><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> @@ -2684,52 +2688,47 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment ┃ axis=<span class="hljs-number">0</span>, │ a <span class="hljs-number">1</span> <span class="hljs-number">2</span> . │ <span class="hljs-number">2</span> │ │ Uses <span class="hljs-string">'outer'</span> by default. ┃ ┃ join=…) │ b <span class="hljs-number">3</span> <span class="hljs-number">4</span> . │ <span class="hljs-number">4</span> │ │ A Series is treated as a ┃ ┃ │ b . <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ <span class="hljs-number">4</span> │ │ column. To add a row use ┃ -┃ │ c . <span class="hljs-number">6</span> <span class="hljs-number">7</span> │ <span class="hljs-number">6</span> │ │ pd.concat([l, DF([sr])]).┃ +┃ │ c . <span class="hljs-number">6</span> <span class="hljs-number">7</span> │ <span class="hljs-number">6</span> │ │ pd.concat([l, DF([s])]). ┃ ┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨ ┃ pd.concat([l, r], │ x y y z │ │ │ Adds columns at the ┃ ┃ axis=<span class="hljs-number">1</span>, │ a <span class="hljs-number">1</span> <span class="hljs-number">2</span> . . │ x y y z │ │ right end. Uses <span class="hljs-string">'outer'</span> ┃ ┃ join=…) │ b <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ │ by default. A Series is ┃ ┃ │ c . . <span class="hljs-number">6</span> <span class="hljs-number">7</span> │ │ │ treated as a column. ┃ -┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨ -┃ l.combine_first(r) │ x y z │ │ │ Adds missing rows and ┃ -┃ │ a <span class="hljs-number">1</span> <span class="hljs-number">2</span> . │ │ │ columns. Also updates ┃ -┃ │ b <span class="hljs-number">3</span> <span class="hljs-number">4</span> <span class="hljs-number">5</span> │ │ │ items that contain NaN. ┃ -┃ │ c . <span class="hljs-number">6</span> <span class="hljs-number">7</span> │ │ │ Argument r must be a DF. ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━┛ </code></pre> -<div><h4 id="dataframeaggregatetransformmap">DataFrame — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs"><Sr> = <DF>.sum/max/mean/idxmax/all() <span class="hljs-comment"># Or: <DF>.apply/agg(lambda <Sr>: <el>)</span> -<DF> = <DF>.rank/diff/cumsum/ffill/interpo…() <span class="hljs-comment"># Or: <DF>.apply/agg/transfo…(lambda <Sr>: <Sr>)</span> -<DF> = <DF>.fillna(<el>) <span class="hljs-comment"># Or: <DF>.applymap(lambda <el>: <el>)</span> +<div><h4 id="dataframeaggregatetransformmap">DataFrame — Aggregate, Transform, Map:</h4><pre><code class="python language-python hljs"><S> = <DF>.sum/max/mean/idxmax/all() <span class="hljs-comment"># Or: <DF>.apply/agg(lambda <S>: <el>)</span> +<DF> = <DF>.rank/diff/cumsum/ffill/interpo…() <span class="hljs-comment"># Or: <DF>.apply/agg/transform(lambda <S>: <S>)</span> +<DF> = <DF>.isna/fillna/isin([<el/coll>]) <span class="hljs-comment"># Or: <S>.agg/transform/map(lambda <el>: <el>)</span> </code></pre></div> -<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>]); 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> -</code></pre> -<pre><code class="python hljs">┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ -┃ │ <span class="hljs-string">'sum'</span> │ [<span class="hljs-string">'sum'</span>] │ {<span class="hljs-string">'x'</span>: <span class="hljs-string">'sum'</span>} ┃ -┠─────────────────┼─────────────┼─────────────┼───────────────┨ -┃ df.apply(…) │ x <span class="hljs-number">4</span> │ x y │ x <span class="hljs-number">4</span> ┃ -┃ df.agg(…) │ y <span class="hljs-number">6</span> │ sum <span class="hljs-number">4</span> <span class="hljs-number">6</span> │ ┃ -┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ +<pre><code class="python hljs">┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ +┃ │ <span class="hljs-string">'sum'</span> │ [<span class="hljs-string">'sum'</span>] │ {<span class="hljs-string">'x'</span>: <span class="hljs-string">'sum'</span>} ┃ +┠────────────────┼───────────────┼───────────────┼───────────────┨ +┃ l.apply(…) │ x <span class="hljs-number">4</span> │ x y │ x <span class="hljs-number">4</span> ┃ +┃ l.agg(…) │ y <span class="hljs-number">6</span> │ sum <span class="hljs-number">4</span> <span class="hljs-number">6</span> │ ┃ +┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ -┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ -┃ │ <span class="hljs-string">'rank'</span> │ [<span class="hljs-string">'rank'</span>] │ {<span class="hljs-string">'x'</span>: <span class="hljs-string">'rank'</span>} ┃ -┠─────────────────┼─────────────┼─────────────┼───────────────┨ -┃ df.apply(…) │ │ x y │ ┃ -┃ df.agg(…) │ x y │ rank rank │ x ┃ -┃ df.transform(…) │ a <span class="hljs-number">1</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> ┃ -┃ │ b <span class="hljs-number">2</span> <span class="hljs-number">2</span> │ b <span class="hljs-number">2</span> <span class="hljs-number">2</span> │ b <span class="hljs-number">2</span> ┃ -┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ +┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓ +┃ │ <span class="hljs-string">'rank'</span> │ [<span class="hljs-string">'rank'</span>] │ {<span class="hljs-string">'x'</span>: <span class="hljs-string">'rank'</span>} ┃ +┠────────────────┼───────────────┼───────────────┼───────────────┨ +┃ l.apply(…) │ │ x y │ ┃ +┃ l.agg(…) │ x y │ rank rank │ x ┃ +┃ l.transform(…) │ a <span class="hljs-number">1.0</span> <span class="hljs-number">1.0</span> │ a <span class="hljs-number">1.0</span> <span class="hljs-number">1.0</span> │ a <span class="hljs-number">1.0</span> ┃ +┃ │ b <span class="hljs-number">2.0</span> <span class="hljs-number">2.0</span> │ b <span class="hljs-number">2.0</span> <span class="hljs-number">2.0</span> │ b <span class="hljs-number">2.0</span> ┃ +┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛ </code></pre> <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> +<li><strong>All methods operate on columns by default. Pass <code class="python hljs"><span class="hljs-string">'axis=1'</span></code> to process the rows instead.</strong></li> +<li><strong>Fifth result's columns are indexed with a multi-index. This means we need a tuple of column keys to specify a column: <code class="python hljs"><span class="hljs-string">'<DF>.loc[row_key, (col_key_1, col_key_2)]'</span></code>.</strong></li> </ul> +<div><h4 id="dataframemultiindex">DataFrame — Multi-Index:</h4><pre><code class="python language-python hljs"><DF> = <DF>.xs(row_key, level=<int>) <span class="hljs-comment"># Rows with key on passed level of multi-index.</span> +<DF> = <DF>.xs(row_keys, level=<ints>) <span class="hljs-comment"># Rows that have first key on first level, etc.</span> +<DF> = <DF>.set_index(col_keys) <span class="hljs-comment"># Combines multiple columns into a multi-index.</span> +<S/DF> = <DF>.stack/unstack(level=<span class="hljs-number">-1</span>) <span class="hljs-comment"># Combines col keys with row keys or vice versa.</span> +<DF> = <DF>.pivot_table(index=col_key/s) <span class="hljs-comment"># `columns=key/s, values=key/s, aggfunc='mean'`.</span> +</code></pre></div> + <div><h4 id="dataframeencodedecode">DataFrame — Encode, Decode:</h4><pre><code class="python language-python hljs"><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> @@ -2743,41 +2742,38 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment </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> +<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">'<S> = pd.to_datetime(<S>, 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">'<S>.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>)) +<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"><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, S or el.</span> +<DF> = <GB>.filter(<func>) <span class="hljs-comment"># Drops a group if function returns False.</span> +<DF> = <GB>.get_group(<el>) <span class="hljs-comment"># Selects a group by grouping column's value.</span> +<S> = <GB>.size() <span class="hljs-comment"># S of group sizes. Same keys as get_group().</span> +<GB> = <GB>[col_key] <span class="hljs-comment"># Single column GB. All operations return S.</span> +</code></pre></div> + + +<pre><code class="python language-python hljs"><DF> = <GB>.sum/max/mean/idxmax/all() <span class="hljs-comment"># Or: <GB>.agg(lambda <S>: <el>)</span> +<DF> = <GB>.rank/diff/cumsum/ffill() <span class="hljs-comment"># Or: <GB>.transform(lambda <S>: <S>)</span> +<DF> = <GB>.fillna(<el>) <span class="hljs-comment"># Or: <GB>.transform(lambda <S>: <S>)</span> +</code></pre> +<div><h4 id="dividesrowsintogroupsandsumstheircolumnsresulthasanamedindexthatcreatescolumnzonreset_index">Divides rows into groups and sums their columns. Result has a named index that creates column <code class="python hljs"><span class="hljs-string">'z'</span></code> on reset_index():</h4><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>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> - - -<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> -<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.sum() +c <span class="hljs-number">7</span> <span class="hljs-number">8</span> <span class="hljs-number">6</span> +<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>[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> +<span class="hljs-number">6</span> <span class="hljs-number">11</span> <span class="hljs-number">13</span></code></pre></div> + +<div><h3 id="rolling">Rolling</h3><p><strong>Object for rolling window calculations.</strong></p><pre><code class="python language-python hljs"><RS/RDF/RGB> = <S/DF/GB>.rolling(win_size) <span class="hljs-comment"># Also: `min_periods=None, center=False`.</span> +<RS/RDF/RGB> = <RDF/RGB>[col_key/s] <span class="hljs-comment"># Or: <RDF/RGB>.col_key</span> +<S/DF> = <R>.mean/sum/max() <span class="hljs-comment"># Or: <R>.apply/agg(<agg_func/str>)</span> </code></pre></div> @@ -2787,7 +2783,7 @@ <h3 id="format-2">Format</h3><div><h4 id="forstandardtypesizesandmanualalignment <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> +<Fig>.write_html/json/image(<span class="hljs-string">'<path>'</span>) <span class="hljs-comment"># <Fig>.show() displays the plot.</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> @@ -2923,12 +2919,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> +<li><strong>Click on the title's <code class="python hljs"><span class="hljs-string">'#'</span></code> to get a link to its section.</strong></li> </ul></div> <footer> - <aside>October 28, 2024</aside> + <aside>November 29, 2024</aside> <a href="https://gto76.github.io" rel="author">Jure Šorn</a> </footer> diff --git a/parse.js b/parse.js index bb68554f1..16488b508 100755 --- a/parse.js +++ b/parse.js @@ -36,8 +36,8 @@ const TOC = ' <strong><span class="hljs-string">\'3. Syntax\'</span></strong>: [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>],\n' + ' <strong><span class="hljs-string">\'4. System\'</span></strong>: [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">Command_Line_Arguments</a>, <a href="#open">Open</a>, <a href="#paths">Path</a>, <a href="#oscommands">OS_Commands</a>],\n' + ' <strong><span class="hljs-string">\'5. Data\'</span></strong>: [<a href="#json">JSON</a>, <a href="#pickle">Pickle</a>, <a href="#csv">CSV</a>, <a href="#sqlite">SQLite</a>, <a href="#bytes">Bytes</a>, <a href="#struct">Struct</a>, <a href="#array">Array</a>, <a href="#memoryview">Memory_View</a>, <a href="#deque">Deque</a>],\n' + - ' <strong><span class="hljs-string">\'6. Advanced\'</span></strong>: [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],\n' + - ' <strong><span class="hljs-string">\'7. Libraries\'</span></strong>: [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>, <a href="#consoleapp">Console_App</a>, <a href="#guiapp">GUI</a>, <a href="#scraping">Scraping</a>, <a href="#web">Web</a>, <a href="#profiling">Profile</a>],\n' + + ' <strong><span class="hljs-string">\'6. Advanced\'</span></strong>: [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],\n' + + ' <strong><span class="hljs-string">\'7. Libraries\'</span></strong>: [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>, <a href="#consoleapp">Console_App</a>, <a href="#guiapp">GUI</a>, <a href="#scraping">Scraping</a>, <a href="#webapp">Web</a>, <a href="#profiling">Profile</a>],\n' + ' <strong><span class="hljs-string">\'8. Multimedia\'</span></strong>: [<a href="#numpy">NumPy</a>, <a href="#image">Image</a>, <a href="#animation">Animation</a>, <a href="#audio">Audio</a>, <a href="#synthesizer">Synthesizer</a>, <a href="#pygame">Pygame</a>, <a href="#pandas">Pandas</a>, <a href="#plotly">Plotly</a>]\n' + '}\n' + '</code></pre>\n'; @@ -84,11 +84,6 @@ const CONSTRUCTOR_OVERLOADING = ' <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">__init__</span><span class="hljs-params">(self, a=<span class="hljs-keyword">None</span>)</span>:</span>\n' + ' self.a = a\n'; -const DATACLASS = - '<class> = make_dataclass(<span class="hljs-string">\'<class_name>\'</span>, <coll_of_attribute_names>)\n' + - '<class> = make_dataclass(<span class="hljs-string">\'<class_name>\'</span>, <coll_of_tuples>)\n' + - '<tuple> = (<span class="hljs-string">\'<attr_name>\'</span>, <type> [, <default_value>])'; - const SHUTIL_COPY = 'shutil.copy(from, to) <span class="hljs-comment"># Copies the file. \'to\' can exist or be a dir.</span>\n' + 'shutil.copy2(from, to) <span class="hljs-comment"># Also copies creation and modification time.</span>\n' + @@ -221,7 +216,7 @@ const AUDIO_1 = ' <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_bytes</span><span class="hljs-params">(a_float)</span>:</span>\n' + ' a_float = max(<span class="hljs-number">-1</span>, min(<span class="hljs-number">1</span> - <span class="hljs-number">2e-16</span>, a_float))\n' + ' a_float += p.sampwidth == <span class="hljs-number">1</span>\n' + - ' a_float *= pow(<span class="hljs-number">2</span>, p.sampwidth * <span class="hljs-number">8</span> - <span class="hljs-number">1</span>)\n' + + ' a_float *= pow(<span class="hljs-number">2</span>, (p.sampwidth * <span class="hljs-number">8</span>) - <span class="hljs-number">1</span>)\n' + ' <span class="hljs-keyword">return</span> int(a_float).to_bytes(p.sampwidth, <span class="hljs-string">\'little\'</span>, signed=(p.sampwidth != <span class="hljs-number">1</span>))\n' + ' <span class="hljs-keyword">if</span> p <span class="hljs-keyword">is</span> <span class="hljs-keyword">None</span>:\n' + ' p = wave._wave_params(nchannels, sampwidth, framerate, <span class="hljs-number">0</span>, <span class="hljs-string">\'NONE\'</span>, <span class="hljs-string">\'not compressed\'</span>)\n' + @@ -316,7 +311,13 @@ const GROUPBY = 'a <span class="hljs-number">1</span> <span class="hljs-number">2</span> <span class="hljs-number">3</span>\n' + ' x y z\n' + 'b <span class="hljs-number">4</span> <span class="hljs-number">5</span> <span class="hljs-number">6</span>\n' + - 'c <span class="hljs-number">7</span> <span class="hljs-number">8</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>\n' + + '<span class="hljs-meta">>>> </span>gb.sum()\n' + + ' x y\n' + + 'z\n' + + '<span class="hljs-number">3</span> <span class="hljs-number">1</span> <span class="hljs-number">2</span>\n' + + '<span class="hljs-number">6</span> <span class="hljs-number">11</span> <span class="hljs-number">13</span>'; + const CYTHON_1 = '<span class="hljs-keyword">cdef</span> <ctype> <var_name> = <obj>\n' + @@ -336,7 +337,7 @@ const INDEX = '<li><strong>Only available in the <a href="https://transactions.sendowl.com/products/78175486/4422834F/view">PDF</a>.</strong></li>\n' + '<li><strong>Ctrl+F / ⌘F is usually sufficient.</strong></li>\n' + '<li><strong>Searching <code class="python hljs"><span class="hljs-string">\'#<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'; + '<li><strong>Click on the title\'s <code class="python hljs"><span class="hljs-string">\'#\'</span></code> to get a link to its section.</strong></li>\n'; const DIAGRAM_1_A = @@ -576,26 +577,26 @@ const DIAGRAM_12_B = '┗━━━━━━━━━━━┷━━━━━━━━━━━┷━━━━━━┷━━━━━━━━━━━┛\n'; const DIAGRAM_13_A = - '| sr.apply(…) | 5 | sum 5 | s 5 |'; + '| s.apply(…) | 3 | sum 3 | s 3 |'; const DIAGRAM_13_B = - "┏━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" + - "┃ │ 'sum' │ ['sum'] │ {'s': 'sum'} ┃\n" + - "┠───────────────┼─────────────┼─────────────┼───────────────┨\n" + - "┃ sr.apply(…) │ 5 │ sum 5 │ s 5 ┃\n" + - "┃ sr.agg(…) │ │ │ ┃\n" + - "┗━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n" + + "┏━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" + + "┃ │ 'sum' │ ['sum'] │ {'s': 'sum'} ┃\n" + + "┠──────────────┼─────────────┼─────────────┼───────────────┨\n" + + "┃ s.apply(…) │ 3 │ sum 3 │ s 3 ┃\n" + + "┃ s.agg(…) │ │ │ ┃\n" + + "┗━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n" + "\n" + - "┏━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" + - "┃ │ 'rank' │ ['rank'] │ {'r': 'rank'} ┃\n" + - "┠───────────────┼─────────────┼─────────────┼───────────────┨\n" + - "┃ sr.apply(…) │ │ rank │ ┃\n" + - "┃ sr.agg(…) │ x 1 │ x 1 │ r x 1 ┃\n" + - "┃ │ y 2 │ y 2 │ y 2 ┃\n" + - "┗━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n"; + "┏━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" + + "┃ │ 'rank' │ ['rank'] │ {'r': 'rank'} ┃\n" + + "┠──────────────┼─────────────┼─────────────┼───────────────┨\n" + + "┃ s.apply(…) │ │ rank │ ┃\n" + + "┃ s.agg(…) │ x 1.0 │ x 1.0 │ r x 1.0 ┃\n" + + "┃ │ y 2.0 │ y 2.0 │ y 2.0 ┃\n" + + "┗━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n"; const DIAGRAM_14_A = - "| | 'rank' | ['rank'] | {'r': 'rank'} |"; + "| | 'rank' | ['rank'] | {'r': 'rank'} |"; const DIAGRAM_15_A = '+------------------------+---------------+------------+------------+--------------------------+'; @@ -618,41 +619,36 @@ const DIAGRAM_15_B = "┃ axis=0, │ a 1 2 . │ 2 │ │ Uses 'outer' by default. ┃\n" + "┃ join=…) │ b 3 4 . │ 4 │ │ A Series is treated as a ┃\n" + "┃ │ b . 4 5 │ 4 │ │ column. To add a row use ┃\n" + - "┃ │ c . 6 7 │ 6 │ │ pd.concat([l, DF([sr])]).┃\n" + + "┃ │ c . 6 7 │ 6 │ │ pd.concat([l, DF([s])]). ┃\n" + "┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨\n" + "┃ pd.concat([l, r], │ x y y z │ │ │ Adds columns at the ┃\n" + "┃ axis=1, │ a 1 2 . . │ x y y z │ │ right end. Uses 'outer' ┃\n" + "┃ join=…) │ b 3 4 4 5 │ 3 4 4 5 │ │ by default. A Series is ┃\n" + "┃ │ c . . 6 7 │ │ │ treated as a column. ┃\n" + - "┠────────────────────────┼───────────────┼────────────┼────────────┼──────────────────────────┨\n" + - "┃ l.combine_first(r) │ x y z │ │ │ Adds missing rows and ┃\n" + - "┃ │ a 1 2 . │ │ │ columns. Also updates ┃\n" + - "┃ │ b 3 4 5 │ │ │ items that contain NaN. ┃\n" + - "┃ │ c . 6 7 │ │ │ Argument r must be a DF. ┃\n" + "┗━━━━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━┛\n"; const DIAGRAM_16_A = - '| df.apply(…) | x 4 | x y | x 4 |'; + '| l.apply(…) | x 4 | x y | x 4 |'; const DIAGRAM_16_B = - "┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" + - "┃ │ 'sum' │ ['sum'] │ {'x': 'sum'} ┃\n" + - "┠─────────────────┼─────────────┼─────────────┼───────────────┨\n" + - "┃ df.apply(…) │ x 4 │ x y │ x 4 ┃\n" + - "┃ df.agg(…) │ y 6 │ sum 4 6 │ ┃\n" + - "┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n" + + "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" + + "┃ │ 'sum' │ ['sum'] │ {'x': 'sum'} ┃\n" + + "┠────────────────┼───────────────┼───────────────┼───────────────┨\n" + + "┃ l.apply(…) │ x 4 │ x y │ x 4 ┃\n" + + "┃ l.agg(…) │ y 6 │ sum 4 6 │ ┃\n" + + "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n" + "\n" + - "┏━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" + - "┃ │ 'rank' │ ['rank'] │ {'x': 'rank'} ┃\n" + - "┠─────────────────┼─────────────┼─────────────┼───────────────┨\n" + - "┃ df.apply(…) │ │ x y │ ┃\n" + - "┃ df.agg(…) │ x y │ rank rank │ x ┃\n" + - "┃ df.transform(…) │ a 1 1 │ a 1 1 │ a 1 ┃\n" + - "┃ │ b 2 2 │ b 2 2 │ b 2 ┃\n" + - "┗━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n"; + "┏━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━━━┓\n" + + "┃ │ 'rank' │ ['rank'] │ {'x': 'rank'} ┃\n" + + "┠────────────────┼───────────────┼───────────────┼───────────────┨\n" + + "┃ l.apply(…) │ │ x y │ ┃\n" + + "┃ l.agg(…) │ x y │ rank rank │ x ┃\n" + + "┃ l.transform(…) │ a 1.0 1.0 │ a 1.0 1.0 │ a 1.0 ┃\n" + + "┃ │ b 2.0 2.0 │ b 2.0 2.0 │ b 2.0 ┃\n" + + "┗━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━┛\n"; const DIAGRAM_17_A = - "| | 'rank' | ['rank'] | {'x': 'rank'} |"; + "| | 'rank' | ['rank'] | {'x': 'rank'} |"; const DIAGRAM_18_A = '| gb.agg(…) | x y | | x y | |'; @@ -841,7 +837,6 @@ function fixHighlights() { $(`code:contains(@debug(print_result=True))`).html(PARAMETRIZED_DECORATOR); $(`code:contains(print/str/repr([<obj>]))`).html(REPR_USE_CASES); $(`code:contains((self, a=None):)`).html(CONSTRUCTOR_OVERLOADING); - $(`code:contains(make_dataclass(\'<class_name>\')`).html(DATACLASS); $(`code:contains(shutil.copy)`).html(SHUTIL_COPY); $(`code:contains(os.rename)`).html(OS_RENAME); $(`code:contains(\'<n>s\')`).html(STRUCT_FORMAT); diff --git a/pdf/README.md b/pdf/README.md index 1a56493b0..6e806f125 100644 --- a/pdf/README.md +++ b/pdf/README.md @@ -14,8 +14,8 @@ Printing to PDF ### Normal PDF * Open `index.html` in text editor and first remove element `<p><br></p>` before the `<h1>Libraries</h1>`. * Then replace the index and footer with contents of `pdf/index_for_pdf.html` file and save. -* Disable internet connection and open the file in Chromium version 108.0.5328.0 (later versions will render the site incorrectly after index is added) with 'Cache killer' extension enabled. -* Right click on the border of the site and select inspect. Select `<body>` element under 'Elements' tab and change top margin from 16 to 0 and top padding from 16 to 5 in 'Styles' tab. +* Disable internet connection and open Chromium version 108.0.5328.0 (later versions will render the site incorrectly after index is added). Right click anywhere in the window and choose 'inspect'. Go to 'Network' tab and check 'Disable Cache'. Open the `index.html` file while keeping the inspect window open. +* Right click on the border of the site and select inspect. Select `<body>` element under 'Elements' tab and change top margin and top padding from 16 to 0 in 'Styles' tab. * Change brightness of comments by right clicking on one of them and selecting inspect. Then click on the rectangle that represents color and toggle the color space to HSLA by clicking on the button with two vertical arrows. Change lightness (L) percentage to 77%. * Change the brightness of text to 13%. * Select 'Print...' with destination 'Save as PDF', paper size 'A4', 'Default' margins (top 10mm, right 9.5mm, bottom 8mm and left 10mm), 'Default' scale and no headers and footers and save (the document should be 51 pages long with last page empty). @@ -26,8 +26,8 @@ Printing to PDF * Change all links in text to normal text and add a page number in brackets like that: '(p. <page_num>)' by running './pdf/remove_links.py' (Links can be found with this regex: `<strong>.*a href.*</strong>`). * Open `index.html` in text editor and first remove element `<p><br></p>` before the `<h1>Libraries</h1>`. * Then replace the index and footer with contents of `pdf/index_for_pdf_print.html` file and save. -* Disable internet connection and open the file in Chromium version 108.0.5328.0 (later versions will render the site incorrectly after index is added) with 'Cache killer' extension enabled. -* Right click on the border of the site and select inspect. Select `<body>` element under 'Elements' tab and change top margin from 16 to 0 and top padding from 16 to 5 in 'Styles' tab. +* Disable internet connection and open Chromium version 108.0.5328.0 (later versions will render the site incorrectly after index is added). Right click anywhere in the window and choose 'inspect'. Go to 'Network' tab and check 'Disable Cache'. Open the `index.html` file while keeping the inspect window open. +* Right click on the border of the site and select inspect. Select `<body>` element under 'Elements' tab and change top margin and top padding from 16 to 0 in 'Styles' tab. * Change brightness of elements by right clicking on them and selecting inspect. Then click on the rectangle that represents color and toggle the color space to HSLA by clicking on the button with two vertical arrows. * Change lightness (L) percentage to: * 0% for the text. diff --git a/pdf/index_for_pdf.html b/pdf/index_for_pdf.html index 54f6747f0..86a2722bb 100644 --- a/pdf/index_for_pdf.html +++ b/pdf/index_for_pdf.html @@ -14,7 +14,7 @@ <h3 id="a">A</h3> <h3 id="b">B</h3> <p><strong>beautifulsoup library, <a href="#scrapespythonsurlandlogofromitswikipediapage">35</a></strong><br> <strong>binary representation, <a href="#ints">7</a>, <a href="#binhex">8</a></strong><br> -<strong>bitwise operators, <a href="#bitwiseoperators">8</a>, <a href="#operator">31</a></strong><br> +<strong>bitwise operators, <a href="#bitwiseoperators">8</a>, <a href="#operator">30</a></strong><br> <strong>bytes, <a href="#open">22</a>-<a href="#modes">23</a>, <a href="#pickle">25</a>, <a href="#bytes">28</a>-<a href="#memoryview">29</a></strong> </p> <h3 id="c">C</h3> <p><strong>cache, <a href="#cache">13</a></strong><br> @@ -26,7 +26,7 @@ <h3 id="c">C</h3> <strong>combinatorics, <a href="#combinatorics">8</a></strong><br> <strong>command line arguments, <a href="#commandlinearguments">22</a></strong><br> <strong>comprehensions, <a href="#comprehensions">11</a></strong><br> -<strong>context manager, <a href="#contextmanager">17</a>, <a href="#readtextfromfile">23</a>, <a href="#or">27</a>, <a href="#or-1">30</a></strong><br> +<strong>context manager, <a href="#contextmanager">17</a>, <a href="#readtextfromfile">23</a>, <a href="#or">27</a>, <a href="#or-1">32</a></strong><br> <strong>copy function, <a href="#copy">15</a></strong><br> <strong>coroutine, <a href="#coroutines">33</a></strong><br> <strong>counter, <a href="#counter">2</a>, <a href="#generator">4</a>, <a href="#nonlocal">12</a>, <a href="#iterator-1">17</a></strong><br> @@ -44,7 +44,7 @@ <h3 id="e">E</h3> <p><strong>enum module, <a href="#enum">19</a>-<a href="#inline-1">20</a></strong><br> <strong>enumerate function, <a href="#enumerate">3</a></strong><br> <strong>excel, <a href="#dataframeencodedecode">46</a></strong><br> -<strong>exceptions, <a href="#exceptions">20</a>-<a href="#exceptionobject">21</a>, <a href="#exceptions-1">23</a>, <a href="#logging">32</a></strong><br> +<strong>exceptions, <a href="#exceptions">20</a>-<a href="#exceptionobject">21</a>, <a href="#exceptions-1">23</a>, <a href="#logging">31</a></strong><br> <strong>exit function, <a href="#exit">21</a></strong> </p> <h3 id="f">F</h3> <p><strong>files, <a href="#print">22</a>-<a href="#memoryview">29</a>, <a href="#runsabasicfileexplorerintheconsole">34</a>, <a href="#dataframeencodedecode">46</a></strong><br> @@ -57,7 +57,7 @@ <h3 id="g">G</h3> <p><strong>games, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a>, <a href="#pygame">42</a>-<a href="#basicmariobrothersexample">43</a></strong><br> <strong>generators, <a href="#generator">4</a>, <a href="#comprehensions">11</a>, <a href="#iterator-1">17</a></strong><br> <strong>global keyword, <a href="#nonlocal">12</a></strong><br> -<strong>gui, <a href="#guiapp">35</a></strong> </p> +<strong>gui app, <a href="#guiapp">35</a></strong> </p> <h3 id="h">H</h3> <p><strong>hashable, <a href="#dataclass">15</a>, <a href="#hashable">16</a></strong><br> <strong>hexadecimal representation, <a href="#ints">7</a>, <a href="#binhex">8</a>, <a href="#encode-1">28</a></strong> </p> @@ -66,9 +66,9 @@ <h3 id="i">I</h3> <strong>imports, <a href="#imports">12</a></strong><br> <strong>inline, <a href="#otheruses">11</a>, <a href="#dataclass">15</a>, <a href="#inline-1">20</a></strong><br> <strong>input function, <a href="#input">22</a></strong><br> -<strong>introspection, <a href="#exceptionobject">21</a>, <a href="#introspection">32</a></strong><br> -<strong>ints, <a href="#abstractbaseclasses">4</a>, <a href="#ints">7</a>, <a href="#random">8</a>, <a href="#encode-1">28</a></strong><br> -<strong>is operator, <a href="#comparable">16</a>, <a href="#operator">31</a></strong><br> +<strong>introspection, <a href="#exceptionobject">21</a>, <a href="#introspection">31</a></strong><br> +<strong>ints, <a href="#abstractbaseclasses">4</a>, <a href="#ints">7</a>-<a href="#random">8</a>, <a href="#encode-1">28</a></strong><br> +<strong>is operator, <a href="#comparable">16</a>, <a href="#operator">30</a></strong><br> <strong>iterable, <a href="#abstractbaseclasses">4</a>, <a href="#iterable">18</a>, <a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a></strong><br> <strong>iterator, <a href="#enumerate">3</a>-<a href="#generator">4</a>, <a href="#comprehensions">11</a>, <a href="#iterator-1">17</a></strong><br> <strong>itertools module, <a href="#itertools">3</a>, <a href="#combinatorics">8</a></strong> </p> @@ -76,25 +76,25 @@ <h3 id="j">J</h3> <p><strong>json, <a href="#json">25</a>, <a href="#restrequest">36</a>, <a href="#dataframeencodedecode">46</a></strong> </p> <h3 id="l">L</h3> <p><strong>lambda, <a href="#lambda">11</a></strong><br> -<strong>lists, <a href="#list">1</a>-<a href="#list">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br> +<strong>lists, <a href="#list">1</a>-<a href="#list">2</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a>, <a href="#collectionsandtheirexceptions">21</a></strong><br> <strong>locale module, <a href="#sortable">16</a></strong><br> -<strong>logging, <a href="#logging">32</a></strong> </p> +<strong>logging, <a href="#logging">31</a></strong> </p> <h3 id="m">M</h3> <p><strong>main function, <a href="#main">1</a>, <a href="#basicscripttemplate">49</a></strong><br> -<strong>match statement, <a href="#matchstatement">31</a></strong><br> -<strong>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>match statement, <a href="#matchstatement">30</a></strong><br> +<strong>matplotlib library, <a href="#plot">34</a>, <a href="#pandas">44</a>, <a href="#dataframe">45</a></strong><br> +<strong>map function, <a href="#mapfilterreduce">11</a>, <a href="#operator">30</a></strong><br> <strong>math module, <a href="#numbers">7</a></strong><br> <strong>memoryviews, <a href="#memoryview">29</a></strong><br> <strong>module, <a href="#imports">12</a></strong> </p> <h3 id="n">N</h3> -<p><strong>namedtuples, <a href="#namedtuple">3</a></strong><br> +<p><strong>namedtuples, <a href="#namedtuple">3</a>, <a href="#example">6</a></strong><br> <strong>nonlocal keyword, <a href="#nonlocal">12</a></strong><br> <strong>numbers, <a href="#abstractbaseclasses">4</a>, <a href="#numbers-1">6</a>-<a href="#random">8</a></strong><br> -<strong>numpy library, <a href="#numpy">37</a>-<a href="#indexing">38</a></strong> </p> +<strong>numpy library, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#image">39</a>, <a href="#series">44</a></strong> </p> <h3 id="o">O</h3> -<p><strong>open function, <a href="#contextmanager">17</a>, <a href="#open">22</a>-<a href="#modes">23</a>, <a href="#readobjectfromjsonfile">25</a>, <a href="#readrowsfromcsvfile">26</a>, <a href="#readbytesfromfile">28</a></strong><br> -<strong>operator module, <a href="#operator">31</a></strong><br> +<p><strong>open function, <a href="#contextmanager">17</a>, <a href="#open">22</a>-<a href="#modes">23</a>, <a href="#readcollectionfromjsonfile">25</a>, <a href="#readrowsfromcsvfile">26</a>, <a href="#readbytesfromfile">28</a></strong><br> +<strong>operator module, <a href="#operator">30</a></strong><br> <strong>os commands, <a href="#paths">23</a>-<a href="#shellcommands">25</a>, <a href="#runsabasicfileexplorerintheconsole">34</a></strong> </p> <h3 id="p">P</h3> <p><strong>pandas library, <a href="#pandas">44</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br> @@ -102,19 +102,19 @@ <h3 id="p">P</h3> <strong>paths, <a href="#paths">23</a>-<a href="#oscommands">24</a>, <a href="#runsabasicfileexplorerintheconsole">34</a></strong><br> <strong>pickle module, <a href="#pickle">25</a></strong><br> <strong>pillow library, <a href="#image">39</a>-<a href="#animation">40</a></strong><br> -<strong>plotting, <a href="#plot">34</a>, <a href="#series">44</a>, <a href="#dataframeencodedecode">46</a>, <a href="#plotly">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br> +<strong>plotting, <a href="#plot">34</a>, <a href="#pandas">44</a>, <a href="#dataframe">45</a>, <a href="#plotly">47</a>-<a href="#displaysamultiaxislinechartoftotalcoronaviruscasesandchangesinpricesofbitcoindowjonesandgold">48</a></strong><br> <strong>print function, <a href="#class">14</a>, <a href="#print">22</a></strong><br> <strong>profiling, <a href="#profiling">36</a>-<a href="#profilingbyline">37</a></strong><br> <strong>progress bar, <a href="#progressbar">34</a></strong><br> -<strong>property decorator, <a href="#property">15</a></strong><br> +<strong>property decorator, <a href="#property">15</a>, <a href="#hashable">16</a></strong><br> <strong>pygame library, <a href="#pygame">42</a>-<a href="#basicmariobrothersexample">43</a></strong> </p> <h3 id="q">Q</h3> -<p><strong>queues, <a href="#deque">29</a>, <a href="#queue">30</a>, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a></strong> </p> +<p><strong>queues, <a href="#deque">29</a>, <a href="#queue">32</a>, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a></strong> </p> <h3 id="r">R</h3> -<p><strong>random module, <a href="#random">8</a></strong><br> +<p><strong>random module, <a href="#random">8</a>, <a href="#runsaterminalgamewhereyoucontrolanasteriskthatmustavoidnumbers">33</a>, <a href="#addsnoisetothewavfile">41</a></strong><br> <strong>ranges, <a href="#range">3</a>, <a href="#abstractbaseclasses">4</a></strong><br> <strong>recursion, <a href="#cache">13</a>, <a href="#builtinexceptions">21</a></strong><br> -<strong>reduce function, <a href="#mapfilterreduce">11</a>, <a href="#operator">31</a></strong><br> +<strong>reduce function, <a href="#mapfilterreduce">11</a></strong><br> <strong>regular expressions, <a href="#regex">5</a>-<a href="#specialsequences">6</a></strong><br> <strong>requests library, <a href="#scrapespythonsurlandlogofromitswikipediapage">35</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong> </p> <h3 id="s">S</h3> @@ -136,12 +136,12 @@ <h3 id="s">S</h3> <h3 id="t">T</h3> <p><strong>table, <a href="#csv">26</a>, <a href="#example-1">27</a>, <a href="#table">34</a>, <a href="#numpy">37</a>-<a href="#indexing">38</a>, <a href="#dataframe">45</a>-<a href="#dataframeaggregatetransformmap">46</a></strong><br> <strong>template, <a href="#format">6</a>, <a href="#dynamicrequest">36</a></strong><br> -<strong>threading module, <a href="#threading">30</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong><br> +<strong>threading module, <a href="#threading">32</a>, <a href="#startstheappinitsownthreadandqueriesitsrestapi">36</a></strong><br> <strong>time module, <a href="#progressbar">34</a>, <a href="#profiling">36</a></strong><br> -<strong>tuples, <a href="#tuple">3</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#tableofrequiredandautomaticallyavailablespecialmethods">19</a></strong><br> -<strong>type, <a href="#type">4</a></strong><br> -<strong>type annotations, <a href="#typeannotations">15</a>, <a href="#introspection">32</a></strong> </p> +<strong>tuples, <a href="#tuple">3</a>, <a href="#abstractbaseclasses">4</a>, <a href="#otheruses">11</a>, <a href="#sequence">18</a>-<a href="#abcsequence">19</a></strong><br> +<strong>type, <a href="#type">4</a>, <a href="#ducktypes">16</a>, <a href="#matchstatement">30</a></strong><br> +<strong>type annotations, <a href="#typeannotations">15</a>, <a href="#introspection">31</a></strong> </p> <h3 id="w">W</h3> <p><strong>wave module, <a href="#audio">40</a>-<a href="#writefloatsamplestowavfile">41</a></strong><br> -<strong>web, <a href="#webapp">36</a></strong> </p> +<strong>web app, <a href="#webapp">36</a></strong> </p> </div> \ No newline at end of file diff --git a/pdf/index_for_pdf_print.html b/pdf/index_for_pdf_print.html index e7bdcfeb7..41ecf8940 100644 --- a/pdf/index_for_pdf_print.html +++ b/pdf/index_for_pdf_print.html @@ -14,7 +14,7 @@ <h3 id="a">A</h3> <h3 id="b">B</h3> <p><strong>beautifulsoup library, 35</strong><br> <strong>binary representation, 7, 8</strong><br> -<strong>bitwise operators, 8, 31</strong><br> +<strong>bitwise operators, 8, 30</strong><br> <strong>bytes, 22-23, 25, 28-29</strong> </p> <h3 id="c">C</h3> <p><strong>cache, 13</strong><br> @@ -26,7 +26,7 @@ <h3 id="c">C</h3> <strong>combinatorics, 8</strong><br> <strong>command line arguments, 22</strong><br> <strong>comprehensions, 11</strong><br> -<strong>context manager, 17, 23, 27, 30</strong><br> +<strong>context manager, 17, 23, 27, 32</strong><br> <strong>copy function, 15</strong><br> <strong>coroutine, 33</strong><br> <strong>counter, 2, 4, 12, 17</strong><br> @@ -44,7 +44,7 @@ <h3 id="e">E</h3> <p><strong>enum module, 19-20</strong><br> <strong>enumerate function, 3</strong><br> <strong>excel, 46</strong><br> -<strong>exceptions, 20-21, 23, 32</strong><br> +<strong>exceptions, 20-21, 23, 31</strong><br> <strong>exit function, 21</strong> </p> <h3 id="f">F</h3> <p><strong>files, 22-29, 34, 46</strong><br> @@ -66,9 +66,9 @@ <h3 id="i">I</h3> <strong>imports, 12</strong><br> <strong>inline, 11, 15, 20</strong><br> <strong>input function, 22</strong><br> -<strong>introspection, 21, 32</strong><br> -<strong>ints, 4, 7, 8, 28</strong><br> -<strong>is operator, 16, 31</strong><br> +<strong>introspection, 21, 31</strong><br> +<strong>ints, 4, 7-8, 28</strong><br> +<strong>is operator, 16, 30</strong><br> <strong>iterable, 4, 18, 19</strong><br> <strong>iterator, 3-4, 11, 17</strong><br> <strong>itertools module, 3, 8</strong> </p> @@ -78,23 +78,23 @@ <h3 id="l">L</h3> <p><strong>lambda, 11</strong><br> <strong>lists, 1-2, 4, 11, 18-19, 21</strong><br> <strong>locale module, 16</strong><br> -<strong>logging, 32</strong> </p> +<strong>logging, 31</strong> </p> <h3 id="m">M</h3> <p><strong>main function, 1, 49</strong><br> -<strong>match statement, 31</strong><br> -<strong>matplotlib library, 34, 44, 46</strong><br> -<strong>map function, 11, 31</strong><br> +<strong>match statement, 30</strong><br> +<strong>matplotlib library, 34, 44, 45</strong><br> +<strong>map function, 11, 30</strong><br> <strong>math module, 7</strong><br> <strong>memoryviews, 29</strong><br> <strong>module, 12</strong> </p> <h3 id="n">N</h3> -<p><strong>namedtuples, 3</strong><br> +<p><strong>namedtuples, 3, 6</strong><br> <strong>nonlocal keyword, 12</strong><br> <strong>numbers, 4, 6-8</strong><br> -<strong>numpy library, 37-38</strong> </p> +<strong>numpy library, 37-38, 39, 44</strong> </p> <h3 id="o">O</h3> <p><strong>open function, 17, 22-23, 25, 26, 28</strong><br> -<strong>operator module, 31</strong><br> +<strong>operator module, 30</strong><br> <strong>os commands, 23-25, 34</strong> </p> <h3 id="p">P</h3> <p><strong>pandas library, 44-48</strong><br> @@ -102,19 +102,19 @@ <h3 id="p">P</h3> <strong>paths, 23-24, 34</strong><br> <strong>pickle module, 25</strong><br> <strong>pillow library, 39-40</strong><br> -<strong>plotting, 34, 44, 46, 47-48</strong><br> +<strong>plotting, 34, 44, 45, 47-48</strong><br> <strong>print function, 14, 22</strong><br> <strong>profiling, 36-37</strong><br> <strong>progress bar, 34</strong><br> -<strong>property decorator, 15</strong><br> +<strong>property decorator, 15, 16</strong><br> <strong>pygame library, 42-43</strong> </p> <h3 id="q">Q</h3> -<p><strong>queues, 29, 30, 33</strong> </p> +<p><strong>queues, 29, 32, 33</strong> </p> <h3 id="r">R</h3> -<p><strong>random module, 8</strong><br> +<p><strong>random module, 8, 33, 41</strong><br> <strong>ranges, 3, 4</strong><br> <strong>recursion, 13, 21</strong><br> -<strong>reduce function, 11, 31</strong><br> +<strong>reduce function, 11</strong><br> <strong>regular expressions, 5-6</strong><br> <strong>requests library, 35, 36</strong> </p> <h3 id="s">S</h3> @@ -136,11 +136,11 @@ <h3 id="s">S</h3> <h3 id="t">T</h3> <p><strong>table, 26, 27, 34, 37-38, 45-46</strong><br> <strong>template, 6, 36</strong><br> -<strong>threading module, 30, 36</strong><br> +<strong>threading module, 32, 36</strong><br> <strong>time module, 34, 36</strong><br> <strong>tuples, 3, 4, 11, 18-19</strong><br> -<strong>type, 4</strong><br> -<strong>type annotations, 15, 32</strong> </p> +<strong>type, 4, 16, 30</strong><br> +<strong>type annotations, 15, 31</strong> </p> <h3 id="w">W</h3> <p><strong>wave module, 40-41</strong><br> <strong>web, 36</strong> </p> diff --git a/pdf/remove_links.py b/pdf/remove_links.py index b7463b2bf..65fec859b 100755 --- a/pdf/remove_links.py +++ b/pdf/remove_links.py @@ -7,8 +7,9 @@ MATCHES = { - '<strong>For details about sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong>': '<strong>For details about sorted(), min() and max() see sortable (p. 16).</strong>', - '<strong>Module <a href="#operator">operator</a> provides functions itemgetter() and mul() that offer the same functionality as <a href="#lambda">lambda</a> expressions above.</strong>': '<strong>Module \'operator\' (p. 31) provides functions itemgetter() and mul() that offer the same functionality as lambda expressions (p. 11) above.</strong>', + '<strong>For details about sort(), sorted(), min() and max() see <a href="#sortable">sortable</a>.</strong>': '<strong>For details about sort(), sorted(), min() and max() see sortable (p. 16).</strong>', + '<strong>Module <a href="#operator">operator</a> has function itemgetter() that can replace listed <a href="#lambda">lambdas</a>.</strong>': '<strong>Module \'operator\' (p. 31) has function itemgetter() that can replace listed lambdas (p. 11).</strong>', + '<strong>This text uses the term \'collection\' instead of \'iterable\'. For rationale see <a href="#collection">collection</a>.</strong>': '<strong>This text uses the term \'collection\' instead of \'iterable\'. For rationale see collection (p. 18).</strong>', '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its <a href="#class">repr()</a> method.</strong>': '<strong>Adding <code class="python hljs"><span class="hljs-string">\'!r\'</span></code> to the expression converts object to string by calling its repr() method.</strong>', '<strong>It can be any <a href="#callable">callable</a>, but is usually implemented as a function that returns a <a href="#closure">closure</a>.</strong>': '<strong>It can be any callable, but is usually implemented as a function that returns a closure.</strong>', '<strong>Hints are used by type checkers like <a href="https://pypi.org/project/mypy/">mypy</a>, data validation libraries such as <a href="https://pypi.org/project/pydantic/">Pydantic</a> and lately also by <a href="https://pypi.org/project/Cython/">Cython</a> compiler. However, they are not enforced by CPython interpreter.</strong>': '<strong>Hints are used by type checkers like mypy, data validation libraries such as Pydantic and lately also by Cython compiler. However, they are not enforced by CPython interpreter.</strong>', @@ -19,15 +20,14 @@ '<strong>Objects returned by the <a href="#itertools">itertools</a> module, such as count, repeat and cycle.</strong>': '<strong>Objects returned by the itertools module, such as count, repeat and cycle (p. 3).</strong>', '<strong>Generators returned by the <a href="#generator">generator functions</a> and <a href="#comprehensions">generator expressions</a>.</strong>': '<strong>Generators returned by the generator functions (p. 4) and generator expressions (p. 11).</strong>', '<strong>File objects returned by the <a href="#open">open()</a> function, etc.</strong>': '<strong>File objects returned by the open() function (p. 22), etc.</strong>', - '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(<message>)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">logging</a>.</strong>': '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(<message>)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see logging (p. 32).</strong>', + '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(<str>)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see <a href="#logging">logging</a>.</strong>': '<strong>Use <code class="python hljs"><span class="hljs-string">\'logging.exception(<str>)\'</span></code> to log the passed message, followed by the full error message of the caught exception. For details see logging (p. 31).</strong>', '<strong>Functions report OS related errors by raising either OSError or one of its <a href="#exceptions-1">subclasses</a>.</strong>': '<strong>Functions report OS related errors by raising OSError or one of its subclasses (p. 23).</strong>', '<strong>To print the spreadsheet to the console use <a href="#table">Tabulate</a> library.</strong>': '<strong>To print the spreadsheet to the console use Tabulate library (p. 34).</strong>', '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use <a href="#dataframeplotencodedecode">Pandas</a> library.</strong>': '<strong>For XML and binary Excel files (xlsx, xlsm and xlsb) use Pandas library (p. 46).</strong>', '<strong>Bools will be stored and returned as ints and dates as <a href="#encode">ISO formatted strings</a>.</strong>': '<strong>Bools will be stored and returned as ints and dates as ISO formatted strings (p. 9).</strong>', - '<strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be <a href="#pickle">pickable</a>, queues must be sent using executor\'s \'initargs\' and \'initializer\' parameters, and all executors should only be reachable via <code class="python hljs"><span class="hljs-string">\'if __name__ == "__main__": ...\'</span></code>.</strong>': '<strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be pickable, queues must be sent using executor\'s \'initargs\' and \'initializer\' parameters, and all executors should only be reachable via <code class="python hljs"><span class="hljs-string">\'if __name__ == "__main__": ...\'</span></code>.</strong>', - '<strong>Asyncio module also provides its own <a href="#queue">Queue</a>, <a href="#semaphoreeventbarrier">Event</a>, <a href="#lock">Lock</a> and <a href="#semaphoreeventbarrier">Semaphore</a> classes.</strong>': '<strong>Asyncio module also provides its own Queue, Event, Lock and Semaphore classes (p. 30).</strong>', + '<strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be <a href="#pickle">pickable</a>, queues must be sent using executor\'s \'initargs\' and \'initializer\' parameters, and executor should only be reachable via <code class="python hljs"><span class="hljs-string">\'if __name__ == "__main__": ...\'</span></code>.</strong>': '<strong>ProcessPoolExecutor provides true parallelism but: everything sent to/from workers must be pickable, queues must be sent using executor\'s \'initargs\' and \'initializer\' parameters, and executor should only be reachable via <code class="python hljs"><span class="hljs-string">\'if __name__ == "__main__": ...\'</span></code>.</strong>', '<strong>Install a WSGI server like <a href="https://flask.palletsprojects.com/en/latest/deploying/waitress/">Waitress</a> and a HTTP server such as <a href="https://flask.palletsprojects.com/en/latest/deploying/nginx/">Nginx</a> for better security.</strong>': '<strong>Install a WSGI server like Waitress and a HTTP server such as Nginx for better security.</strong>', - '<strong>The "latest and greatest" profiler that can also monitor GPU usage is called <a href="https://github.com/plasma-umass/scalene">Scalene</a>.</strong>': '<strong>The "latest and greatest" profiler that can also monitor GPU usage is called Scalene.</strong>', + '<strong>Data analysis library. For examples see <a href="#plotly">Plotly</a>.</strong>': '<strong>Data analysis library. For examples see Plotly (p. 47).</strong>', } diff --git a/web/script_2.js b/web/script_2.js index 7484625a2..12ff725a2 100644 --- a/web/script_2.js +++ b/web/script_2.js @@ -5,8 +5,8 @@ const TOC = ' <strong><span class="hljs-string">\'3. Syntax\'</span></strong>: [<a href="#arguments">Args</a>, <a href="#inline">Inline</a>, <a href="#imports">Import</a>, <a href="#decorator">Decorator</a>, <a href="#class">Class</a>, <a href="#ducktypes">Duck_Types</a>, <a href="#enum">Enum</a>, <a href="#exceptions">Exception</a>],\n' + ' <strong><span class="hljs-string">\'4. System\'</span></strong>: [<a href="#exit">Exit</a>, <a href="#print">Print</a>, <a href="#input">Input</a>, <a href="#commandlinearguments">Command_Line_Arguments</a>, <a href="#open">Open</a>, <a href="#paths">Path</a>, <a href="#oscommands">OS_Commands</a>],\n' + ' <strong><span class="hljs-string">\'5. Data\'</span></strong>: [<a href="#json">JSON</a>, <a href="#pickle">Pickle</a>, <a href="#csv">CSV</a>, <a href="#sqlite">SQLite</a>, <a href="#bytes">Bytes</a>, <a href="#struct">Struct</a>, <a href="#array">Array</a>, <a href="#memoryview">Memory_View</a>, <a href="#deque">Deque</a>],\n' + - ' <strong><span class="hljs-string">\'6. Advanced\'</span></strong>: [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],\n' + - ' <strong><span class="hljs-string">\'7. Libraries\'</span></strong>: [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>, <a href="#consoleapp">Console_App</a>, <a href="#guiapp">GUI</a>, <a href="#scraping">Scraping</a>, <a href="#web">Web</a>, <a href="#profiling">Profile</a>],\n' + + ' <strong><span class="hljs-string">\'6. Advanced\'</span></strong>: [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>, <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],\n' + + ' <strong><span class="hljs-string">\'7. Libraries\'</span></strong>: [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>, <a href="#consoleapp">Console_App</a>, <a href="#guiapp">GUI</a>, <a href="#scraping">Scraping</a>, <a href="#webapp">Web</a>, <a href="#profiling">Profile</a>],\n' + ' <strong><span class="hljs-string">\'8. Multimedia\'</span></strong>: [<a href="#numpy">NumPy</a>, <a href="#image">Image</a>, <a href="#animation">Animation</a>, <a href="#audio">Audio</a>, <a href="#synthesizer">Synthesizer</a>, <a href="#pygame">Pygame</a>, <a href="#pandas">Pandas</a>, <a href="#plotly">Plotly</a>]\n' + '}\n'; @@ -27,12 +27,12 @@ const TOC_MOBILE = ' <strong><span class="hljs-string">\'5. Data\'</span></strong>: [<a href="#json">JSON</a>, <a href="#pickle">Pickle</a>, <a href="#csv">CSV</a>, <a href="#sqlite">SQLite</a>,\n' + ' <a href="#bytes">Bytes</a>, <a href="#struct">Struct</a>, <a href="#array">Array</a>,\n' + ' <a href="#memoryview">Memory_View</a>, <a href="#deque">Deque</a>],\n' + - ' <strong><span class="hljs-string">\'6. Advanced\'</span></strong>: [<a href="#threading">Threading</a>, <a href="#operator">Operator</a>,\n' + - ' <a href="#matchstatement">Match_Stmt</a>, <a href="#logging">Logging</a>, \n' + - ' <a href="#introspection">Introspection</a>, <a href="#coroutines">Coroutines</a>],\n' + + ' <strong><span class="hljs-string">\'6. Advanced\'</span></strong>: [<a href="#operator">Operator</a>, <a href="#matchstatement">Match_Statement</a>,\n' + + ' <a href="#logging">Logging</a>, <a href="#introspection">Introspection</a>,\n' + + ' <a href="#threading">Threading</a>, <a href="#coroutines">Coroutines</a>],\n' + ' <strong><span class="hljs-string">\'7. Libraries\'</span></strong>: [<a href="#progressbar">Progress_Bar</a>, <a href="#plot">Plot</a>, <a href="#table">Table</a>,\n' + ' <a href="#consoleapp">Console_App</a>, <a href="#guiapp">GUI_App</a>,\n' + - ' <a href="#scraping">Scraping</a>, <a href="#web">Web</a>, <a href="#profiling">Profiling</a>],\n' + + ' <a href="#scraping">Scraping</a>, <a href="#webapp">Web</a>, <a href="#profiling">Profiling</a>],\n' + ' <strong><span class="hljs-string">\'8. Multimedia\'</span></strong>: [<a href="#numpy">NumPy</a>, <a href="#image">Image</a>, <a href="#animation">Animation</a>,\n' + ' <a href="#audio">Audio</a>, <a href="#synthesizer">Synthesizer</a>,\n' + ' <a href="#pygame">Pygame</a>, <a href="#pandas">Pandas</a>, <a href="#plotly">Plotly</a>]\n' +