<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Python on Benny Simmonds</title>
    <link>https://www.bencode.io/categories/python/</link>
    <description>Recent content in Python on Benny Simmonds</description>
    <generator>Hugo -- 0.149.1</generator>
    <language>en-us</language>
    <lastBuildDate>Fri, 29 Dec 2023 17:29:33 +1100</lastBuildDate>
    <atom:link href="https://www.bencode.io/categories/python/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Python Packaging (2024)</title>
      <link>https://www.bencode.io/posts/pythonpack/</link>
      <pubDate>Fri, 29 Dec 2023 17:29:33 +1100</pubDate>
      <guid>https://www.bencode.io/posts/pythonpack/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#sysconfig&#34;&gt;sysconfig&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#project-structure&#34;&gt;Project Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#setup-script&#34;&gt;Setup Script&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#distribution-archives&#34;&gt;Distribution Archives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#distribution&#34;&gt;Distribution&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;sysconfig&#34;&gt;sysconfig&lt;/h2&gt;
&lt;p&gt;The process of bundling Python code into a format that eases distribution and sharing. First up, I find it helps to get a concrete understanding of how the specific python distro I&amp;rsquo;m working with is configured, of paricular interest are the various system paths that will be visited for package dependencies. The built-in &lt;a href=&#34;https://docs.python.org/3/library/sysconfig.html&#34;&gt;sysconfig&lt;/a&gt; module neatly manages and surfaces this information.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;python -m sysconfig
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;On a Windows system:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python PR Checklist</title>
      <link>https://www.bencode.io/posts/pythonchecklist/</link>
      <pubDate>Mon, 30 Oct 2023 20:44:33 +1100</pubDate>
      <guid>https://www.bencode.io/posts/pythonchecklist/</guid>
      <description>&lt;p&gt;A modified version of excellent original checklist by &lt;a href=&#34;https://python-coding-guidelines.readthedocs.io/en/latest/code_review_checklist.html&#34;&gt;Paul Wolf&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;general&#34;&gt;General&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Code is blackened with &lt;code&gt;black&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;code&gt;ruff&lt;/code&gt; has been run with no errors&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;code&gt;mypy&lt;/code&gt; has been run with no errors&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Function complexity problems have been resolved using the &lt;em&gt;default&lt;/em&gt; complexity index of &lt;code&gt;flake8&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Important core code can be loaded in iPython, ipdb easily.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; There is no dead code&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Comprehensions or generator expressions are used in place of for loops where appropriate&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Comprehensions and generator expressions produce state but they do not have side effects within the expression.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Use &lt;code&gt;zip()&lt;/code&gt;, &lt;code&gt;any()&lt;/code&gt;, &lt;code&gt;all()&lt;/code&gt;, &lt;code&gt;filter()&lt;/code&gt;, etc. instead of for loops where appropriate&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Functions that take as parameters and mutate mutable variables don’t return these variables. They return None.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Return immutable copies of mutable types instead of mutating the instances themselves when mutable types are passed as parameters with the intention of returning a mutated version of that variable.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Avoid method cascading on objects with methods that return &lt;code&gt;self&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Function and method parameters never use empty collection or sequence instances like list &lt;code&gt;[]&lt;/code&gt; or dict &lt;code&gt;{}&lt;/code&gt;. Instead they must use &lt;code&gt;None&lt;/code&gt; to indicate missing input&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Variables in a function body are initialised with empty sequences or collections by callables, &lt;code&gt;list()&lt;/code&gt;, &lt;code&gt;dict()&lt;/code&gt;, instead of &lt;code&gt;[]&lt;/code&gt;, &lt;code&gt;{}&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Always use the &lt;code&gt;Final&lt;/code&gt; type hint for class instance parameters that will not change.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Context-dependent variables are not unnecessarily passed between functions or methods&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; View functions either implement the business rules the view is repsonsible for or it passes data downstream to have this done by services and receives non-context dependent data back.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; View functions don’t pass &lt;code&gt;request&lt;/code&gt; to called functions&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Functions including class methods don’t have too many local parameters or instance variables. Especially a class’ &lt;code&gt;__init__()&lt;/code&gt; should not have too many parameters.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Profiling code is minimal&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Logging is the minimum required for production use&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; There are no home-brewed solutions for things that already exist in the PSL (python standard library)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;n00b-habbits&#34;&gt;n00b habbits&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Bare &lt;code&gt;except&lt;/code&gt; clause, Python uses exceptions to flag system level interupts such as sigkills. Don&amp;rsquo;t do this.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Argument default mutatable arguments such as &lt;code&gt;def foo(bar=[])&lt;/code&gt; are defined when the function is defined, not when its run, and will result in a all function calls sharing the same instance of &lt;code&gt;bar&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Checking for equality using &lt;code&gt;==&lt;/code&gt;. Due to inheritance this is not desirable as it pins to a concrete type and not potentially it descendents. In other words the Liskov substitution principle. Instead &lt;code&gt;isinstance(p, tuple)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Explicit bool or length checks, such as &lt;code&gt;if bool(x)&lt;/code&gt; or &lt;code&gt;if len(x) &amp;gt; 0&lt;/code&gt; is redundant, as Python has sane truthy evaluation.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Use of &lt;code&gt;range&lt;/code&gt; over the &lt;code&gt;for in&lt;/code&gt; idiom&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; If you really need the index, always use &lt;code&gt;enumerate&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Not using items() on a dict &lt;code&gt;for k, v in dict.items()&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Using &lt;code&gt;time.time&lt;/code&gt; to measure code performance. Use &lt;code&gt;time.perf_counter&lt;/code&gt; instead.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Using &lt;code&gt;print&lt;/code&gt; statements over &lt;code&gt;logging&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Using &lt;code&gt;import *&lt;/code&gt; will normally liter the namespace with variable. Dont be lazy, be specific. &lt;code&gt;from itertools import count&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;imports-and-modules&#34;&gt;Imports and modules&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Imports are sorted by &lt;code&gt;isort&lt;/code&gt; or according to some standard that is consistent within the team&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Import packages or modules to qualify the use of functions or classes so that unqualified function calls can be assumed to be to functions in the current module&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;documentation&#34;&gt;Documentation&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Modules have docstrings&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Classes have docstrings unless their purpose is immediately obvious&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Methods and functions have docstrings&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Comments and docstrings add non-obvious and helpful information that is not already present in the naming of functions and variables&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;general-complexity&#34;&gt;General Complexity&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Functions as complex as they need to be but no more (as defined by &lt;code&gt;flake8&lt;/code&gt;\ ’s default complexity threshold)&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Classes have only as many methods as required and have a simple hierarchy&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;context-freedom&#34;&gt;Context Freedom&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; All important functionality can be loaded easily in &lt;code&gt;ipython&lt;/code&gt; without having to construct dummy requests, etc.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; All important functionality can be loaded in pdb (or a variant, ipdb, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;types&#34;&gt;Types&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Use immutable types ()&lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;frozenset&lt;/code&gt;, &lt;code&gt;Enum&lt;/code&gt;, etc) over mutable types whenever possible&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;functions&#34;&gt;Functions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Functions are pure wherever possible, i.e. they take input and provide a return value with no side-effects or reliance on hidden state.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;modules&#34;&gt;Modules&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Module level variables do not take context-dependent values like connection clients to remote systems unless the client is used immediately for another module level variable and not used again&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;classes&#34;&gt;Classes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Every class has a single well-defined purpose. That is, the class does not mix up different tasks, like remote state acquisition, web sockets notification, data formatting, etc.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Classes manage state and do not just represent the encapsulation of behaviour&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; All methods access either &lt;code&gt;cls&lt;/code&gt; or &lt;code&gt;self&lt;/code&gt; in the body. If a method does not access &lt;code&gt;cls&lt;/code&gt; or &lt;code&gt;self&lt;/code&gt;, it should be a function at module level.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;code&gt;@classmethod&lt;/code&gt; is used in preference to &lt;code&gt;@staticmethod&lt;/code&gt; but only if the method body accesses &lt;code&gt;cls&lt;/code&gt; otherwise the method should be a module level function.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Constants are declared at module level not in methods or class level&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Constants are always upper case&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Abstract classes are derived from abc: &lt;code&gt;from abc import ABC&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Abstract methods use the &lt;code&gt;@abstractmethod&lt;/code&gt; decorator&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Abstract class properties use both &lt;code&gt;@abstractmethod&lt;/code&gt; and &lt;code&gt;@property&lt;/code&gt; decorators&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Classes do not use multiple inheritance&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Classes do not use mixins (use composition instead) except in rare cases&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Class names do not use the word “Base” to signal they are the single ancestor, like “BaseWhatever”&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Decorators are not used to replace classes as a design pattern&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; &lt;code&gt;__init__()&lt;/code&gt; does not define too many local variables. Use the Parameter Consolidation pattern instead.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; A factory class or function at module level is used for complex class construction (see Design Patterns) to achieve composition&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Classes are not dynamically created from strings except where forward reference requires this&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;design-patterns&#34;&gt;Design Patterns&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Do not use designs that cause a typical Python developer to have to learn new semantics that are unexpected in Python&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Classes primarily use composition in preference to inheritance&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; Beyond a very small number of simple variables, a class’ purpose is to acquire state for another class or it uses another class to acquire state in particular if the state is from a remote service.&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; If you use the Context Parameter pattern, it is critical that the state of the context does not change after calling its &lt;code&gt;__init__()&lt;/code&gt;, i.e. it should be immutable&lt;/li&gt;
