diff --git a/README.md b/README.md index 6c7899fa0..8c30272a4 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,9 @@ List ``` ```python -.sort() # Sorts elements in ascending order. -.reverse() # Reverses the list in-place. - = sorted() # Returns new list with sorted elements. +.sort() # Sorts the elements in ascending order. +.reverse() # Reverses the order of list's elements. + = sorted() # Returns a new list with sorted elements. = reversed() # Returns reversed iterator of elements. ``` @@ -69,9 +69,9 @@ flatter_list = list(itertools.chain.from_iterable()) = .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. -.insert(, ) # Inserts item at index and moves the rest to the right. +.insert(, ) # Inserts item at passed index and moves the rest to the right. .remove() # Removes first occurrence of the item or raises ValueError. -.clear() # Removes all items. Also works on dictionary and set. +.clear() # Removes all list's items. Also works on dictionary and set. ``` @@ -88,7 +88,7 @@ Dictionary ``` ```python -value = .get(key, default=None) # Returns default if key is missing. +value = .get(key, default=None) # Returns default argument if key is missing. value = .setdefault(key, default=None) # Returns and writes default if key is missing. = collections.defaultdict() # Returns a dict with default value `()`. = collections.defaultdict(lambda: 1) # Returns a dict with default value 1. @@ -104,7 +104,7 @@ value = .setdefault(key, default=None) # Returns and writes default if .update() # Adds items. Replaces ones with matching keys. value = .pop(key) # Removes item or raises KeyError if missing. {k for k, v in .items() if v == value} # Returns set of keys that point to the value. -{k: v for k, v in .items() if k in keys} # Filters the dictionary by keys. +{k: v for k, v in .items() if k in keys} # Filters the dictionary by specified keys. ``` ### Counter @@ -168,7 +168,7 @@ Tuple >>> p = Point(1, y=2) >>> print(p) Point(x=1, y=2) ->>> p[0], p.y +>>> p.x, p[1] (1, 2) ``` @@ -215,11 +215,11 @@ import itertools as it ```python = it.count(start=0, step=1) # Returns updated value endlessly. Accepts floats. = it.repeat( [, times]) # Returns element endlessly or 'times' times. - = it.cycle() # Repeats the sequence endlessly. + = it.cycle() # Repeats the passed sequence of elements endlessly. ``` ```python - = it.chain(, [, ...]) # Empties collections in order (figuratively). + = it.chain(, [, ...]) # Empties collections in order (only figuratively). = it.chain.from_iterable() # Empties collections inside a collection in order. ``` @@ -350,7 +350,7 @@ String = .isnumeric() # Checks for [¼½¾…], [零〇一…] and isdigit(). = .isalnum() # Checks for [a-zA-Z…] and isnumeric(). = .isprintable() # Checks for [ !#$%…] and isalnum(). - = .isspace() # Checks for [ \t\n\r\f\v\x1c-\x1f\x85\xa0…]. + = .isspace() # Checks for [ \t\n\r\f\v\x1c-\x1f\x85…]. ``` @@ -370,9 +370,9 @@ import re * **Raw string literals do not interpret escape sequences, thus enabling us to use regex-specific escape sequences that cause SyntaxWarning in normal string literals (since 3.12).** * **Argument 'new' of re.sub() can be a function that accepts Match object and returns a str.** -* **Argument `'flags=re.IGNORECASE'` can be used with all functions.** +* **Argument `'flags=re.IGNORECASE'` can be used with all functions that are listed above.** * **Argument `'flags=re.MULTILINE'` makes `'^'` and `'$'` match the start/end of each line.** -* **Argument `'flags=re.DOTALL'` makes `'.'` also accept the `'\n'`.** +* **Argument `'flags=re.DOTALL'` makes `'.'` also accept the `'\n'` (besides all other chars).** * **`'re.compile()'` returns a Pattern object with methods sub(), findall(), etc.** ### Match Object @@ -380,8 +380,8 @@ import re = .group() # Returns the whole match. Also group(0). = .group(1) # Returns part inside the first brackets. = .groups() # Returns all bracketed parts as strings. - = .start() # Returns start index of the match. - = .end() # Returns exclusive end index of the match. + = .start() # Returns start index of the whole match. + = .end() # Returns its exclusive end index. ``` ### Special Sequences @@ -397,7 +397,7 @@ import re Format ------ ```perl - = f'{}, {}' # Curly brackets can also contain expressions. + = f'{}, {}' # Curly braces can also contain expressions. = '{}, {}'.format(, ) # Same as '{0}, {a}'.format(, a=). = '%s, %s' % (, ) # Redundant and inferior C-style formatting. ``` @@ -418,8 +418,8 @@ Format {:.<10} # '......' {:0} # '' ``` -* **Objects are rendered using `'format(, "")'`.** -* **Options can be generated dynamically: `f'{:{}[…]}'`.** +* **Objects are rendered by calling the `'format(, "")'` function.** +* **Options inside curly braces can be generated dynamically: `f'{:{}[…]}'`.** * **Adding `'='` to the expression prepends it to the output: `f'{1+1=}'` returns `'1+1=2'`.** * **Adding `'!r'` to the expression converts object to string by calling its [repr()](#class) method.** @@ -495,13 +495,13 @@ Numbers ```python = int() # Whole number of any size. Truncates floats. = float() # 64-bit decimal number. Also . - = complex(real=0, imag=0) # Complex number. Also ` ± j`. + = complex(real=0, imag=0) # A complex number. Also ` ± j`. = fractions.Fraction(, ) # E.g. `Fraction(1, 2) / 3 == Fraction(1, 6)`. = decimal.Decimal() # E.g. `Decimal((1, (2, 3), 4)) == -230_000`. ``` -* **`'int()'` and `'float()'` raise ValueError on malformed strings.** +* **`'int()'` and `'float()'` raise ValueError if passed string is malformed.** * **Decimal objects store numbers exactly, unlike most floats where `'1.1 + 2.2 != 3.3'`.** -* **Floats can be compared with: `'math.isclose(, )'`.** +* **Floats can be compared with: `'math.isclose(, , rel_tol=1e-09)'`.** * **Precision of decimal operations is set with: `'decimal.getcontext().prec = '`.** * **Bools can be used anywhere ints can, because bool is a subclass of int: `'True + 1 == 2'`.** @@ -539,7 +539,7 @@ from random import random, randint, uniform # Also: gauss, choice, shuffle, s = randint/uniform(a, b) # Returns an int/float inside [a, b]. = gauss(mean, stdev) # Also triangular(low, high, mode). = choice() # Keeps it intact. Also sample(p, n). -shuffle() # Works on any mutable sequence. +shuffle() # Works on all mutable sequences. ``` ### Hexadecimal Numbers @@ -554,8 +554,8 @@ shuffle() # Works on any mutable sequence. = & # E.g. `0b1100 & 0b1010 == 0b1000`. = | # E.g. `0b1100 | 0b1010 == 0b1110`. = ^ # E.g. `0b1100 ^ 0b1010 == 0b0110`. - = << n_bits # Left shift. Use >> for right. - = ~ # Not. Same as `- - 1`. + = << n_bits # E.g. `0b1111 << 4 == 0b11110000`. + = ~ # E.g. `~0b1 == -0b10 == -(0b1+1)`. ``` @@ -603,8 +603,8 @@ 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`. ``` -* **Times and datetimes that have defined timezone are called aware and ones that don't, naive. 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.** +* **Times and datetimes that have defined timezone are called aware and ones that don't, naive. If time or datetime 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 (usually 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 integer, with Monday being 0.** @@ -615,10 +615,10 @@ import zoneinfo, dateutil.tz ``` * **To extract time use `'.time()'`, `'.time()'` or `'.timetz()'`.** -### Timezone +### Timezones ```python - = timezone.utc # London without daylight saving time (DST). - = timezone() # Timezone with fixed offset from UTC. + = timezone.utc # Coordinated universal time (UK without DST). + = timezone() # Timezone with fixed offset from universal time. = dateutil.tz.tzlocal() # Local timezone with dynamic offset from UTC. = zoneinfo.ZoneInfo('') # 'Continent/City_Name' zone with dynamic offset. =
.astimezone([]) # Converts DT to the passed or local fixed zone. @@ -640,9 +640,9 @@ import zoneinfo, dateutil.tz ### Decode ```python - = .isoformat(sep='T') # Also `timespec='auto/hours/minutes/seconds/…'`. + = .isoformat(sep='T') # Also `timespec='auto/hours/minutes/seconds…'`. = .strftime('') # Custom string representation of the object. - = .toordinal() # Days since Gregorian NYE 1, ignoring time and tz. + = .toordinal() # Days since NYE 1. Ignores DT's time and zone. = .timestamp() # Seconds since the Epoch, from local naive DT. = .timestamp() # Seconds since the Epoch, from aware datetime. ``` @@ -661,7 +661,7 @@ import zoneinfo, dateutil.tz = > # Ignores time jumps (fold attribute). Also ==. = > # Ignores time jumps if they share tzinfo object. = - # Ignores jumps. Convert to UTC for actual delta. - = - # Ignores jumps if they share tzinfo object. + = - # Ignores jumps if they share the tzinfo object. = ± # Returned datetime can fall into missing hour. = * # Also ` = abs()`, ` = ± `. = / # Also `(, ) = divmod(, )`. @@ -788,13 +788,13 @@ from functools import reduce ### And, Or ```python - = and [and ...] # Returns first false or last operand. - = or [or ...] # Returns first true or last operand. + = and [and ...] # Returns first false or last object. + = or [or ...] # Returns first true or last object. ``` ### Walrus Operator ```python ->>> [i for a in '0123' if (i := int(a)) > 0] # Assigns to variable mid-sentence. +>>> [i for ch in '0123' if (i := int(ch)) > 0] # Assigns to variable mid-sentence. [1, 2, 3] ``` @@ -823,9 +823,9 @@ import # Imports a built-in or '.py'. import # Imports a built-in or '/__init__.py'. import . # Imports a built-in or '/.py'. ``` -* **Package is a collection of modules, but it can also define its own objects.** +* **Package is a collection of modules, but it can also define its own functions, classes, etc.** * **On a filesystem this corresponds to a directory of Python files with an optional init script.** -* **Running `'import '` does not automatically provide access to the package's modules unless they are explicitly imported in its init script.** +* **Running `'import '` does not automatically provide access to the package's modules unless they are explicitly imported in the `'/__init__.py'` script.** * **Directory of the file that is passed to python command serves as a root of local imports.** * **For relative imports use `'from .[…][[.…]] import '`.** @@ -885,8 +885,7 @@ def get_counter(): Decorator --------- -* **A decorator takes a function, adds some functionality and returns it.** -* **It can be any [callable](#callable), but is usually implemented as a function that returns a [closure](#closure).** +**A decorator takes a function, adds some functionality and returns it. It can be any [callable](#callable), but is usually implemented as a function that returns a [closure](#closure).** ```python @decorator_name @@ -972,7 +971,7 @@ class MyClass: >>> obj.a, str(obj), repr(obj) (1, '1', 'MyClass(1)') ``` -* **Methods whose names start and end with two underscores are called special methods. They are executed when object is passed to a built-in function or used as an operand, for example, `'print(a)'` calls `'a.__str__()'` and `'a + b'` calls `'a.__add__(b)'`.** +* **Methods whose names start and end with two underscores are called special methods. They are executed when object is passed to a built-in function or used as an operand, for example, `'print(a)'` calls `'a.__str__()'` and `'a + b'` calls `'a.__add__(b)'`.** * **Methods decorated with `'@staticmethod'` receive neither 'self' nor 'cls' argument.** * **Return value of str() special method should be readable and of repr() unambiguous. If only repr() is defined, it will also be used for str().** @@ -1043,7 +1042,7 @@ class : ``` * **Objects can be made [sortable](#sortable) with `'order=True'` and immutable with `'frozen=True'`.** * **For object to be [hashable](#hashable), all attributes must be hashable and 'frozen' must be True.** -* **Function field() is needed because `': list = []'` would make a list that is shared among all instances. Its 'default_factory' argument can be any [callable](#callable).** +* **Function field() is needed because `': list = []'` would make a list that is shared among all instances. Its 'default_factory' argument accepts any [callable](#callable) object.** * **For attributes of arbitrary type use `'typing.Any'`.** ```python @@ -1094,8 +1093,8 @@ Duck Types **A duck type is an implicit type that prescribes a set of special methods. Any object that has those methods defined is considered a member of that duck type.** ### Comparable -* **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`. That means all user-defined objects compare not equal by default, because id() returns object's unique identification number (its memory address).** -* **Only the left side object has eq() method called, unless it returns NotImplemented, in which case the right object is consulted. False is returned if both return NotImplemented.** +* **If eq() method is not overridden, it returns `'id(self) == id(other)'`, which is the same as `'self is other'`. That means all user-defined objects compare not equal by default (because id() returns object's memory address that is guaranteed to be unique).** +* **Only the left side object has eq() method called, unless it returns NotImplemented, in which case the right object is consulted. Result is False if both return NotImplemented.** * **Ne() automatically works on any object that has eq() defined.** ```python @@ -1173,14 +1172,14 @@ class Counter: ``` #### Python has many different iterator objects: -* **Sequence iterators returned by the [iter()](#iterator) function, such as list\_iterator and set\_iterator.** +* **Sequence iterators returned by the [iter()](#iterator) function, such as list\_iterator, etc.** * **Objects returned by the [itertools](#itertools) module, such as count, repeat and cycle.** * **Generators returned by the [generator functions](#generator) and [generator expressions](#comprehensions).** * **File objects returned by the [open()](#open) function, etc.** ### Callable -* **All functions and classes have a call() method, hence are callable.** -* **Use `'callable()'` or `'isinstance(, collections.abc.Callable)'` to check if object is callable. Calling an uncallable object raises TypeError.** +* **All functions and classes have a call() method that is executed when they are called.** +* **Use `'callable()'` or `'isinstance(, collections.abc.Callable)'` to check if object is callable. You can also call the object and check if it raised TypeError.** * **When this cheatsheet uses `''` as an argument, it means `''`.** ```python class Counter: @@ -1199,8 +1198,8 @@ class Counter: ### Context Manager * **With statements only work on objects that have enter() and exit() special methods.** -* **Enter() should lock the resources and optionally return an object.** -* **Exit() should release the resources (for example close a file).** +* **Enter() should lock the resources and optionally return an object (file, lock, etc.).** +* **Exit() should release the resources (for example close a file, release a lock, etc.).** * **Any exception that happens inside the with block is passed to the exit() method.** * **The exit() method can suppress the exception by returning a true value.** ```python @@ -1248,7 +1247,7 @@ True ### Collection * **Only required methods are iter() and len(). Len() should return the number of items.** -* **This cheatsheet actually means `''` when it uses `''`.** +* **This cheatsheet actually means `''` when it uses the `''`.** * **I chose not to use the name 'iterable' because it sounds scarier and more vague than 'collection'. The main drawback of this decision is that the reader could think a certain function doesn't accept iterators when it does, since iterators are the only built-in objects that are iterable but are not collections.** ```python class MyCollection: @@ -1263,8 +1262,7 @@ class MyCollection: ``` ### Sequence -* **Only required methods are getitem() and len().** -* **Getitem() should return an item at the passed index or raise IndexError.** +* **Only required methods are getitem() and len(). Getitem() should return the item at the passed index or raise IndexError (it may also support negative indices and/or slices).** * **Iter() and contains() automatically work on any object that has getitem() defined.** * **Reversed() automatically works on any object that has getitem() and len() defined. It returns reversed iterator of object's items.** ```python @@ -1288,8 +1286,8 @@ class MySequence: * **Passing ABC Iterable to isinstance() or issubclass() only checks whether object/class has special method iter(), while ABC Collection checks for iter(), contains() and len().** ### ABC Sequence -* **It's a richer interface than the basic sequence.** -* **Extending it generates iter(), contains(), reversed(), index() and count().** +* **It's a richer interface than the basic sequence that also requires just getitem() and len().** +* **Extending it generates iter(), contains(), reversed(), index() and count() special methods.** * **Unlike `'abc.Iterable'` and `'abc.Collection'`, it is not a duck type. That is why `'issubclass(MySequence, abc.Sequence)'` would return False even if MySequence had all the methods defined. It however recognizes list, tuple, range, str, bytes, bytearray, array, memoryview and deque, since they are registered as Sequence's virtual subclasses.** ```python from collections import abc @@ -1332,8 +1330,8 @@ from enum import Enum, auto ```python class (Enum): = auto() # Increment of the last numeric value or 1. - = # Values don't have to be hashable. - = , # Values can be collections (this is a tuple). + = # Values don't have to be hashable or unique. + = , # Values can be collections. This is a tuple. ``` * **Methods receive the member they were called on as the 'self' argument.** * **Accessing a member named after a reserved keyword causes SyntaxError.** @@ -1342,20 +1340,20 @@ class (Enum): = . # Returns a member. Raises AttributeError. = [''] # Returns a member. Raises KeyError. = () # Returns a member. Raises ValueError. - = .name # Returns member's name. - = .value # Returns member's value. + = .name # Returns the member's name. + = .value # Returns the member's value. ``` ```python - = list() # Returns enum's members. - = [a.name for a in ] # Returns enum's member names. - = [a.value for a in ] # Returns enum's member values. + = list() # Returns a list of enum's members. + = ._member_names_ # Returns a list of member names. + = [m.value for m in ] # Returns a list of member values. ``` ```python - = type() # Returns member's enum. - = itertools.cycle() # Returns endless iterator of members. - = random.choice(list()) # Returns a random member. + = type() # Returns an enum. Also .__class__. + = itertools.cycle() # Returns an endless iterator of members. + = random.choice(list()) # Randomly selects one of the members. ``` ### Inline @@ -1397,8 +1395,8 @@ finally: ``` * **Code inside the `'else'` block will only be executed if `'try'` block had no exceptions.** * **Code inside the `'finally'` block will always be executed (unless a signal is received).** -* **All variables that are initialized in executed blocks are also visible in all subsequent blocks, as well as outside the try statement (only function block delimits scope).** -* **To catch signals use `'signal.signal(signal_number, )'`.** +* **All variables that are initialized in executed blocks are also visible in all subsequent blocks, as well as outside the try statement (only the function block delimits scope).** +* **To catch signals use `'signal.signal(signal_number, handler_function)'`.** ### Catching Exceptions ```python @@ -1407,10 +1405,10 @@ except as : ... except (, [...]): ... except (, [...]) as : ... ``` -* **Also catches subclasses of the exception.** -* **Use `'traceback.print_exc()'` to print the full error message to stderr.** -* **Use `'print()'` to print just the cause of the exception (its arguments).** -* **Use `'logging.exception()'` to log the passed message, followed by the full error message of the caught exception. For details see [Logging](#logging).** +* **Also catches subclasses, e.g. `'IndexError'` is caught by `'except LookupError:'`.** +* **Use `'traceback.print_exc()'` to print the full error message to standard error stream.** +* **Use `'print()'` to print just the cause of the exception (that is, its arguments).** +* **Use `'logging.exception()'` to log the passed message, followed by the full error message of the caught exception. For details about setting up the logger see [Logging](#logging).** * **Use `'sys.exc_info()'` to get exception type, object, and traceback of caught exception.** ### Raising Exceptions @@ -1433,7 +1431,7 @@ arguments = .args exc_type = .__class__ filename = .__traceback__.tb_frame.f_code.co_filename func_name = .__traceback__.tb_frame.f_code.co_name -line = linecache.getline(filename, .__traceback__.tb_lineno) +line_str = linecache.getline(filename, .__traceback__.tb_lineno) trace_str = ''.join(traceback.format_tb(.__traceback__)) error_msg = ''.join(traceback.format_exception(type(), , .__traceback__)) ``` @@ -1441,25 +1439,25 @@ error_msg = ''.join(traceback.format_exception(type(), , .__tr ### Built-in Exceptions ```text BaseException - +-- SystemExit # Raised by the sys.exit() function. - +-- KeyboardInterrupt # Raised when the user hits the interrupt key (ctrl-c). + +-- SystemExit # Raised by the sys.exit() function (see #Exit for details). + +-- KeyboardInterrupt # Raised when the user hits the interrupt key (control-c). +-- Exception # User-defined exceptions should be derived from this class. +-- ArithmeticError # Base class for arithmetic errors such as ZeroDivisionError. +-- AssertionError # Raised by `assert ` if expression returns false value. +-- AttributeError # Raised when object doesn't have requested attribute/method. +-- EOFError # Raised by input() when it hits an end-of-file condition. +-- LookupError # Base class for errors when a collection can't find an item. - | +-- IndexError # Raised when a sequence index is out of range. + | +-- IndexError # Raised when index of a sequence (list/str) is out of range. | +-- KeyError # Raised when a dictionary key or set element is missing. +-- MemoryError # Out of memory. May be too late to start deleting variables. +-- NameError # Raised when nonexistent name (variable/func/class) is used. | +-- UnboundLocalError # Raised when local name is used before it's being defined. - +-- OSError # Errors such as FileExistsError/TimeoutError (see #Open). - | +-- ConnectionError # Errors such as BrokenPipeError/ConnectionAbortedError. + +-- OSError # Errors such as FileExistsError, TimeoutError (see #Open). + | +-- ConnectionError # Errors such as BrokenPipeError and ConnectionAbortedError. +-- RuntimeError # Raised by errors that don't fall into other categories. | +-- NotImplementedEr… # Can be raised by abstract methods or by unfinished code. | +-- RecursionError # Raised if max recursion depth is exceeded (3k by default). - +-- StopIteration # Raised when an empty iterator is passed to next(). + +-- StopIteration # Raised when exhausted (empty) iterator is passed to next(). +-- TypeError # When an argument of the wrong type is passed to function. +-- ValueError # When argument has the right type but inappropriate value. ``` @@ -1506,7 +1504,7 @@ Print ```python print(, ..., sep=' ', end='\n', file=sys.stdout, flush=False) ``` -* **Use `'file=sys.stderr'` for messages about errors.** +* **Use `'file=sys.stderr'` for messages about errors so they can be processed separately.** * **Stdout and stderr streams hold output in a buffer until they receive a string containing '\n' or '\r', buffer reaches 4096 characters, `'flush=True'` is used, or program exits.** ### Pretty Print @@ -1539,7 +1537,7 @@ arguments = sys.argv[1:] ### Argument Parser ```python from argparse import ArgumentParser, FileType -p = ArgumentParser(description=) # Returns a parser. +p = ArgumentParser(description=) # Returns a parser object. p.add_argument('-', '--', action='store_true') # Flag (defaults to False). p.add_argument('-', '--', type=) # Option (defaults to None). p.add_argument('', type=, nargs=1) # Mandatory first argument. @@ -1550,8 +1548,8 @@ args = p.parse_args() # Exits on par ``` * **Use `'help='` to set argument description that will be displayed in help message.** -* **Use `'default='` to set option's or optional argument's default value.** -* **Use `'type=FileType()'` for files. Accepts 'encoding', but 'newline' is None.** +* **Use `'default='` to override None as option's or optional argument's default value.** +* **Use `'type=FileType()'` for files. It accepts 'encoding', but 'newline' is None.** Open @@ -1561,7 +1559,7 @@ Open ```python = open(, mode='r', encoding=None, newline=None) ``` -* **`'encoding=None'` means that the default encoding is used, which is platform dependent. Best practice is to use `'encoding="utf-8"'` whenever possible.** +* **`'encoding=None'` means that the default encoding is used, which is platform dependent. Best practice is to use `'encoding="utf-8"'` until it becomes the default (Python 3.15).** * **`'newline=None'` means all different end of line combinations are converted to '\n' on read, while on write all '\n' characters are converted to system's default line separator.** * **`'newline=""'` means no conversions take place, but input is still broken into chunks by readline() and readlines() on every '\n', '\r' and '\r\n'.** @@ -1583,21 +1581,21 @@ Open ### File Object ```python -.seek(0) # Moves to the start of the file. +.seek(0) # Moves current position to the start of file. .seek(offset) # Moves 'offset' chars/bytes from the start. -.seek(0, 2) # Moves to the end of the file. +.seek(0, 2) # Moves current position to the end of file. .seek(±offset, origin) # Origin: 0 start, 1 current position, 2 end. ``` ```python - = .read(size=-1) # Reads 'size' chars/bytes or until EOF. + = .read(size=-1) # Reads 'size' chars/bytes or until the EOF. = .readline() # Returns a line or empty string/bytes on EOF. - = .readlines() # Returns a list of remaining lines. - = next() # Returns a line using buffer. Do not mix. + = .readlines() # Returns remaining lines. Also list(). + = next() # Returns a line using a read-ahead buffer. ``` ```python -.write() # Writes a string or bytes object. +.write() # Writes a str or bytes object to write buffer. .writelines() # Writes a coll. of strings or bytes objects. .flush() # Flushes write buffer. Runs every 4096/8192 B. .close() # Closes the file after flushing write buffer. @@ -1628,7 +1626,7 @@ from pathlib import Path ```python = os.getcwd() # Returns working dir. Starts as shell's $PWD. - = os.path.join(, ...) # Joins two or more pathname components. + = os.path.join(, ...) # Uses os.sep to join strings or Path objects. = os.path.realpath() # Resolves symlinks and calls path.abspath(). ``` @@ -1639,19 +1637,19 @@ from pathlib import Path ``` ```python - = os.listdir(path='.') # Returns filenames located at the path. + = os.listdir(path='.') # Returns all filenames located at the path. = glob.glob('') # Returns paths matching the wildcard pattern. ``` ```python - = os.path.exists() # Same as .exists(). - = os.path.isfile() # Same as .is_file(). - = os.path.isdir() # Same as .is_dir(). + = os.path.exists() # Checks if path exists. Also .exists(). + = os.path.isfile() # Also .is_file() and .is_file(). + = os.path.isdir() # Also .is_dir() and .is_dir(). ``` ```python - = os.stat() # Same as .stat(). - = .st_mtime/st_size/… # Modification time, size in bytes, etc. + = os.stat() # File's status. Also .stat(). + = .st_mtime/st_size/… # Returns modification time, size in bytes, etc. ``` ### DirEntry @@ -1659,8 +1657,8 @@ from pathlib import Path ```python = os.scandir(path='.') # Returns DirEntry objects located at the path. - = .path # Returns the whole path as a string. - = .name # Returns final component as a string. + = .path # Is absolute if 'path' argument was absolute. + = .name # Returns path's final component as a string. = open() # Opens the file and returns its file object. ``` @@ -1672,7 +1670,7 @@ from pathlib import Path ``` ```python - = Path() # Returns relative CWD. Also Path('.'). + = Path() # Returns current working dir. Also Path('.'). = Path.cwd() # Returns absolute CWD. Also Path().resolve(). = Path.home() # Returns user's home directory (absolute). = Path(__file__).resolve() # Returns module's path if CWD wasn't changed. @@ -1680,10 +1678,10 @@ from pathlib import Path ```python = .parent # Returns Path without the final component. - = .name # Returns final component as a string. - = .suffix # Returns name's last extension, e.g. '.py'. + = .name # Returns path's final component as a string. + = .suffix # Returns name's last extension, e.g. '.gz'. = .stem # Returns name without the last extension. - = .parts # Returns all components as strings. + = .parts # Returns all path's components as strings. ``` ```python @@ -1693,7 +1691,7 @@ from pathlib import Path ```python = str() # Returns path as string. Also .as_uri(). - = open() # Also .read/write_text/bytes(). + = open() # Also .read_text/write_bytes(). ``` @@ -1716,15 +1714,15 @@ shutil.copytree(from, to) # Copies the directory. 'to' must not exist. ``` ```python -os.rename(from, to) # Renames/moves the file or directory. +os.rename(from, to) # Renames or moves the file or directory 'from'. os.replace(from, to) # Same, but overwrites file 'to' even on Windows. shutil.move(from, to) # Rename() that moves into 'to' if it's a dir. ``` ```python -os.remove() # Deletes the file. -os.rmdir() # Deletes the empty directory. -shutil.rmtree() # Deletes the directory. +os.remove() # Deletes the file. Or `pip3 install send2trash`. +os.rmdir() # Deletes the empty directory or raises OSError. +shutil.rmtree() # Deletes the directory and all of its contents. ``` * **Paths can be either strings, Path objects, or DirEntry objects.** * **Functions report OS related errors by raising OSError or one of its [subclasses](#exceptions-1).** @@ -1811,24 +1809,25 @@ CSV import csv ``` -### Read ```python - = csv.reader() # Also: `dialect='excel', delimiter=','`. - = next() # Returns next row as a list of strings. - = list() # Returns a list of remaining rows. + = open(, newline='') # Opens the CSV (text) file for reading. + = csv.reader() # Also: `dialect='excel', delimiter=','`. + = next() # Returns next row as a list of strings. + = list() # Returns a list of all remaining rows. ``` -* **File must be opened with a `'newline=""'` argument, or every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'!** -* **To print the spreadsheet to the console use [Tabulate](#table) library.** -* **For XML and binary Excel files (xlsx, xlsm and xlsb) use [Pandas](#dataframe-plot-encode-decode) library.** -* **Reader accepts any iterator or collection of strings, not just files.** +* **Without the `'newline=""'` argument, every '\r\n' sequence that is embedded inside a quoted field will get converted to '\n'! For details about newline argument see [Open](#open).** +* **To print the spreadsheet to the console use [Tabulate](#table) or PrettyTable library.** +* **For XML and binary Excel files (xlsx, xlsm and xlsb) use [Pandas](#fileformats) library.** +* **Reader accepts any iterator (or collection) of strings, not just files.** ### Write ```python - = csv.writer() # Also: `dialect='excel', delimiter=','`. -.writerow() # Encodes objects using `str()`. -.writerows() # Appends multiple rows. + = open(, 'w', newline='') # Opens the CSV (text) file for writing. + = csv.writer() # Also: `dialect='excel', delimiter=','`. +.writerow() # Encodes each object using `str()`. +.writerows() # Appends multiple rows to the file. ``` -* **File must be opened with a `'newline=""'` argument, or '\r' will be added in front of every '\n' on platforms that use '\r\n' line endings!** +* **If file is opened without the `'newline=""'` argument, '\r' will be added in front of every '\n' on platforms that use '\r\n' line endings (i.e., newlines may get doubled on Windows)!** * **Open existing file with `'mode="a"'` to append to it or `'mode="w"'` to overwrite it.** ### Parameters @@ -1837,7 +1836,7 @@ import csv * **`'lineterminator'` - How writer terminates rows. Reader looks for '\n', '\r' and '\r\n'.** * **`'quotechar'` - Character for quoting fields containing delimiters, quotechars, '\n' or '\r'.** * **`'escapechar'` - Character for escaping quotechars (not needed if doublequote is True).** -* **`'doublequote'` - Whether quotechars inside fields are/get doubled or escaped.** +* **`'doublequote'` - Whether quotechars inside fields are/get doubled instead of escaped.** * **`'quoting'` - 0: As necessary, 1: All, 2: All but numbers which are read as floats, 3: None.** * **`'skipinitialspace'` - Is space character at the start of the field stripped by the reader.** @@ -1885,7 +1884,7 @@ import sqlite3 ### Read ```python = .execute('') # Can raise a subclass of sqlite3.Error. - = .fetchone() # Returns next row. Also next(). + = .fetchone() # Returns the next row. Also next(). = .fetchall() # Returns remaining rows. Also list(). ``` @@ -1905,19 +1904,19 @@ with : # Exits the block with commit() o ### Placeholders ```python .execute('', ) # Replaces every question mark with an item. -.execute('', ) # Replaces every : with a value. -.executemany('', ) # Runs execute() multiple times. +.execute('', ) # Replaces every : with a matching value. +.executemany('', ) # Runs execute() once for each collection. ``` * **Passed values can be of type str, int, float, bytes, None, or bool (stored as 1 or 0).** +* **SQLite does not restrict columns to any type unless table is declared as strict.** ### Example **Values are not actually saved in this example because `'conn.commit()'` is omitted!** ```python >>> conn = sqlite3.connect('test.db') ->>> conn.execute('CREATE TABLE person (person_id INTEGER PRIMARY KEY, name, height)') ->>> conn.execute('INSERT INTO person VALUES (NULL, ?, ?)', ('Jean-Luc', 187)).lastrowid -1 ->>> conn.execute('SELECT * FROM person').fetchall() +>>> conn.execute('CREATE TABLE person (name TEXT, height INTEGER) STRICT') +>>> conn.execute('INSERT INTO person VALUES (?, ?)', ('Jean-Luc', 187)) +>>> conn.execute('SELECT rowid, * FROM person').fetchall() [(1, 'Jean-Luc', 187)] ``` @@ -2029,21 +2028,21 @@ b'\x00\x01\x00\x02\x00\x00\x00\x03' Array ----- -**List that can only hold numbers of a predefined type. Available types and their minimum sizes in bytes are listed above. Type sizes and byte order are always determined by the system, however bytes of each element can be reversed with byteswap() method.** +**List that can only hold numbers of a predefined type. Available types and their minimum sizes in bytes are listed above. Type sizes and byte order are always determined by the system, however bytes of each element can be reversed (by calling the byteswap() method).** ```python from array import array ``` ```python - = array('', ) # Creates array from collection of numbers. - = array('', ) # Writes passed bytes to array's memory. + = array('', ) # Creates an array from collection of numbers. + = array('', ) # Writes passed bytes to the array's memory. = array('', ) # Treats passed array as a sequence of numbers. -.fromfile(, n_items) # Appends file's contents to array's memory. +.fromfile(, n_items) # Appends file contents to the array's memory. ``` ```python - = bytes() # Returns a copy of array's memory. + = bytes() # Returns a copy of array's memory as bytes. .write() # Writes array's memory to the binary file. ``` @@ -2054,7 +2053,7 @@ Memory View ```python = memoryview() # Immutable if bytes is passed, else mutable. - = [index] # Returns int/float. Bytes if format is 'c'. + = [index] # Returns ints/floats. Bytes if format is 'c'. = [] # Returns memoryview with rearranged elements. = .cast('') # Only works between B/b/c and other types. .release() # Releases memory buffer of the base object. @@ -2069,7 +2068,7 @@ Memory View ```python = list() # Returns a list of ints, floats or bytes. - = str(, 'utf-8') # Treats memoryview as a bytes object. + = str(, 'utf-8') # Treats passed memoryview as a bytes object. = .hex() # Returns hex pairs. Accepts `sep=`. ``` @@ -2085,15 +2084,15 @@ from collections import deque ```python = deque() # Use `maxlen=` to set size limit. .appendleft() # Opposite element is dropped if full. -.extendleft() # Passed collection gets reversed. -.rotate(n=1) # Last element becomes first. +.extendleft() # Prepends reversed coll. to the deque. +.rotate(n=1) # Last element becomes the first one. = .popleft() # Raises IndexError if deque is empty. ``` Operator -------- -**Module of functions that provide the functionality of operators. Functions are grouped by operator precedence, from least to most binding. Functions and operators in lines 1, 3 and 5 are also ordered by precedence within a group.** +**Module of functions that provide the functionality of operators. Functions are grouped by operator precedence, from least to most binding. Functions and operators in first, third and fifth line are also ordered by precedence within a group.** ```python import operator as op ``` @@ -2101,11 +2100,11 @@ import operator as op ```python = op.not_() # or, and, not (or/and missing) = op.eq/ne/lt/ge/is_/is_not/contains(, ) # ==, !=, <, >=, is, is not, in - = op.or_/xor/and_(, ) # |, ^, & - = op.lshift/rshift(, ) # <<, >> - = op.add/sub/mul/truediv/floordiv/mod(, ) # +, -, *, /, //, % - = op.neg/invert() # -, ~ - = op.pow(, ) # ** + = op.or_/xor/and_(, ) # |, ^, & (sorted by precedence) + = op.lshift/rshift(, ) # <<, >> (i.e. << n_bits) + = op.add/sub/mul/truediv/floordiv/mod(, ) # +, -, *, /, //, % (two groups) + = op.neg/invert() # -, ~ (negate and bitwise not) + = op.pow(, ) # ** (pow() accepts 3 arguments) = op.itemgetter/attrgetter/methodcaller( [, ...]) # [index/key], .name, .name([…]) ``` @@ -2137,17 +2136,16 @@ match : = _ # Matches any object. Useful in last case. = # Matches any object and binds it to name. = as # Binds match to name. Also (). - = | [| ...] # Matches any of the patterns. - = [, ...] # Matches sequence with matching items. - = {: , ...} # Matches dictionary with matching items. - = (=, ...) # Matches object with matching attributes. + = | [| ...] # Matches if any of listed patterns match. + = [, ...] # Matches a sequence. All items must match. + = {: , ...} # Matches a dict that has matching items. + = (=, ...) # Matches an object if attributes match. ``` -* **Sequence pattern can also be written as a tuple, i.e. `'(, [...])'`.** +* **Sequence pattern can also be written as a tuple, either with or without the brackets.** * **Use `'*'` and `'**'` in sequence/mapping patterns to bind remaining items.** * **Sequence pattern must match all items of the collection, while mapping pattern does not.** -* **Patterns can be surrounded with brackets to override precedence (`'|'` > `'as'` > `','`).** -* **Built-in types allow a single positional pattern that is matched against the entire object.** -* **All names that are bound in the matching case, as well as variables initialized in its block, are visible after the match statement.** +* **Patterns can be surrounded with brackets to override their precedence: `'|'` > `'as'` > `','`. For example, `'[1, 2]'` is matched by the `'case 1|2, 2|3 as x if x == 2:'` block.** +* **All names that are bound in the matching case, as well as variables initialized in its body, are visible after the match statement (only function block delimits scope).** ### Example ```python @@ -2169,9 +2167,9 @@ import logging as log ```python log.basicConfig(filename=, level='DEBUG') # Configures the root logger (see Setup). -log.debug/info/warning/error/critical() # Sends message to the root logger. - = log.getLogger(__name__) # Returns logger named after the module. -.() # Sends message to the logger. +log.debug/info/warning/error/critical() # Sends passed message to the root logger. + = log.getLogger(__name__) # Returns a logger named after the module. +.() # Sends the message. Same levels as above. .exception() # Error() that appends caught exception. ``` @@ -2186,11 +2184,11 @@ log.basicConfig( ``` ```python - = log.Formatter('') # Creates a Formatter. - = log.FileHandler(, mode='a') # Creates a Handler. Also `encoding=None`. -.setFormatter() # Adds Formatter to the Handler. -.setLevel() # Processes all messages by default. -.addHandler() # Adds Handler to the Logger. + = log.Formatter('') # Formats messages according to format str. + = log.FileHandler(, mode='a') # Appends to file. Also `encoding=None`. +.setFormatter() # Only outputs bare messages by default. +.setLevel() # Prints or saves every message by default. +.addHandler() # Logger can have more than one handler. .setLevel() # What is sent to its/ancestors' handlers. .propagate = # Cuts off ancestors' handlers if False. ``` @@ -2220,7 +2218,7 @@ Introspection ------------- ```python = dir() # Local names of variables, functions, classes and modules. - = vars() # Dict of local names and their objects. Also locals(). + = vars() # Dict of local names and their objects. Same as locals(). = globals() # Dict of global names and their objects, e.g. __builtin__. ``` @@ -2228,13 +2226,13 @@ Introspection = 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. +value = getattr(, '') # Returns the object's attribute or raises AttributeError. setattr(, '', value) # Sets attribute. Only works on objects with __dict__ attr. delattr(, '') # Deletes attribute from __dict__. Also `del .`. ``` ```python - = inspect.signature() # Returns a Signature object of the passed function. + = inspect.signature() # Returns Signature object of the passed function or class. = .parameters # Returns dict of Parameters. Also .return_annotation. = .kind # Returns ParameterKind member (Parameter.KEYWORD_ONLY, …). = .annotation # Returns Parameter.empty if missing. Also .default. @@ -2260,31 +2258,31 @@ from concurrent.futures import ThreadPoolExecutor, as_completed ### 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. + = Lock/RLock() # RLock can only be released by acquirer thread. +.acquire() # Blocks (waits) until lock becomes available. +.release() # Releases the lock so it can be acquired again. ``` #### Or: ```python -with : # Enters the block by calling acquire() and - ... # exits it with release(), even on error. +with : # Enters the block by calling method acquire(). + ... # Exits it by calling 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. + = Barrier() # Wait() blocks until it's called int 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. + = queue.Queue(maxsize=0) # A first-in-first-out queue. It's thread safe. +.put() # Call blocks until queue stops being full. +.put_nowait() # Raises queue.Full exception if queue is full. + = .get() # Call blocks until queue stops being empty. + = .get_nowait() # Raises queue.Empty exception if it's empty. ``` ### Thread Pool Executor @@ -2292,24 +2290,24 @@ with : # Enters the block by calling acq = ThreadPoolExecutor(max_workers=None) # Also `with ThreadPoolExecutor() as : …`. = .map(, , ...) # Multithreaded and non-lazy map(). Keeps order. = .submit(, , ...) # Creates a thread and returns its Future obj. -.shutdown() # Waits for all submitted threads to finish. +.shutdown() # Waits for all threads to finish executing. ``` ```python = .done() # Checks if the thread has finished executing. - = .result(timeout=None) # Waits for thread to finish and returns result. + = .result(timeout=None) # Raises TimeoutError after 'timeout' seconds. = .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.** +* **Exceptions that happen inside threads are raised when map iterator's next() or Future's result() are called. Future's exception() method returns an 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.** -* **Coroutine definition starts with `'async'` and its call with `'await'`.** +* **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 consume as much memory.** +* **Coroutine definition starts with `'async'` keyword and its call with `'await'`.** * **Use `'asyncio.run()'` to start the first/main coroutine.** ```python @@ -2318,8 +2316,8 @@ import asyncio as aio ```python = () # Creates a coroutine by calling async def function. - = await # Starts the coroutine and returns its result. - = aio.create_task() # Schedules the coroutine for execution. + = await # Starts the coroutine. Returns its result or None. + = aio.create_task() # Schedules it for execution. Always keep the task. = await # Returns coroutine's result. Also .cancel(). ``` @@ -2333,12 +2331,12 @@ import asyncio as aio ```python import asyncio, collections, curses, curses.textpad, enum, random -P = collections.namedtuple('P', 'x y') # Position -D = enum.Enum('D', 'n e s w') # Direction -W, H = 15, 7 # Width, Height +P = collections.namedtuple('P', 'x y') # Position (x and y coordinates). +D = enum.Enum('D', 'n e s w') # Direction (north, east, etc.). +W, H = 15, 7 # Width and height of the field. def main(screen): - curses.curs_set(0) # Makes cursor invisible. + curses.curs_set(0) # Makes the cursor invisible. screen.nodelay(True) # Makes getch() non-blocking. asyncio.run(main_coroutine(screen)) # Starts running asyncio code. @@ -2346,7 +2344,7 @@ async def main_coroutine(screen): moves = asyncio.Queue() state = {'*': P(0, 0)} | {id_: P(W//2, H//2) for id_ in range(10)} ai = [random_controller(id_, moves) for id_ in range(10)] - mvc = [human_controller(screen, moves), model(moves, state), view(state, screen)] + mvc = [controller(screen, moves), model(moves, state), view(state, screen)] tasks = [asyncio.create_task(coro) for coro in ai + mvc] await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED) @@ -2356,7 +2354,7 @@ async def random_controller(id_, moves): moves.put_nowait((id_, d)) await asyncio.sleep(random.triangular(0.01, 0.65)) -async def human_controller(screen, moves): +async def controller(screen, moves): while True: key_mappings = {258: D.s, 259: D.n, 260: D.w, 261: D.e} if d := key_mappings.get(screen.getch()): @@ -3455,17 +3453,17 @@ def main(): display_data(df) def get_covid_cases(): - url = 'https://covid.ourworldindata.org/data/owid-covid-data.csv' + url = 'https://catalog.ourworldindata.org/garden/covid/latest/compact/compact.csv' df = pd.read_csv(url, parse_dates=['date']) - df = df[df.location == 'World'] + df = df[df.country == 'World'] s = df.set_index('date').total_cases return s.rename('Total Cases') def get_tickers(): with selenium.webdriver.Chrome() as driver: + driver.implicitly_wait(10) symbols = {'Bitcoin': 'BTC-USD', 'Gold': 'GC=F', 'Dow Jones': '%5EDJI'} - for name, symbol in symbols.items(): - yield get_ticker(driver, name, symbol) + return [get_ticker(driver, name, symbol) for name, symbol in symbols.items()] def get_ticker(driver, name, symbol): url = f'https://finance.yahoo.com/quote/{symbol}/history/' diff --git a/index.html b/index.html index ac30454b2..8d9c6d30b 100644 --- a/index.html +++ b/index.html @@ -56,12 +56,11 @@
- +
-
-

Comprehensive Python Cheatsheet

Comprehensive Python Cheatsheet