&lt;li&gt;&lt;input disabled=&#34;&#34; type=&#34;checkbox&#34;&gt; If a class’ purpose is to represent an external integration, you probably want numerous classes to compose the service: &lt;code&gt;RemoteDataClient&lt;/code&gt;, &lt;code&gt;DomainManager&lt;/code&gt;, &lt;code&gt;ContextManager&lt;/code&gt;, &lt;code&gt;Factory&lt;/code&gt;, &lt;code&gt;NotificationController&lt;/code&gt;, &lt;code&gt;DomainResponse&lt;/code&gt;, &lt;code&gt;DataFormatter&lt;/code&gt; and so on.&lt;/li&gt;
&lt;/ul&gt;</description>
    </item>
    <item>
      <title>Async Python</title>
      <link>https://www.bencode.io/posts/pythonasync/</link>
      <pubDate>Wed, 09 Aug 2023 21:12:33 +1100</pubDate>
      <guid>https://www.bencode.io/posts/pythonasync/</guid>
      <description>&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;Using &lt;code&gt;asyncio&lt;/code&gt; will not make your code multi-threaded. That is, it will not cause multiple Python instructions to be executed at the same time, and it will not in any way allow you to side step the so-called “global interpreter lock” (GIL).&lt;/p&gt;
&lt;p&gt;Some processes are CPU-bound: they consist of a series of instructions which need to be executed one after another until the result has been computed. Most of their time is spent making heavy use of the processor.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python Type Annotations</title>
      <link>https://www.bencode.io/posts/pythontypes/</link>
      <pubDate>Wed, 09 Aug 2023 20:44:33 +1100</pubDate>
      <guid>https://www.bencode.io/posts/pythontypes/</guid>
      <description>&lt;p&gt;Start with the &lt;a href=&#34;https://docs.python.org/3/library/typing.html&#34;&gt;docs&lt;/a&gt; and the &lt;a href=&#34;https://mypy.readthedocs.io/en/stable/cheat_sheet_py3.html&#34;&gt;Type hints cheat sheet&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Topics for consideration:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;syntax shorthands e.g. &lt;code&gt;|&lt;/code&gt; for Union or Optional&lt;/li&gt;
&lt;li&gt;Self&lt;/li&gt;
&lt;li&gt;If you are using the typing library then there is an abstract type class provided for asynchronous context managers AsyncContextManager[T], where T is the type of the object which will be bound by the as clause of the async with statement.&lt;/li&gt;
&lt;li&gt;mypy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you are using typing then there is an abstract class &lt;code&gt;Awaitable&lt;/code&gt; which is generic, so that &lt;code&gt;Awaitable[R]&lt;/code&gt; for some type R means &lt;em&gt;anything which is awaitable, and when used in an await statement will return something of type R&lt;/em&gt;.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python Standard Libraries</title>
      <link>https://www.bencode.io/posts/pythonstdlib/</link>
      <pubDate>Fri, 04 Aug 2023 18:01:33 +1100</pubDate>
      <guid>https://www.bencode.io/posts/pythonstdlib/</guid>
      <description>&lt;p&gt;An important part of becoming &amp;ldquo;good&amp;rdquo; at a language is becoming familiar with its library eco-system.&lt;/p&gt;
&lt;p&gt;The official &lt;a href=&#34;https://docs.python.org/3/library/index.html&#34;&gt;Python Standard Library&lt;/a&gt; reference manual rocks.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Module&lt;/th&gt;
          &lt;th&gt;Category&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;argparse&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions for parsing command line arguments&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;atexit&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;allows you to register functions for your program to call when it exits&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;bisect&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;bisection algorithms for sorting lists (see Chapter 10)&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;calendar&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;a number of date-related functions&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;codecs&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions for encoding and decoding data&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;collections&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;a variety of useful data structures&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;concurrent&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;asynchronous computation&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;copy&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions for copying data&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;csv&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions for reading and writing CSV files&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;datetime&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;classes for handling dates and times&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;fileinput&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;file access&lt;/td&gt;
          &lt;td&gt;iterate over lines from multiple files or input streams&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;fnmatch&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions for matching Unix-style filename patterns&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;glob&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions for matching Unix-style path patterns&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;io&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions for handling I/O streams and StringIO, which allows you to treat strings as files.&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;json&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions for reading and writing data in JSON format&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;logging&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;access to Python’s own built-in logging functionality&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;multiprocessing&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;allows you to run multiple subprocesses, while providing an API that makes them look like threads&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;operator&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions implementing the basic Python operators, instead of writing your own lambda expressions&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;os&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;swiss army knife&lt;/td&gt;
          &lt;td&gt;access to basic OS functions&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;pprint&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;data types&lt;/td&gt;
          &lt;td&gt;data pretty printer&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;random&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions for generating pseudorandom numbers&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;re&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;regular expression functionality&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;sched&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;an event scheduler without using multithreading&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;select&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;access to the select() and poll() functions for creating event loops&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;shutil&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;file access&lt;/td&gt;
          &lt;td&gt;access to high-level file functions&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;signal&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;functions for handling POSIX signals&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;tempfile&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;file access&lt;/td&gt;
          &lt;td&gt;functions for creating temporary files and directories&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;threading&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;access to high-level threading functionality&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;urllib&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;provides functions for handling and parsing URLs&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;uuid&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;&lt;/td&gt;
          &lt;td&gt;allows you to generate Universally Unique Identifiers (UUIDs)&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;</description>
    </item>
    <item>
      <title>Objects in Python</title>
      <link>https://www.bencode.io/posts/pythonobjects/</link>
      <pubDate>Thu, 03 Aug 2023 16:28:33 +1100</pubDate>
      <guid>https://www.bencode.io/posts/pythonobjects/</guid>
      <description>&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#special-methods-dunders&#34;&gt;Special methods (dunders)&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;#foundational&#34;&gt;Foundational&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#iterators&#34;&gt;Iterators&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#compariable-classes&#34;&gt;Compariable classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#serializable-classes&#34;&gt;Serializable classes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#classes-with-computed-attributes&#34;&gt;Classes with computed attributes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#classes-that-are-callable&#34;&gt;Classes that are callable&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#classes-that-act-like-sets&#34;&gt;Classes that act like sets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#classes-that-act-like-dictionaries&#34;&gt;Classes that act like dictionaries&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#classes-that-act-like-numbers&#34;&gt;Classes that act like numbers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#classes-that-can-be-used-in-a-with-block&#34;&gt;Classes that can be used in a with block&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#esoteric-behavior&#34;&gt;Esoteric behavior&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;#design-patterns&#34;&gt;Design Patterns&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As I learn more about Pythons idioms reflect on its unique approach to object based programming. In combination with duck typing its approach to objects feels distrubingly flexible.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Testing in Python</title>
      <link>https://www.bencode.io/posts/pythontesting/</link>
      <pubDate>Thu, 03 Aug 2023 16:28:33 +1100</pubDate>
      <guid>https://www.bencode.io/posts/pythontesting/</guid>
      <description>&lt;p&gt;There are many ways to write unit tests in Python.&lt;/p&gt;
&lt;h2 id=&#34;unittest&#34;&gt;unittest&lt;/h2&gt;
&lt;p&gt;Here the focus is living off the land with built-in &lt;a href=&#34;https://docs.python.org/3/library/unittest.html&#34;&gt;unittest&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;unittest&lt;/code&gt; is both a framework and test runner, meaning it can execute your tests and return the results. In order to write &lt;code&gt;unittest&lt;/code&gt; tests, you must:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Write your tests as methods within classes&lt;/li&gt;
&lt;li&gt;These &lt;code&gt;TestCase&lt;/code&gt; classes must subclass &lt;code&gt;unittest.TestCase&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Names of test functions must begin with &lt;code&gt;test_&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Import the code to be tested&lt;/li&gt;
&lt;li&gt;Use a series of built-in assertion methods&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;basic-example&#34;&gt;Basic example&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-python&#34; data-lang=&#34;python&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kn&#34;&gt;import&lt;/span&gt; &lt;span class=&#34;nn&#34;&gt;unittest&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;class&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;TestStringMethods&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;unittest&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;TestCase&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;test_upper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assertEqual&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;foo&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;upper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;FOO&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;test_isupper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assertTrue&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;FOO&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isupper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assertFalse&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;Foo&amp;#39;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;isupper&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;def&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;test_split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;hello world&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assertEqual&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(),&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;hello&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;world&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;c1&#34;&gt;# check that s.split fails when the separator is not a string&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;k&#34;&gt;with&lt;/span&gt; &lt;span class=&#34;bp&#34;&gt;self&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;assertRaises&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;ne&#34;&gt;TypeError&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;            &lt;span class=&#34;n&#34;&gt;s&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;split&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;__name__&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;unittest&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;assertions&#34;&gt;Assertions&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;TestCase&lt;/code&gt; class provides several assert methods to check for and report failures.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Python quick reference</title>
      <link>https://www.bencode.io/posts/python/</link>
      <pubDate>Sun, 05 Jun 2022 13:57:33 +1100</pubDate>
      <guid>https://www.bencode.io/posts/python/</guid>
      <description>&lt;p&gt;Forked from &lt;a href=&#34;https://gist.github.com/101t/55012e46fc5746d074d7bf5de00acf2f&#34;&gt;101t/python-cheatsheet.md&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;rtfm&#34;&gt;RTFM&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.python.org/3/library/index.html&#34;&gt;The Python Standard Library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://docs.python.org/3/library/functions.html#repr&#34;&gt;Built-in Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://peps.python.org/&#34;&gt;Python Enhancement Propsoals (PEPs)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://peps.python.org/pep-0020/&#34;&gt;The Zen of Python&lt;/a&gt; never far away in the REPL &lt;code&gt;import this&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;contents&#34;&gt;Contents&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Getting started: &lt;a href=&#34;#cpython&#34;&gt;&lt;code&gt;CPython&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#easter-eggs&#34;&gt;&lt;code&gt;Easter eggs&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#import-paths&#34;&gt;&lt;code&gt;Import paths&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#venv&#34;&gt;&lt;code&gt;venv&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Collections: &lt;a href=&#34;#list&#34;&gt;&lt;code&gt;List&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#dictionary&#34;&gt;&lt;code&gt;Dictionary&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#set&#34;&gt;&lt;code&gt;Set&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#tuple&#34;&gt;&lt;code&gt;Tuple&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#range&#34;&gt;&lt;code&gt;Range&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#enumerate&#34;&gt;&lt;code&gt;Enumerate&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#iterator&#34;&gt;&lt;code&gt;Iterator&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#generator&#34;&gt;&lt;code&gt;Generator&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Functions: &lt;a href=&#34;#functions&#34;&gt;&lt;code&gt;Functions&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#modules&#34;&gt;&lt;code&gt;Modules&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Types: &lt;a href=&#34;#type&#34;&gt;&lt;code&gt;Type&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#string&#34;&gt;&lt;code&gt;String&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#regex&#34;&gt;&lt;code&gt;Regular_Exp&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#format&#34;&gt;&lt;code&gt;Format&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#numbers&#34;&gt;&lt;code&gt;Numbers&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#combinatorics&#34;&gt;&lt;code&gt;Combinatorics&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#datetime&#34;&gt;&lt;code&gt;Datetime&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Syntax: &lt;a href=&#34;#arguments&#34;&gt;&lt;code&gt;Args&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#splat&#34;&gt;&lt;code&gt;Splat&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#inline&#34;&gt;&lt;code&gt;Inline&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#closure&#34;&gt;&lt;code&gt;Closure&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#decorator&#34;&gt;&lt;code&gt;Decorator&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#class&#34;&gt;&lt;code&gt;Class&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#duck-types&#34;&gt;&lt;code&gt;Duck_Type&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#enum&#34;&gt;&lt;code&gt;Enum&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#exceptions&#34;&gt;&lt;code&gt;Exception&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;System: &lt;a href=&#34;#exit&#34;&gt;&lt;code&gt;Exit&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#print&#34;&gt;&lt;code&gt;Print&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#input&#34;&gt;&lt;code&gt;Input&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#command-line-arguments&#34;&gt;&lt;code&gt;Command_Line_Arguments&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#open&#34;&gt;&lt;code&gt;Open&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#path&#34;&gt;&lt;code&gt;Path&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#oscommands&#34;&gt;&lt;code&gt;OS_Commands&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Data: &lt;a href=&#34;#json&#34;&gt;&lt;code&gt;JSON&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#pickle&#34;&gt;&lt;code&gt;Pickle&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#csv&#34;&gt;&lt;code&gt;CSV&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#sqlite&#34;&gt;&lt;code&gt;SQLite&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#bytes&#34;&gt;&lt;code&gt;Bytes&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#struct&#34;&gt;&lt;code&gt;Struct&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#array&#34;&gt;&lt;code&gt;Array&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#memory-view&#34;&gt;&lt;code&gt;Memory_View&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#deque&#34;&gt;&lt;code&gt;Deque&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Advanced: &lt;a href=&#34;#threading&#34;&gt;&lt;code&gt;Threading&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#operator&#34;&gt;&lt;code&gt;Operator&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#introspection&#34;&gt;&lt;code&gt;Introspection&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#metaprograming&#34;&gt;&lt;code&gt;Metaprograming&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#eval&#34;&gt;&lt;code&gt;Eval&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#coroutines&#34;&gt;&lt;code&gt;Coroutines&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Libraries: &lt;a href=&#34;#progress-bar&#34;&gt;&lt;code&gt;Progress_Bar&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#plot&#34;&gt;&lt;code&gt;Plot&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#table&#34;&gt;&lt;code&gt;Table&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#curses&#34;&gt;&lt;code&gt;Curses&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#logging&#34;&gt;&lt;code&gt;Logging&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#scraping&#34;&gt;&lt;code&gt;Scraping&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#web&#34;&gt;&lt;code&gt;Web&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#profiling&#34;&gt;&lt;code&gt;Profile&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#numpy&#34;&gt;&lt;code&gt;NumPy&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Packaging and Tools: &lt;a href=&#34;#real-app&#34;&gt;&lt;code&gt;Real app&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#bytecode-disassembler&#34;&gt;&lt;code&gt;Bytecode disassembler&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#poetry&#34;&gt;&lt;code&gt;Poetry&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#gems&#34;&gt;&lt;code&gt;Gems&lt;/code&gt;&lt;/a&gt;, &lt;a href=&#34;#resources&#34;&gt;&lt;code&gt;Resources&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;cpython&#34;&gt;CPython&lt;/h2&gt;
&lt;p&gt;Most distros lag behind the latest releases of python. Its quite a pleasant experience to just build CPython from source, as per &lt;a href=&#34;https://devguide.python.org/getting-started/setup-building/#linux&#34;&gt;the docs&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt update
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt install build-essential gdb lcov pkg-config &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;      libbz2-dev libffi-dev libgdbm-dev libgdbm-compat-dev liblzma-dev &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;      libncurses5-dev libreadline6-dev libsqlite3-dev libssl-dev &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;      lzma lzma-dev tk-dev uuid-dev zlib1g-dev
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./configure
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo make
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo make install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo python3 -m pip install --upgrade pip setuptools wheel
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;easter-eggs&#34;&gt;Easter eggs&lt;/h2&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;import this
import antigravity
from __future__ import braces
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;import-paths&#34;&gt;Import paths&lt;/h2&gt;
&lt;p&gt;When importing modules, Python relies on a list of paths to know where to look for the module. This list is stored in the &lt;code&gt;sys.path&lt;/code&gt; variable.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
