﻿<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Python Koans]]></title><description><![CDATA[A Python newsletter for developers who want to learn Python through short puzzles and deep explanations]]></description><link>https://pythonkoans.substack.com</link><image><url>https://substackcdn.com/image/fetch/$s_!wNQ0!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png</url><title>Python Koans</title><link>https://pythonkoans.substack.com</link></image><generator>Substack</generator><lastBuildDate>Tue, 09 Jun 2026 14:23:02 GMT</lastBuildDate><atom:link href="https://pythonkoans.substack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Python Koans]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[pythonkoans@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[pythonkoans@substack.com]]></itunes:email><itunes:name><![CDATA[Vivis Dev]]></itunes:name></itunes:owner><itunes:author><![CDATA[Vivis Dev]]></itunes:author><googleplay:owner><![CDATA[pythonkoans@substack.com]]></googleplay:owner><googleplay:email><![CDATA[pythonkoans@substack.com]]></googleplay:email><googleplay:author><![CDATA[Vivis Dev]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Koan 20: The Unreliable Messenger]]></title><description><![CDATA[Exploring traps in try/finally blocks, and the reasoning behind PEP601 and PEP765]]></description><link>https://pythonkoans.substack.com/p/koan-20-the-unreliable-messenger</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-20-the-unreliable-messenger</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Mon, 11 May 2026 00:00:15 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!0Zvc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0Zvc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0Zvc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png 424w, https://substackcdn.com/image/fetch/$s_!0Zvc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png 848w, https://substackcdn.com/image/fetch/$s_!0Zvc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png 1272w, https://substackcdn.com/image/fetch/$s_!0Zvc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0Zvc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png" width="1456" height="1045" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1045,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:305141,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/193932656?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0Zvc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png 424w, https://substackcdn.com/image/fetch/$s_!0Zvc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png 848w, https://substackcdn.com/image/fetch/$s_!0Zvc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png 1272w, https://substackcdn.com/image/fetch/$s_!0Zvc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff50e228d-8d11-42a4-b112-f189354c29cb_1536x1102.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>How to Clean Up</h3><p>When you work with external resources such as a database or temporary files, you often need to run some cleanup actions after you've done the work.</p><p>Python provides two options - the context manager and the try/finally block. Both are valid options, but the context manager is often lauded as being more Pythonic.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>Despite this, try/finally block is still widely used. As we will discover, try/finally is simple to use and well-suited in some cases,  but it does come with pitfalls, as the messenger tragically discovered.</p><p>Let us try and contact the messenger.</p><h3><strong>Part 1: The Assured Action</strong></h3><p>A variant of the try/finally pattern exists in most languages<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> and functions pretty much in the way you might imagine. Consider this trivial example:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def walk_path():
    try:
        print("Taking a step")
    finally:
        print("Leaving a footprint")

'Taking a step'
'Leaving a footprint'</code></pre></div><p>The interpreter enters the first block and executes the statement. The interpreter then proceeds to the finally block. The final block always executes. It does not matter if the first block succeeds or fails.</p><p>If a failure is raised during execution as shown below, the error disrupts the normal flow and the interpreter stops executing the try block immediately. The interpreter then jumps directly to the finally block.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def walk_path():
    try:
        raise Exception("A fallen tree")
    finally:
        print("Leaving a footprint")</code></pre></div><p>If you choose to handle the failure using an except block as shown below, the error is caught and handled by the except block before proceeding to the finally block. An error could also occur inside the except or else block. The interpreter would still execute the finally block before raising the new error.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def walk_path():
    try:
        raise Exception("A fallen tree")
    except Exception:
        print("Climbing over the trunk")
    else:
        print("Kicking the trunk away using superhuman strength")
    finally:
        print("Leaving a footprint")</code></pre></div><h3><strong>Part 2: The Trapped Messenger</strong></h3><p>This brings us to the behavior of returning values. A function can return a value from within the try block. When the interpreter encounters this return statement, It prepares to send this value back to the caller. But first, it must honor the finally block. So it pauses the return process and executes the finally block first before returning the prepared value from the try block.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def walk_path():
    try:
        return "Reaching the destination"
    finally:
        print("Leaving a footprint")</code></pre></div><p>The finally block can also contain its own return statement, as shown below. When this happens, the return in the finally block wins and the return value from the try is effectively ignored.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def walk_path():
    try:
        return "Reaching the destination"
    finally:
        return "Returning home"</code></pre></div><p>This behavior applies to exceptions as well. We can place a loop around our structure to observe break and continue statements.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def scout_path():
    for step in range(3):
        try:
            raise Exception("A hidden trap")
        finally:
            break
    return "The scout survives"
'The scout survives'</code></pre></div><p>A break statement inside a finally block will swallow any unhandled exception from the try block. A continue statement will do the exact same thing. The exception disappears completely.</p><h3><strong>Part 3: The Trapped Voice</strong></h3><p>Lets examine a more complex example with nested try/finally statements. Do return statements break out of parent try/finally blocks?</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">def send_message():
    try:
        print("Everything is fine")
        return 0
    finally:
        try:
            try:
                print("Everything is still fine")
            finally:
                for x in range(2):
                    print(f"Scouting area {x}")
                return 1
        finally:
            for x in range(2):
                print(f"Covering tracks in area {x}")
                return 2
print(f"Return value: {send_message()}")

Everything is fine
Everything is still fine
Scouting area 0
Scouting area 1
Covering tracks in area 0
Covering tracks in area 1
Return value: 2</code></pre></div><p>No, try/finally statements can be nested, and return statements from child blocks do not prevent parent finally blocks from running. However, the value from the last return statement trumps the rest and is still the one that is returned by the function.</p><h3><strong>Part 4: The Plot Thickens</strong></h3><p>As you can imagine, any language which allows you to write dead code that produces unintended outcomes is problematic. The Python language developers recognized this danger, and proposed that <strong>return/break/continue </strong>statements should be disallowed in <code>finally</code> blocks in PEP601<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a>.</p><p>However, it was voted down for the following reason:</p><blockquote><p>Reading the references in the PEP it seems to me that most languages implement this kind of construct but have style guides and/or linters that reject it. I would support a proposal to add this to PEP 8 (if it isn&#8217;t already there).</p><p>I note that the toy examples are somewhat misleading &#8211; the functionality that <em>may</em> be useful is a <em>conditional</em> return (or break etc.) inside a finally block.</p><p>-Guido 2019 PEP601</p></blockquote><p>Guido&#8217;s reasoning was that there may be valid scenarios where the user requires full control of exception handling in the finally block, and may wish to override the raising of exceptions. Preventing this behavior would effectively hamstring advanced users.</p><p>However, in 2024 the community tried again with PEP765<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>. This time they were armed with evidence. They analyzed the top 8000 PyPi packages and found that:</p><blockquote><p>Most of the usages (of <code>return</code> in <code>finally</code>) are incorrect, and introduce unintended exception-swallowing bugs. - PEP765</p></blockquote><p>This was enough for the proposal to get over the line, and from Python 3.14 onwards, using <code>return, break </code>or<code> continue </code>in<code> </code>a<code> finally </code>clause emits a <code>SyntaxWarning.</code></p><h3>Part 5: Why use try/finally at all?</h3><p>A context manager is the pythonic choice <em>most</em> of the time when you&#8217;re working with resources that already expose acquire/release semantics that can easily slot into <code>__enter__</code> and <code>__exit__</code>. It&#8217;s the natural choice for files, locks, database connections, temporary state changes, etc. It&#8217;s declarative and minimizes surface area for errors. </p><p>However, they don&#8217;t always make sense:</p><ul><li><p>Context manager code lives in a different location, and so introduces an extra layer of abstraction. Sometimes your code is so simple and localized that introducing an extra layer of abstraction would make the code less readable with little benefit.</p></li><li><p>Context managers can only use variables passed in during initialization, whereas finally can reference variables mutated during execution in the try block.</p></li><li><p>With try/finally, you can combine <code>except</code> and <code>finally</code> clauses to explicitly manage different failure modes for more granular control.</p></li></ul><h3><strong>Closing the Circle</strong></h3><p>The novice believed the original message was secure. The master understood the final seal controls the truth.</p><p>The finally block always speaks last. You must ensure its final words do not obscure the truth of what came before.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>https://en.wikipedia.org/wiki/Exception_handling_syntax</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>https://peps.python.org/pep-0601/</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>https://peps.python.org/pep-0765/</p><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;33b8fe67-06da-4b1d-845c-7ee9f2ffdde6&quot;,&quot;caption&quot;:&quot;When crafting software, we often mistake a side effect for a feature. We assume that because a behavior works once, it will always work in all situations. In the transition from Python 3.11 to 3.12 the importlib.resources underwent such a refinement. A shortcut that once worked was revealed to be an illusion.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 19: The Unhelpful Eclipse&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-01-30T17:41:06.035Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!opxI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-19-the-unhelpful-eclipse&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:186238158,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></div></div>]]></content:encoded></item><item><title><![CDATA[Koan 19: The Unhelpful Eclipse]]></title><description><![CDATA[On the fragility of unintended behavior and the wisdom of explicit paths]]></description><link>https://pythonkoans.substack.com/p/koan-19-the-unhelpful-eclipse</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-19-the-unhelpful-eclipse</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Fri, 30 Jan 2026 17:41:06 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!opxI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!opxI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!opxI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png 424w, https://substackcdn.com/image/fetch/$s_!opxI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png 848w, https://substackcdn.com/image/fetch/$s_!opxI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png 1272w, https://substackcdn.com/image/fetch/$s_!opxI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!opxI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png" width="1456" height="1693" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1693,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:540613,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/186238158?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!opxI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png 424w, https://substackcdn.com/image/fetch/$s_!opxI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png 848w, https://substackcdn.com/image/fetch/$s_!opxI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png 1272w, https://substackcdn.com/image/fetch/$s_!opxI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1698d3c-ba91-4571-82fc-e9e5a0a4ef3d_1536x1786.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When crafting software, we often mistake a side effect for a feature. We assume that because a behavior works once, it will always work in all situations. In the transition from Python 3.11 to 3.12 the <code>importlib.resources </code>underwent such a refinement. A shortcut that once worked was revealed to be an illusion.</p><p>Let us peer at the sky slowly.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3>Part 1: The Nature of the Traversable</h3><p>In <a href="https://pythonkoans.substack.com/p/koan-14-the-missing-grain">Koan 14</a> we explored how non-python files can be included within a python package. <code>importlib.resources</code> is a Python standard library which lets you bundle up configuration files, database schemas, binaries and any other non-source files you may need to run your code.</p><p>When you run <code>importlib.resources.files(&#8220;my_package.test_data&#8221;)</code>, you might expect to get back a <code>Path</code>, but instead you get a <code>Traversible</code> object.</p><p>A <a href="https://docs.python.org/3/library/importlib.resources.abc.html#importlib.resources.abc.Traversable">Traversable</a> is an abstract class which provides &#8220;a <em><strong>subset</strong></em> of <code>pathlib.Path</code> methods suitable for traversing directories and opening files.&#8221;.</p><p><code>importlib.resources.files</code> returns a <code>Traversable </code>instead of a regular<code> pathlib.Path</code> because package data files can exist in various formats on disk:</p><ol><li><p>Within a tar file (in the case of wheels)</p></li><li><p>In a plain directory (in the case of editable installs) </p></li><li><p>Spread across multiple packages (in the case of namespace packages, which we learnt about in <a href="https://pythonkoans.substack.com/p/koan-7-the-unburdened-village">Koan 7</a>).</p></li></ol><p>It is a promise that something behaves like a file system path even if it is trapped inside a zip file or a remote package.</p><h3>Part 2: The Differences Emerge</h3><p>In our offending example, <code>importlib.resources.files </code>returns a <code>MultiplexedPath. </code>And this usually gives us most of the features we need to work with a path:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!D15k!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!D15k!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png 424w, https://substackcdn.com/image/fetch/$s_!D15k!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png 848w, https://substackcdn.com/image/fetch/$s_!D15k!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png 1272w, https://substackcdn.com/image/fetch/$s_!D15k!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!D15k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png" width="1456" height="684" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:684,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:240282,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/186238158?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!D15k!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png 424w, https://substackcdn.com/image/fetch/$s_!D15k!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png 848w, https://substackcdn.com/image/fetch/$s_!D15k!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png 1272w, https://substackcdn.com/image/fetch/$s_!D15k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc703e52-bf69-4a10-be18-041e4d548f14_1536x722.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>But sometimes we have code trapped in a library or an upstream function which expects a <code>Path</code> and uses methods unsupported by a <code>Traversable</code>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bCvA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bCvA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png 424w, https://substackcdn.com/image/fetch/$s_!bCvA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png 848w, https://substackcdn.com/image/fetch/$s_!bCvA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png 1272w, https://substackcdn.com/image/fetch/$s_!bCvA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bCvA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png" width="1456" height="720" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:273246,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/186238158?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bCvA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png 424w, https://substackcdn.com/image/fetch/$s_!bCvA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png 848w, https://substackcdn.com/image/fetch/$s_!bCvA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png 1272w, https://substackcdn.com/image/fetch/$s_!bCvA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4ce4677-950c-411d-aadc-7df67cecfd7f_1536x760.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And that might tempt us into using a shortcut to convert the <code>MultiplexedPath<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></code> into a <code>Path</code>.</p><h3><strong>Part 3: The Accidental Shortcut</strong></h3><p>In Python &lt;=3.11, <code>MultiplexedPath.joinpath("")</code> would return the first physical path it found. It felt like a convenient way to &#8220;extract&#8221; a real path.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!LBYF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LBYF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png 424w, https://substackcdn.com/image/fetch/$s_!LBYF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png 848w, https://substackcdn.com/image/fetch/$s_!LBYF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png 1272w, https://substackcdn.com/image/fetch/$s_!LBYF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!LBYF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png" width="1456" height="648" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:648,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:239603,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/186238158?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!LBYF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png 424w, https://substackcdn.com/image/fetch/$s_!LBYF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png 848w, https://substackcdn.com/image/fetch/$s_!LBYF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png 1272w, https://substackcdn.com/image/fetch/$s_!LBYF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4091fc44-6d06-4741-9f9e-4243ef8314bf_1536x684.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>By passing an empty string to <code>joinpath</code> you were asking the system to join &#8220;nothing&#8221; to the collection. The system responded by handing back the first item it held <em>as a PosixPath. </em>However, this turned out to be a quirk of the implementation, rather than a contract.</p><p>In Python 3.12 the implementation of <code>joinpath</code> was made more generic and robust. It began to strictly follow the logic of its ancestors. When you ask to join a path to a <code>MultiplexedPath</code> it now iterates through its internal requirements.</p><p>When you pass an empty string or a dot the iterator now reaches the end of its instructions and finds nothing to give. This <a href="https://github.com/python/cpython/issues/106614">tripped up</a> a lot of developers, and users of <a href="https://github.com/jupyter/notebook/pull/6965">libraries</a>.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3sGD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3sGD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png 424w, https://substackcdn.com/image/fetch/$s_!3sGD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png 848w, https://substackcdn.com/image/fetch/$s_!3sGD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png 1272w, https://substackcdn.com/image/fetch/$s_!3sGD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!3sGD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png" width="1456" height="906" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:906,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:329913,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/186238158?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!3sGD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png 424w, https://substackcdn.com/image/fetch/$s_!3sGD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png 848w, https://substackcdn.com/image/fetch/$s_!3sGD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png 1272w, https://substackcdn.com/image/fetch/$s_!3sGD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56973365-399a-4d74-9dee-c03dae27a99a_1536x956.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>Part 4: Facing the Eclipse</strong></h3><p>If your intent is to turn a <code>Traversable</code> object into a real physical file path, you must use a tool designed for that purpose. We should not use <code>joinpath</code> to change the nature of an object. Instead, use <code>as_file</code> to convert a MultiplexedPath to a PosixPath safely:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RGBL!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RGBL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png 424w, https://substackcdn.com/image/fetch/$s_!RGBL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png 848w, https://substackcdn.com/image/fetch/$s_!RGBL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png 1272w, https://substackcdn.com/image/fetch/$s_!RGBL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RGBL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png" width="1456" height="684" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:684,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:265599,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/186238158?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!RGBL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png 424w, https://substackcdn.com/image/fetch/$s_!RGBL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png 848w, https://substackcdn.com/image/fetch/$s_!RGBL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png 1272w, https://substackcdn.com/image/fetch/$s_!RGBL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faebe9647-a355-4719-8a1c-afe38abc7e0c_1536x722.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The Emperor lost his kingdom because he had mistaken a pattern for a law. He claimed power over the night because he had never seen the night without the light. In the same way, a programmer who relies on the side-effects of a method mistakes a consistent coincidence for a formal promise.</p><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>The full list of supported methods can be found here - https://importlib-resources.readthedocs.io/en/latest/api.html#importlib_resources.readers.MultiplexedPath</p><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;42191f7e-b4d3-4af3-ba43-fe8c5bd2971e&quot;,&quot;caption&quot;:&quot;In Python, a raw string literal is a string marked by the r prefix. It instructs the Python interpreter to treat the string &#8220;as it is written&#8221;, ignoring any escape sequences (such as \\n for newline, or \\t for tab).&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 18: The Loose Bundle&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-01-14T23:00:28.217Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!CSjp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-18-the-loose-bundle&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:183776647,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></div></div>]]></content:encoded></item><item><title><![CDATA[Koan 18: The Loose Bundle]]></title><description><![CDATA[Exploring the pitfalls of raw string literals in Python]]></description><link>https://pythonkoans.substack.com/p/koan-18-the-loose-bundle</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-18-the-loose-bundle</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Wed, 14 Jan 2026 23:00:28 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!CSjp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CSjp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CSjp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png 424w, https://substackcdn.com/image/fetch/$s_!CSjp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png 848w, https://substackcdn.com/image/fetch/$s_!CSjp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png 1272w, https://substackcdn.com/image/fetch/$s_!CSjp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CSjp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png" width="1456" height="901" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:901,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:463509,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183776647?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CSjp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png 424w, https://substackcdn.com/image/fetch/$s_!CSjp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png 848w, https://substackcdn.com/image/fetch/$s_!CSjp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png 1272w, https://substackcdn.com/image/fetch/$s_!CSjp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb23d5034-32ad-4d86-8768-842c26ac57ba_1536x950.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In Python, a raw string literal is a string marked by the <code>r</code> prefix. It instructs the Python interpreter to treat the string &#8220;as it is written&#8221;, ignoring any escape sequences (such as <code>\n</code> for newline, or <code>\t</code> for tab). </p><p>Last week in Koan 17 we explored how raw string literals can be used to prevent the &#8220;plague of backslashes&#8221; needed to search for strings containing escape sequences.</p><p>While raw string literals are certainly handy, there is one pitfall to watch out for. If a raw string ends in an odd number of backslashes, the last backslash escapes the closing quote. The string never ends, and the parser wanders into the void.</p><h3>Part 1: The Broken Promise of Rawness</h3><p>In a raw string literal one might assume that the backslash loses <em>all</em> of its power. However, this is not true. The backslash is stripped of its ability to create special characters (escape sequences), <em><strong>but it is not stripped of its ability to escape the next character</strong></em>.</p><p>Consider what a parser might do for the following:</p><p><code>s = r"The path is \"</code></p><p>When the parser encounters <code>\&#8221;</code>, it follows a strict rule: A backslash before a quote means the quote is part of the data, and not the end of the container. Even though this is a raw string, the parser still lets you include quotes:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CQi4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CQi4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png 424w, https://substackcdn.com/image/fetch/$s_!CQi4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png 848w, https://substackcdn.com/image/fetch/$s_!CQi4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png 1272w, https://substackcdn.com/image/fetch/$s_!CQi4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CQi4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png" width="1456" height="468" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:468,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:369782,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183776647?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CQi4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png 424w, https://substackcdn.com/image/fetch/$s_!CQi4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png 848w, https://substackcdn.com/image/fetch/$s_!CQi4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png 1272w, https://substackcdn.com/image/fetch/$s_!CQi4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dbead2f-531c-4e42-b113-bb951701ebe6_1536x494.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The backslash prevented the string from closing, <em><strong>but it also remained in the string.</strong></em></p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3>Part 2: The Unbound String</h3><p>This leads us to the weaver's bundle. If you want a raw string that ends with a single backslash, you create a problem for the parser. With the following string, your intent might be to create a string containing just a backslash, but instead:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2dM9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2dM9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png 424w, https://substackcdn.com/image/fetch/$s_!2dM9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png 848w, https://substackcdn.com/image/fetch/$s_!2dM9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png 1272w, https://substackcdn.com/image/fetch/$s_!2dM9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2dM9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png" width="1456" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:368543,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183776647?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2dM9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png 424w, https://substackcdn.com/image/fetch/$s_!2dM9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png 848w, https://substackcdn.com/image/fetch/$s_!2dM9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png 1272w, https://substackcdn.com/image/fetch/$s_!2dM9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2240f909-22bb-49b1-b014-f4c8342ff250_1536x532.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ol><li><p>The parser sees the opening <code>&#8221;</code></p></li><li><p>It enters raw mode</p></li><li><p>It sees <code>\</code></p></li><li><p>It sees <code>&#8221;</code> immediately after</p></li><li><p>Because of the backslash, it treats the <code>&#8220;</code> as a literal character inside the string</p></li><li><p>It continues looking for the closing quote, encounters the end of the line and raises a <code>SyntaxError</code></p></li></ol><p>This is why you can&#8217;t create a raw string literal that ends in an odd number of backslashes. The sharp edges of the bamboo pierce the binding rope.</p><h3>Part 3: Securing the Bundle</h3><p>If you absolutely must end a string with a backslash, you cannot use a raw string literal in isolation. You must separate the content from the termination.</p><p>There are several ways to tie this knot.</p><ol><li><p>Concatenate the raw string literal with a regular string with a single escaped backslash</p></li><li><p>Use an fstring, and either include the backslash as a variable, or escape it outside a variable</p></li><li><p>Same as the first method, but concatenate the string by using join on an array of strings containing the escaped backslash</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!PCMt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!PCMt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png 424w, https://substackcdn.com/image/fetch/$s_!PCMt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png 848w, https://substackcdn.com/image/fetch/$s_!PCMt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png 1272w, https://substackcdn.com/image/fetch/$s_!PCMt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!PCMt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png" width="1456" height="648" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:648,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:437804,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183776647?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!PCMt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png 424w, https://substackcdn.com/image/fetch/$s_!PCMt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png 848w, https://substackcdn.com/image/fetch/$s_!PCMt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png 1272w, https://substackcdn.com/image/fetch/$s_!PCMt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1c94f3bc-f336-472b-8846-040b1b06364e_1536x684.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>The Master&#8217;s Reflection</h3><p>The raw string is a tool of convenience, but it is still a servant to the parser. While it treats backslashes as literals for the sake of the string's <em>value</em>, it still respects backslashes for the sake of the string's <em>syntax</em>. A diligent developer separates the boundary from the content when these conflicts arise.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-18-the-loose-bundle?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! If you enjoyed this post, share it with your friends</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-18-the-loose-bundle?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://pythonkoans.substack.com/p/koan-18-the-loose-bundle?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;feff7062-d722-44a5-9631-f94b368ca590&quot;,&quot;caption&quot;:&quot;Regex: Searching for the tiger&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 17: The Watchman at the Gate&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-01-07T23:00:38.090Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!Zv1h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-17-the-watchman-at-the-gate&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:183537722,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:6,&quot;comment_count&quot;:2,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Koan 17: The Watchman at the Gate]]></title><description><![CDATA[A look into Python's regex module]]></description><link>https://pythonkoans.substack.com/p/koan-17-the-watchman-at-the-gate</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-17-the-watchman-at-the-gate</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Wed, 07 Jan 2026 23:00:38 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Zv1h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Zv1h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Zv1h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png 424w, https://substackcdn.com/image/fetch/$s_!Zv1h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png 848w, https://substackcdn.com/image/fetch/$s_!Zv1h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png 1272w, https://substackcdn.com/image/fetch/$s_!Zv1h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Zv1h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png" width="1456" height="1261" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1261,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:560455,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183537722?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Zv1h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png 424w, https://substackcdn.com/image/fetch/$s_!Zv1h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png 848w, https://substackcdn.com/image/fetch/$s_!Zv1h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png 1272w, https://substackcdn.com/image/fetch/$s_!Zv1h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70254e67-1de5-40cb-9535-4a19c7e450af_1536x1330.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Regex: Searching for the tiger</h3><p>Python&#8217;s `re` module is a robust toolset for writing regular expressions (regex), but its behavior often deviates from other engines. Understanding the nuances of the interpreter and the Unicode standard is essential for writing predictable patterns.</p><p>Let us explore the treacherous terrain of the re module.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3>Part 1: Anchoring: match() vs. search()</h3><p>A common misconception is that <code>re.match()</code> scans the entire string. In reality, it is implicitly anchored to the start of the string (effectively adding a <code>\A</code> or <code>^</code> anchor). If you want to find a pattern anywhere in the input, use re.search() instead.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yGm4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yGm4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png 424w, https://substackcdn.com/image/fetch/$s_!yGm4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png 848w, https://substackcdn.com/image/fetch/$s_!yGm4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png 1272w, https://substackcdn.com/image/fetch/$s_!yGm4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yGm4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png" width="1456" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:262678,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183537722?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yGm4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png 424w, https://substackcdn.com/image/fetch/$s_!yGm4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png 848w, https://substackcdn.com/image/fetch/$s_!yGm4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png 1272w, https://substackcdn.com/image/fetch/$s_!yGm4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa949f9b4-3911-4901-8897-d98486cc1bc0_1536x798.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>You can think of<code> re.match()</code> like the watchman at the gate, fastidiously inspecting anything coming into the city. If the string you are searching for is not right at the start, he declares it absent.</p><p>re.search on the other hand is more like a scout. He wanders through the city looking for that which is hidden. This scans the entire string to find a match.</p><p>If you wish to find a pattern that may be hidden deep within the text, you must send the scout (<code>re.search</code>) instead of the guard (<code>re.match)</code>.</p><h3>Part 2: The Map and the Territory (Raw Strings)</h3><p>Python strings process backslashes (<code>\</code>) as escape sequences before they reach the regex engine. An escape sequence<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> is a sequence of characters following a backslash which the Python interpreter treats differently. There are several such strings: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Spou!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Spou!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png 424w, https://substackcdn.com/image/fetch/$s_!Spou!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png 848w, https://substackcdn.com/image/fetch/$s_!Spou!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png 1272w, https://substackcdn.com/image/fetch/$s_!Spou!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Spou!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png" width="410" height="652" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:652,&quot;width&quot;:410,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:62921,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183537722?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Spou!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png 424w, https://substackcdn.com/image/fetch/$s_!Spou!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png 848w, https://substackcdn.com/image/fetch/$s_!Spou!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png 1272w, https://substackcdn.com/image/fetch/$s_!Spou!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffcd75b95-dfaf-4d30-8588-0e98b520496a_410x652.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>To prevent this, and to match a literal backslash in regex one must create a &#8220;plague of backslashes&#8221;. For example, to match a literal backslash you would need four backslashes (<code>\\\\</code>)</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2dMT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2dMT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png 424w, https://substackcdn.com/image/fetch/$s_!2dMT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png 848w, https://substackcdn.com/image/fetch/$s_!2dMT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png 1272w, https://substackcdn.com/image/fetch/$s_!2dMT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2dMT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png" width="1456" height="540" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:540,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:203514,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183537722?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2dMT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png 424w, https://substackcdn.com/image/fetch/$s_!2dMT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png 848w, https://substackcdn.com/image/fetch/$s_!2dMT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png 1272w, https://substackcdn.com/image/fetch/$s_!2dMT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F627bef69-9adf-4ecf-835f-4e0906806cd4_1536x570.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>As you can see this is prone to error as you can easily use the wrong number of backslashes. A master uses raw string literals instead<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> (<code>r""). This</code> tells Python to ignore the escape sequences and pass the string exactly as written to the regex engine.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YjpZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YjpZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png 424w, https://substackcdn.com/image/fetch/$s_!YjpZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png 848w, https://substackcdn.com/image/fetch/$s_!YjpZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png 1272w, https://substackcdn.com/image/fetch/$s_!YjpZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YjpZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png" width="1456" height="432" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:432,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:168785,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183537722?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YjpZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png 424w, https://substackcdn.com/image/fetch/$s_!YjpZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png 848w, https://substackcdn.com/image/fetch/$s_!YjpZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png 1272w, https://substackcdn.com/image/fetch/$s_!YjpZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4e4ac5b-2024-4f1c-a940-acbf2dbc1f72_1536x456.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Part 3: The Illusion of the End</h3><p>By default, the <code>$</code> anchor matches the end of the string or the position immediately preceding a newline at the very end. This is fine most of the time, but sometimes you may want to verify that a string contains no trailing whitespace or newlines:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YfJp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YfJp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png 424w, https://substackcdn.com/image/fetch/$s_!YfJp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png 848w, https://substackcdn.com/image/fetch/$s_!YfJp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png 1272w, https://substackcdn.com/image/fetch/$s_!YfJp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YfJp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png" width="1456" height="576" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:576,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:213276,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183537722?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YfJp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png 424w, https://substackcdn.com/image/fetch/$s_!YfJp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png 848w, https://substackcdn.com/image/fetch/$s_!YfJp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png 1272w, https://substackcdn.com/image/fetch/$s_!YfJp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F48893309-3a1f-429c-bcab-2fd04a7aca26_1536x608.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>To strictly enforce the absolute end of the string and disregard any trailing newlines, use <code>\Z. </code>This only matches the absolute end of the input.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Jvc3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Jvc3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png 424w, https://substackcdn.com/image/fetch/$s_!Jvc3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png 848w, https://substackcdn.com/image/fetch/$s_!Jvc3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png 1272w, https://substackcdn.com/image/fetch/$s_!Jvc3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Jvc3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png" width="1456" height="540" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:540,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:199299,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183537722?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Jvc3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png 424w, https://substackcdn.com/image/fetch/$s_!Jvc3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png 848w, https://substackcdn.com/image/fetch/$s_!Jvc3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png 1272w, https://substackcdn.com/image/fetch/$s_!Jvc3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec3a23c-b5e2-4220-9915-85863048d65f_1536x570.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Part 4: The Thousand Faces of Numbers</h3><p>In the modern era of Python 3, the definition of the "digit" escape sequence (<code>\d)</code> has expanded beyond the Arabic numerals 0-9.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!R31W!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!R31W!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png 424w, https://substackcdn.com/image/fetch/$s_!R31W!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png 848w, https://substackcdn.com/image/fetch/$s_!R31W!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png 1272w, https://substackcdn.com/image/fetch/$s_!R31W!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!R31W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png" width="1456" height="540" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:540,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:211623,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183537722?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!R31W!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png 424w, https://substackcdn.com/image/fetch/$s_!R31W!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png 848w, https://substackcdn.com/image/fetch/$s_!R31W!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png 1272w, https://substackcdn.com/image/fetch/$s_!R31W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0b36be91-40ce-472d-ab14-d62e02da3198_1536x570.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Python 3&#8217;s <code>re</code> module is Unicode aware, which means the regex token <code>\d</code> does not just mean the ASCII digits 0&#8211;9 anymore. It matches any character that has the Unicode property of <code>Numeric_Type=Decimal</code>.</p><p>For example, the Tamil characters <code>&#3054;</code> (U+0BEA) and <code>&#3056;</code> (U+0BF0) are officially categorized as digits/numbers in the Unicode database.</p><p>When a developer writes a regex to extract a price, they might assume <code>\d+</code> will only return characters that can be easily cast to an integer using standard libraries, or characters they can safely display in an ASCII-only receipt.</p><p>You can imagine the chaos that would be caused if a payment system accepts <code>&#3054;&#3056;</code> as a valid &#8220;number&#8221; but the downstream payment processor only understands <code>80</code>. It might crash or, worse, treat the value as <code>0</code> or <code>null</code>, leading to logic errors.</p><p>If your logic depends on strictly parsing standard <code>0-9</code> integers, you must instruct the engine to ignore the wider world using the <code>re.ASCII</code> flag.</p><h3>Part 6: The Broken Collection (<code>findall</code>)</h3><p>The <code>re.findall()</code> method is a powerful tool for gathering all occurrences. However, its changes it&#8217;s return type based on the pesence of &#8220;capturing groups&#8221; (parentheses) in the regex.</p><p>If there are no capturing groups, it returns a list of strings. If there is a group, it returns only the contents of that matched group.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NLar!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NLar!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png 424w, https://substackcdn.com/image/fetch/$s_!NLar!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png 848w, https://substackcdn.com/image/fetch/$s_!NLar!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png 1272w, https://substackcdn.com/image/fetch/$s_!NLar!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NLar!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png" width="1456" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:251864,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/183537722?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NLar!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png 424w, https://substackcdn.com/image/fetch/$s_!NLar!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png 848w, https://substackcdn.com/image/fetch/$s_!NLar!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png 1272w, https://substackcdn.com/image/fetch/$s_!NLar!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F965ec42c-e50c-401c-bb92-0b41d96c93bf_1536x798.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Because of variability in return type, it is not advisable to run <code>re.findall()</code> on a regex you do not know in advance (i.e. from a variable or user input).</p><p>If you want to ensure consistent output regardless of pattern structure, use <code>re.finditer()</code>.</p><h3>The Final Pattern</h3><p>The regex engine is a powerful but tricky feature to master, but the following guidelines can help light your way:</p><ol><li><p>Know when to choose a watchman (<code>match</code>) or a scout (search)</p></li><li><p>Use raw strings over escaped backslashes.</p></li><li><p>Know the true boundaries when searching the end of a line (<code>$</code> vs <code>\Z</code>).</p></li><li><p>Handle Unicode when matching numbers</p></li><li><p>Prefer <code>re.finditer() </code>over<code> re.findall()</code> for ensure consistent output regardless of regex</p></li></ol><p>Do not assume the pattern you see in your mind is the pattern you have written on the scroll.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-17-the-watchman-at-the-gate?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! If you enjoyed this post, restack or share it!</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-17-the-watchman-at-the-gate?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://pythonkoans.substack.com/p/koan-17-the-watchman-at-the-gate?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>https://docs.python.org/3/reference/lexical_analysis.html#escape-sequences</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>https://docs.python.org/3/reference/lexical_analysis.html#raw-string-literals</p><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;1c0ea6a5-db13-45d0-96dd-9204e7e9818e&quot;,&quot;caption&quot;:&quot;The Hidden Teaching: The Boundary of Execution&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 16: The Master's Lesson&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-11-05T23:16:29.909Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!5jwW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-16-the-masters-lesson&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:177876505,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></div></div>]]></content:encoded></item><item><title><![CDATA[Koan 9: The Unfired Pot REDUX]]></title><description><![CDATA[Experience is simply the name we give our mistakes - Oscar Wilde]]></description><link>https://pythonkoans.substack.com/p/koan-9-the-unfired-pot-redux</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-9-the-unfired-pot-redux</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Tue, 16 Dec 2025 23:01:33 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/c99a4a74-526f-444e-93a1-3c00e32ee70f_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This is not your usual Python Koans post. It&#8217;s come to my attention that there is some information in <a href="https://pythonkoans.substack.com/p/koan-9-the-unfired-pot">Koan 9: The Unfired Pot</a> that is either incorrect or misleading. </p><p>Firstly, I&#8217;d like to apologize sincerely for letting this slip through the cracks. I try to be as diligent as possible when writing each post, but this one wasn&#8217;t my best work. I&#8217;ve put some steps in place so that this doesn&#8217;t happen again. Also, a big thanks to <a href="https://substack.com/@vekyll">@vekyll</a> who pointed some of the issues out.</p><p>Secondly, I&#8217;ve edited the original post to correct those mistakes, but I thought it would be worthwhile to revisit some fundamental concepts underpinning the topic here, and also expand on the corrections.</p><h2>Python Statements and Expressions</h2><p>The building blocks of Python are statements. A statement is a block of code which does something. If a statement can fit in one line, it is a <a href="https://docs.python.org/3/reference/simple_stmts.html#simple-statements">Simple Statement</a>, otherwise it&#8217;s a <a href="https://docs.python.org/3/reference/compound_stmts.html#compound-statements">Compound Statement</a>.</p><p>An <a href="https://docs.python.org/3/glossary.html#term-expression">expression</a> is a special type of statement which evaluates to a single value:</p><blockquote><p>An expression is an accumulation of expression elements like literals, names, attribute access, operators or function calls which all return a value. In contrast to many other languages, not all language constructs are expressions. There are also&nbsp;statements which cannot be used as expressions, such as&nbsp;<a href="http://(https://docs.python.org/3/reference/compound_stmts.html#while).">while</a>. </p><p>from <a href="https://docs.python.org/3/glossary.html#term-expression">Python Glossary</a></p></blockquote><h3>1. Assignments don&#8217;t return values</h3><p><em><strong>An assignment is a statement, but it is not an expression</strong></em>. This is because it doesn&#8217;t return a value. Some of the text from the original post <em>implied</em> that assignment returns a value. For e.g.</p><blockquote><p>This assignment itself returns the value that was assigned</p></blockquote><p>This is false, assignment <em><strong>never</strong></em> returns a value. </p><p>You also can&#8217;t use assignments inside expressions like you can in C (like <code>if (x = y)</code>).  However, one exception was introduced in Python 3.8. <a href="https://docs.python.org/3/reference/expressions.html#assignment-expressions">Assignment expressions</a> (also known as the walrus operator) like <code>if (x := y):</code> lets you assign values within an expression.</p><h3>2. Chained Assignment evaluates RHS, then binds names left -&gt; right</h3><p>The original post stated that chained assignments are evaluated right to left, but this is misleading. For this example from the original post:</p><pre><code>x = 10
x = y = z = x + 2</code></pre><p>Python evaluates the right-hand-side <code>x + 2</code> first, then binds the value to the names from left to right. i.e <code>x</code>, <code>y</code>, and then <code>z</code> last.</p><p>Python does <em><strong>not</strong></em> evaluate chained assignment by returning a value from each individual assignment and then reassigning it leftwards. </p><h3>3. Comparison Chains Do Not Behave Like Assignment Chains</h3><p>The original post ambiguously stated that <em>chained operations</em> like <code>1 &lt; x &lt; 10</code> and <em>chained assignments</em> operate under the same principle:</p><blockquote><p>The same principle applies to chained comparison operators such as&nbsp;<code>&lt;</code>,&nbsp;<code>&gt;</code>&nbsp;and&nbsp;<code>==</code>.</p></blockquote><p>This is false of course, and the rest of the section does gets it right. Comparison chains are essentially syntactic sugar which evaluates to distinct comparisons <code>and</code>-ed together: <code>(1 &lt; x) and (x &lt; 10)</code>. </p><div><hr></div><p>Thanks again for continuing to read Python Koans. I hope you&#8217;ve learnt something new along the way. I&#8217;ve got lots of great content and a new learning platform planned for the new year. Stay tuned!</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Koan 16: The Master's Lesson]]></title><description><![CDATA[Why we need "if __name__ == '__main__'"]]></description><link>https://pythonkoans.substack.com/p/koan-16-the-masters-lesson</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-16-the-masters-lesson</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Wed, 05 Nov 2025 23:16:29 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!5jwW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5jwW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5jwW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png 424w, https://substackcdn.com/image/fetch/$s_!5jwW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png 848w, https://substackcdn.com/image/fetch/$s_!5jwW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png 1272w, https://substackcdn.com/image/fetch/$s_!5jwW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5jwW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png" width="1456" height="1244" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1244,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:440037,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/177876505?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5jwW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png 424w, https://substackcdn.com/image/fetch/$s_!5jwW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png 848w, https://substackcdn.com/image/fetch/$s_!5jwW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png 1272w, https://substackcdn.com/image/fetch/$s_!5jwW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d2371d5-73b9-44f8-822e-b729c499f7f8_1536x1312.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>The Hidden Teaching: The Boundary of Execution</strong></h3><p>One of the most ubiquitous pieces of Python code is the expression <code>if __name__ == &#8220;__main__&#8221;. </code>You will often find this in standalone scripts or entrypoints to cli tools. But why is this needed and what are the consequences if this simple statement is left out? Some of these may surprise you.</p><p>Let us begin again.</p><h3><strong>Part 1: The Dual Nature of Python Files</strong></h3><p>When Python processes a file, whether by running it directly (<code>python training_hall.py</code>) or by importing it (<code>import training_hall</code>):</p><ol><li><p>It reads the code from top to bottom of the file, executing all code that is <em><strong>not</strong></em> inside a function or class definition.</p></li><li><p>It inserts all objects (functions, classes and variables) into the current namespace (using the scoping rules we learnt in <a href="https://pythonkoans.substack.com/p/koan-4-the-grand-library">Koan 4</a>).</p></li></ol><p>In our introductory snippet, the functions <code>fetch_staff</code> and <code>conduct_lesson </code>are defined on import, becoming <em><strong>functions available in the global scope</strong></em>. The code inside them is not executed. This is correct behavior for a utility.</p><p>Observe what happens without the protective boundary:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Oy0P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Oy0P!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!Oy0P!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!Oy0P!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!Oy0P!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Oy0P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:233439,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/177876505?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Oy0P!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!Oy0P!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!Oy0P!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!Oy0P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b017086-1fc9-427b-bf29-dd369399e1aa_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>if another file attempts to import this file, the terminal will print:</p><pre><code>The master enters. The lesson begins.
A staff is taken from the rack.</code></pre><p>The lesson begins prematurely. The boundary was not drawn to separate <strong>definition</strong> from <strong>invocation</strong>.</p><p>The special attribute <code>__name__</code> is a string that holds the module&#8217;s identity.</p><ul><li><p>When the file is executed directly, Python&#8217;s master interpreter sets <code>__name__</code> to the string <code>&#8220;__main__&#8221;</code>.</p></li><li><p>When the file is imported, <code>__name__</code> is set to the module&#8217;s <strong>file name</strong> (e.g., <code>&#8220;training_hall&#8221;</code>).</p></li></ul><p>The guard acts as a lock:</p><pre><code><code>if __name__ == &#8220;__main__&#8221;:
    conduct_lesson()</code></code></pre><p>Now, if imported, <code>__name__</code> is <code>&#8220;training_hall&#8221;</code>. The condition is <strong>False</strong>, and <code>conduct_lesson()</code> is not run.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3><strong>Part 2: The Breakage of Relative Paths</strong></h3><p>Sometimes modules use relative imports to refer to its siblings:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WC6z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WC6z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!WC6z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!WC6z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!WC6z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WC6z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:223612,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/177876505?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WC6z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!WC6z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!WC6z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!WC6z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8803394a-e181-46b6-9bc3-9ed56be2331a_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When you run <code>python mypackage/temple.py</code> directly, you will be greeted with this error:</p><pre><code>ImportError: attempted relative import with no known parent package</code></pre><p>When run directly, <code>temple.py </code>is not part of a package, so it&#8217;s <code>__name__</code> becomes <code>__main__</code>, not <code>mypackage.temple. </code>Python&#8217;s import system expects a module run as main to be at the package root. The relative import from <code>.</code> (the current directory)  breaks as the package structure is lost.</p><p>The fix is to run the code as a module: <code>python -m mypackage.temple;</code> or switch to a relative import: <code>import mypackage.temple.</code></p><h3>Part 3: A Fine Pickle</h3><p>The <code>pickle</code> module can be used to serialize and deserialize python objects to disk. To do this, it stores object references by their importable path, e.g. <code>mypackage.temple.ClassName</code>. Imagine you had two files - <code>save_code.py</code> which saved an object to disk in the main module, and another - <code>load_code.py</code> which tried to load the pickled object from disk:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YG7z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YG7z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png 424w, https://substackcdn.com/image/fetch/$s_!YG7z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png 848w, https://substackcdn.com/image/fetch/$s_!YG7z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png 1272w, https://substackcdn.com/image/fetch/$s_!YG7z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YG7z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png" width="1456" height="925" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:925,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:301721,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/177876505?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YG7z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png 424w, https://substackcdn.com/image/fetch/$s_!YG7z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png 848w, https://substackcdn.com/image/fetch/$s_!YG7z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png 1272w, https://substackcdn.com/image/fetch/$s_!YG7z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F60059986-4e11-4f91-9d57-9ed4a6900125_1536x976.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This would throw an error:</p><pre><code>AttributeError: Can&#8217;t get attribute &#8216;Model&#8217; on &lt;module &#8216;__main__&#8217;&gt;</code></pre><p>When you define a class or function in <code>__main__</code>, its path is <code>&#8220;__main__.ClassName&#8221;</code>, which gets saved in the pickled object. When the object is unpickled in load_code.py  <code>&#8220;__main__.ClassName&#8221; </code>doesn&#8217;t exist in the module. So data pickled in the <code>__main__</code> module <em><strong>cannot be re-imported later</strong></em> when unpickling elsewhere. The fix is to ensure that you always pickle in an importable module:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Wf4s!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Wf4s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!Wf4s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!Wf4s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!Wf4s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Wf4s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:217117,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/177876505?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Wf4s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!Wf4s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!Wf4s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!Wf4s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9d0ab29-4b29-482a-83f9-d8cedef33bb9_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>Part 3: The Child Process and the Re-Import</strong></h3><p>In certain operating systems, especially Windows, Python&#8217;s <code>multiprocessing</code> library avoids sharing memory state directly between a parent and its new child process. Instead, it <strong>re-imports the entire main module</strong> into the new child process to ensure a clean start. Consider the risk:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nhq2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nhq2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png 424w, https://substackcdn.com/image/fetch/$s_!nhq2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png 848w, https://substackcdn.com/image/fetch/$s_!nhq2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png 1272w, https://substackcdn.com/image/fetch/$s_!nhq2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nhq2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png" width="1456" height="726" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:726,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:271779,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/177876505?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nhq2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png 424w, https://substackcdn.com/image/fetch/$s_!nhq2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png 848w, https://substackcdn.com/image/fetch/$s_!nhq2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png 1272w, https://substackcdn.com/image/fetch/$s_!nhq2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F063ef6e2-18ce-40c6-9876-eb365e4cd0ce_1536x766.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Without a guard, the child process, upon re-importing <code>master.py</code>, would execute the process creation line again, leading to an <strong>infinite creation of child processes</strong>.</p><p>Again, our simple guard prevents this:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XJwl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XJwl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png 424w, https://substackcdn.com/image/fetch/$s_!XJwl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png 848w, https://substackcdn.com/image/fetch/$s_!XJwl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png 1272w, https://substackcdn.com/image/fetch/$s_!XJwl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XJwl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png" width="1456" height="726" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:726,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:261493,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/177876505?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!XJwl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png 424w, https://substackcdn.com/image/fetch/$s_!XJwl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png 848w, https://substackcdn.com/image/fetch/$s_!XJwl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png 1272w, https://substackcdn.com/image/fetch/$s_!XJwl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4d05ed82-b3a3-4a6a-9a9b-6b8d556855aa_1536x766.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The child process, when re-importing the module, sets the module&#8217;s name to its file name (e.g., <code>&#8216;master&#8217;</code>), not <code>&#8220;__main__&#8221;</code>, thus bypassing the process creation code and safely starting its task.</p><h3><strong>Part 4: Python Execution Types</strong></h3><p>There are other ways a module may be executed without becoming the true primary executable, each leading to a different <code>__name__</code> value.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1KHz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1KHz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!1KHz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!1KHz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!1KHz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1KHz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:254617,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/177876505?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1KHz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!1KHz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!1KHz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!1KHz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa42e7405-7dc6-4fd2-bc86-1fda9f1e5add_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ul><li><p>When running a module with <code>python -m my_package.my_module</code>, the <code>runpy<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></code> utility is used. This forces <code>__name__</code> to <code>&#8220;__main__&#8221;</code>, allowing execution of a module within a package structure.</p></li><li><p>In environments like Jupyter or the basic Python REPL, an executed cell or a pasted block of code is considered the immediate execution context, and its <code>__name__</code> is also temporarily <code>&#8220;__main__&#8221;</code>.</p></li><li><p>In test environments (like <strong>pytest</strong>) or when a file is genuinely imported <code>__name__</code> will not be <code>&#8220;__main__&#8221;</code>. Test files are executed as imported modules, not as main scripts, ensuring that their test suites do not inadvertently run the protected code.</p></li></ul><h3><strong>Ending The Lesson</strong></h3><p>The Master&#8217;s teaching was simple: the <strong>staff</strong> stands ready on the rack, until the lesson is initiated by the master. The guard <code>if __name__ == &#8220;__main__&#8221;:</code> serves as the master&#8217;s permission, ensuring that the module&#8217;s core logic is run only when needed.</p><p>It separates code that is merely <em><strong>defined</strong></em> from code that is <em><strong>executed</strong></em> and answers a fundamental question Python asks of every file it touches: <em>Are you a library I should use, or a program I should run?</em></p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-16-the-masters-lesson?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! If you enjoyed this post, consider sharing it with your friends!</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-16-the-masters-lesson?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://pythonkoans.substack.com/p/koan-16-the-masters-lesson?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>&#8220;The <code>runpy</code> module is used to locate and run Python modules without importing them first. Its main use is to implement the <code>-m</code> command line switch that allows scripts to be located using the Python module namespace rather than the filesystem&#8221; - https://docs.python.org/3/library/runpy.html</p><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;81610de3-4e4a-4c86-9efd-c33b27447f22&quot;,&quot;caption&quot;:&quot;The Hidden Teaching: The Depth Below the Surface&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 15: The Invisible Ink&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-10-23T23:01:21.762Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4bae663d-2b3b-49a0-9289-4f6ee9728f62_1536x1102.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-15-the-invisible-ink&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:176553222,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:7,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p></p></div></div>]]></content:encoded></item><item><title><![CDATA[Koan 15: The Invisible Ink]]></title><description><![CDATA[Understanding Unicode equivalence and the deceptive nature of glyphs]]></description><link>https://pythonkoans.substack.com/p/koan-15-the-invisible-ink</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-15-the-invisible-ink</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Thu, 23 Oct 2025 23:01:21 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/4bae663d-2b3b-49a0-9289-4f6ee9728f62_1536x1102.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6WJ7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6WJ7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png 424w, https://substackcdn.com/image/fetch/$s_!6WJ7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png 848w, https://substackcdn.com/image/fetch/$s_!6WJ7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png 1272w, https://substackcdn.com/image/fetch/$s_!6WJ7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6WJ7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png" width="1456" height="1045" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1045,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:344192,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/176553222?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6WJ7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png 424w, https://substackcdn.com/image/fetch/$s_!6WJ7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png 848w, https://substackcdn.com/image/fetch/$s_!6WJ7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png 1272w, https://substackcdn.com/image/fetch/$s_!6WJ7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a2d1a4b-5017-4914-bf97-2181bcb5be8c_1536x1102.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>The Hidden Teaching: The Depth Below the Surface</h3><p>When the eye sees a character it perceives a <em><strong>glyph<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a></strong></em><strong>, </strong>which is a single visual form. Computers represent the glyph using a number (a <em><strong>code point</strong></em>) within a lookup table (a <em><strong>codespace</strong></em>). To the eye the forms may be identical, but to the machine they are different.</p><p>To work with text is to know the difference between what is seen and what is unseen.</p><h3>Part 1: The Illusion of Sameness</h3><p>The novice&#8217;s confusion is a common one. Two strings can appear to be the same character yet possess different underlying structures. This is the issue of <strong>canonical equivalence</strong><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> in Unicode.</p><p>Consider the character &#233;. It can be represented in two ways:</p><ol><li><p><strong>Normalization Form C (NFC):</strong> A single code point, U+00E9 (<strong>LATIN SMALL LETTER E WITH ACUTE)</strong>. This is the <em><strong>composed</strong></em> form.</p></li><li><p><strong>Normalization Form D (NFD):</strong> Two code points, U+0065 (<strong>LATIN SMALL LETTER E)</strong> followed by U+0301 (<strong>COMBINING ACUTE ACCENT)</strong>. This is the <em><strong>decomposed</strong></em> form.</p></li></ol><p>Python treats them as distinct sequences of code points, which are unequal in length and content:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!78Qm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!78Qm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png 424w, https://substackcdn.com/image/fetch/$s_!78Qm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png 848w, https://substackcdn.com/image/fetch/$s_!78Qm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png 1272w, https://substackcdn.com/image/fetch/$s_!78Qm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!78Qm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png" width="1456" height="686" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:686,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:247363,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/176553222?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!78Qm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png 424w, https://substackcdn.com/image/fetch/$s_!78Qm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png 848w, https://substackcdn.com/image/fetch/$s_!78Qm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png 1272w, https://substackcdn.com/image/fetch/$s_!78Qm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F278e83ff-9a26-4e21-a819-cfc06eb10344_1536x724.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3>Part 2: Achieving Canonical Truth with <code>unicodedata</code></h3><p>To compare characters based on their visual or canonical meaning, we must <em><strong>normalize</strong></em> them. Python&#8217;s <code>unicodedata</code> module provides the tool for this alignment.</p><p>The <code>unicodedata.normalize()</code> function converts strings to a standard form ensuring that sequences that are visually the same (canonically equivalent) are also code-point-wise the same.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cNV8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cNV8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png 424w, https://substackcdn.com/image/fetch/$s_!cNV8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png 848w, https://substackcdn.com/image/fetch/$s_!cNV8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png 1272w, https://substackcdn.com/image/fetch/$s_!cNV8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cNV8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png" width="1456" height="726" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:726,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:264923,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/176553222?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!cNV8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png 424w, https://substackcdn.com/image/fetch/$s_!cNV8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png 848w, https://substackcdn.com/image/fetch/$s_!cNV8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png 1272w, https://substackcdn.com/image/fetch/$s_!cNV8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F272a5879-8eac-4850-a1a4-915368bbd6cd_1536x766.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>By normalizing both strings to NFC we ensure that the decomposed form e\u0301 is converted into its single-point composed form &#233; making the comparison meaningful and true to the eye&#8217;s perception.</p><p>The common wisdom for text processing is:</p><ul><li><p>Use <strong>NFC</strong> (Composition) for storage and transmission of unicode text.</p></li><li><p>Use <strong>NFD</strong> (Decomposition) for text processing and complex comparisons.</p></li></ul><h3>Part 3: The Deception of String Length</h3><p>As we saw previously, the built-in <code>len()</code> function counts the number of <strong>code points,</strong> not the number of visual characters or <strong>graphemes</strong>. This is important for tasks like truncating text display or cursor movement which operate on <em><strong>grapheme clusters</strong></em><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a>.</p><p>To correctly count the visual characters, one must implement a more sophisticated counting mechanism which understands the rules of grapheme clustering. For simple cases, normalization can offer a partial solution.</p><p>For example, if we normalize to NFC before counting, we often align the code point count closer to the grapheme count:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!G6XT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!G6XT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!G6XT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!G6XT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!G6XT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!G6XT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/af6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:224485,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/176553222?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!G6XT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!G6XT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!G6XT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!G6XT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faf6d07a8-b8f2-4826-8738-f1d4f62294ca_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This is a helpful step <em><strong>but it is not a complete answer for all complex scripts and combining marks</strong></em> which may still result in a grapheme that is more than one code point, even in NFC.</p><h3>Part 4: Seeing the Unseen</h3><p>Beyond composition lies the matter of invisible characters. <em><strong>Control characters</strong></em><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a> like the Zero Width Space U+200B or soft hyphens are valid code points but have no visual rendering. They are often copied from web sources and cause silent failures in parsing or comparison.</p><p>When inspecting strings the standard <code>print()</code> function often hides the true nature of the text. The <code>repr()</code> function however reveals the string&#8217;s raw code point sequence making the invisible visible.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AtAH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AtAH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png 424w, https://substackcdn.com/image/fetch/$s_!AtAH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png 848w, https://substackcdn.com/image/fetch/$s_!AtAH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png 1272w, https://substackcdn.com/image/fetch/$s_!AtAH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AtAH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png" width="1456" height="607" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:607,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:238270,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/176553222?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AtAH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png 424w, https://substackcdn.com/image/fetch/$s_!AtAH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png 848w, https://substackcdn.com/image/fetch/$s_!AtAH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png 1272w, https://substackcdn.com/image/fetch/$s_!AtAH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7f7fa84-0b86-4fec-a608-377a551bc120_1536x640.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The <strong>Zero Width Space</strong> \u200b is revealed by <code>repr()</code>. Before comparison or processing it is often necessary to aggressively strip or replace such characters.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_ywy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_ywy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!_ywy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!_ywy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!_ywy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_ywy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:231381,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/176553222?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_ywy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!_ywy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!_ywy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!_ywy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3daf501e-7085-474f-8842-bc5ecc473310_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Part 5: Homographic Attacks</h3><p>The principle of canonical equivalence and unseen control characters have been pu to nefarious use in phishing attacks. Attackers register a domain name containing one or more unicode characters which are canonically equivalent to a well known character. </p><p>They then host an identical copy of the legitimate website on the newly registered domain, and steal user data or infect their computer with malware.</p><p>The following is an example of an homographic attack; the Latin letters &#8220;e&#8221; and &#8220;a&#8221; are replaced with the Cyrillic letters &#8220;<a href="https://en.wikipedia.org/wiki/Ye_(Cyrillic)">&#1077;</a>&#8220; and &#8220;<a href="https://en.wikipedia.org/wiki/A_(Cyrillic)">&#1072;</a>&#8220;<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Rkwf!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Rkwf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png 424w, https://substackcdn.com/image/fetch/$s_!Rkwf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png 848w, https://substackcdn.com/image/fetch/$s_!Rkwf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png 1272w, https://substackcdn.com/image/fetch/$s_!Rkwf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Rkwf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png" width="250" height="39" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:39,&quot;width&quot;:250,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;An example of an IDN homograph attack; the Latin letters \&quot;e\&quot; and \&quot;a\&quot; are replaced with the Cyrillic letters \&quot;&#1077;\&quot; and \&quot;&#1072;\&quot;.&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="An example of an IDN homograph attack; the Latin letters &quot;e&quot; and &quot;a&quot; are replaced with the Cyrillic letters &quot;&#1077;&quot; and &quot;&#1072;&quot;." title="An example of an IDN homograph attack; the Latin letters &quot;e&quot; and &quot;a&quot; are replaced with the Cyrillic letters &quot;&#1077;&quot; and &quot;&#1072;&quot;." srcset="https://substackcdn.com/image/fetch/$s_!Rkwf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png 424w, https://substackcdn.com/image/fetch/$s_!Rkwf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png 848w, https://substackcdn.com/image/fetch/$s_!Rkwf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png 1272w, https://substackcdn.com/image/fetch/$s_!Rkwf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F813dbde5-4dfc-44b1-b319-a628d1d85d74_250x39.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>This necessity to look beneath the surface reveals a universal principle: <em><strong>Trust the representation not the appearance</strong>.</em></p><h3>Revealing The Ink</h3><p>When the Master revealed the second character with the candle&#8217;s heat, he showed the novice a fundamental truth. The text seen by the eye is merely a <strong>glyph</strong>,  but the text seen by the machine is a sequence of <strong>code points</strong>.</p><p>To write robust code is to not be deceived by the visual form. One must apply the heat of <em><strong>normalization</strong></em> to reveal and align the true sequence of underlying code points. Only then can the comparison be honest and the measurement be true.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>A glyph is a picture representing a character in a language. You type a character on your keyboard, the glyph is what you see on the screen. Often one glyph corresponds to a character, but not always.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>&#8220;Unicode provides two concepts - canonical equivalence and compatibility. Code point sequences that are defined as <strong>canonically equivalent</strong> are assumed to have the same appearance and meaning when printed or displayed. Sequences that are defined as <strong>compatible</strong> are assumed to have possibly distinct appearances, but the same meaning in some contexts.&#8221; - <a href="https://en.wikipedia.org/wiki/Unicode_equivalence">Source</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>&#8220;Grapheme clusters are the sequence of code points which users perceive as a single character. They are a best-effort approximation that can be determined programmatically and unambiguously.&#8221; - <a href="https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries">Source</a></p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p>Control Characters are fascinating, and I encourage you to read more about their history. They are used to &#8220;cause effects other than the addition of a symbol to the text&#8221;. For example, the 0x07 (<a href="https://en.wikipedia.org/wiki/Bell_character">bell</a>, BEL, \a, ^G) character in ASCII &#8220;may cause the device to emit a warning such as a bell or beep sound&#8221;.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p>Source - https://en.wikipedia.org/wiki/IDN_homograph_attack</p><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;b6fb2b44-849e-46bf-9aa0-0a7176d7c34a&quot;,&quot;caption&quot;:&quot;The Master asked the young cook &#8220;Where is the millet for the morning congee?&#8221;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 14: The Missing Grain&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-10-04T00:00:42.797Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!-dpr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-14-the-missing-grain&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:175007734,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></div></div>]]></content:encoded></item><item><title><![CDATA[Koan 14: The Missing Grain]]></title><description><![CDATA[When distributing python package_data goes wrong]]></description><link>https://pythonkoans.substack.com/p/koan-14-the-missing-grain</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-14-the-missing-grain</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Sat, 04 Oct 2025 00:00:42 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!-dpr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-dpr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-dpr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-dpr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-dpr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-dpr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-dpr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg" width="1024" height="574" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:574,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:158293,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/175007734?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!-dpr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg 424w, https://substackcdn.com/image/fetch/$s_!-dpr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg 848w, https://substackcdn.com/image/fetch/$s_!-dpr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!-dpr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc4a7738b-0eb2-43c0-a108-56ce217c3147_1024x574.jpeg 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The Master asked the young cook &#8220;Where is the millet for the morning congee?&#8221;</p><p>The cook gestured to the open sack. &#8220;It is there Master where it has always been.&#8221;</p><p>The Master reached into the sack but pulled out only dust. &#8220;When the sack is tied and carried to the marketplace, the millet must travel with it. The sack itself is but a suggestion of grain.&#8221;</p><p>The cook lowered his eyes. &#8220;I forgot to check the sack.&#8221;</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><h3>The Python Packaging Ecosystem</h3><p>In Python projects, code is rarely enough on its own. Configuration files, database schemas, assets, and binaries often need to accompany it. These files are what allow code to function correctly in real environments.</p><p>When working directly from a source tree, all files are accessible through the filesystem. But when you build a package into a wheel or source distribution and install it elsewhere, only the files you explicitly include are carried forward. Any undeclared files vanish in the process.</p><p>The governing principle is the <em>package manifest</em>. If non-code files are required, you must declare them so the build system knows to include them. Without this, your project risks arriving at its destination empty-handed.</p><div><hr></div><h3>Part 1: The Initial Oversight</h3><p>Suppose you begin with a project that reads a configuration file:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YSkK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YSkK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!YSkK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!YSkK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!YSkK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YSkK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:214520,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/175007734?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YSkK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!YSkK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!YSkK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!YSkK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F357e8741-c22b-40f2-b83b-a7b026cb69e3_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><code>logic.py</code> might try to access <code>defaults.yaml</code>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sbZQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sbZQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!sbZQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!sbZQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!sbZQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!sbZQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:251866,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/175007734?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!sbZQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!sbZQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!sbZQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!sbZQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2b61e80-fd16-47a8-b3ca-b6494c9f9d0e_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This works only if you run the script from the project root. Change the working directory and it breaks. Reliance on the current directory is fragile.</p><div><hr></div><h3>Part 2: Editable Installs</h3><p>During development, many use <em>editable installs</em>. Running:</p><pre><code>pip install -e .</code></pre><p>places a reference to your source tree in <code>site-packages</code>. Imports resolve against the live code, so changes take effect immediately without reinstalling.</p><p>This approach removes the need to run from the project root. But when you distribute the package, if <code>defaults.yaml</code> was never declared as package data, users installing it elsewhere will find that Python cannot locate the file.</p><h3>Part 3: Using<strong> </strong><code>importlib.resources</code></h3><p>The recommended way to access package data is <code>importlib.resources</code> (or its backport for older Python versions). It looks up resources relative to the package, independent of how or where it is installed.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!I5zX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!I5zX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png 424w, https://substackcdn.com/image/fetch/$s_!I5zX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png 848w, https://substackcdn.com/image/fetch/$s_!I5zX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png 1272w, https://substackcdn.com/image/fetch/$s_!I5zX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!I5zX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png" width="1456" height="726" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:726,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:296132,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/175007734?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!I5zX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png 424w, https://substackcdn.com/image/fetch/$s_!I5zX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png 848w, https://substackcdn.com/image/fetch/$s_!I5zX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png 1272w, https://substackcdn.com/image/fetch/$s_!I5zX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4b7a1708-3192-451d-a890-a521cc585cb8_1536x766.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This resolves the path issue. But it does not solve the packaging problem: if <code>defaults.yaml</code> is not bundled into the distribution, it still won&#8217;t be present in the installed package.</p><div><hr></div><h3>Part 4: Declaring Resources</h3><p>To ensure resources travel with your package, you must declare them in your build configuration. By default, only Python source files are included.</p><p>Below are minimal <code>pyproject.toml</code> snippets showing how to include <code>*.yaml</code> files using <a href="https://setuptools.pypa.io/en/latest/setuptools.html">setuptools</a> and <a href="https://hatch.pypa.io/latest/config/build/#build-system">hatchling</a>:</p><h4>Setuptools</h4><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gO3U!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gO3U!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png 424w, https://substackcdn.com/image/fetch/$s_!gO3U!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png 848w, https://substackcdn.com/image/fetch/$s_!gO3U!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png 1272w, https://substackcdn.com/image/fetch/$s_!gO3U!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gO3U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png" width="1372" height="624" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:624,&quot;width&quot;:1372,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:193465,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/175007734?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gO3U!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png 424w, https://substackcdn.com/image/fetch/$s_!gO3U!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png 848w, https://substackcdn.com/image/fetch/$s_!gO3U!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png 1272w, https://substackcdn.com/image/fetch/$s_!gO3U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb72c44f6-ca42-4805-b6a1-14c23b57a8f0_1372x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4>Hatchling</h4><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aYbd!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aYbd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png 424w, https://substackcdn.com/image/fetch/$s_!aYbd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png 848w, https://substackcdn.com/image/fetch/$s_!aYbd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png 1272w, https://substackcdn.com/image/fetch/$s_!aYbd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!aYbd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png" width="1372" height="624" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:624,&quot;width&quot;:1372,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:186005,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/175007734?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!aYbd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png 424w, https://substackcdn.com/image/fetch/$s_!aYbd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png 848w, https://substackcdn.com/image/fetch/$s_!aYbd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png 1272w, https://substackcdn.com/image/fetch/$s_!aYbd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0727a15a-1d58-4e85-aad1-ca8f05f9509a_1372x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Both achieve the same effect: <code>defaults.yaml</code> is bundled into the wheel and available through <code>importlib.resources</code>.</p><div><hr></div><h3>Part 5: Namespace Packages</h3><p>With implicit namespace packages (PEP 420), parts of a namespace can be spread across multiple distributions. Such packages omit an <code>__init__.py</code> in the top-level directory, enabling a flat layout as we learnt in <a href="https://pythonkoans.substack.com/p/koan-7-the-unburdened-village">Koan 7</a>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZoQT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZoQT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png 424w, https://substackcdn.com/image/fetch/$s_!ZoQT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png 848w, https://substackcdn.com/image/fetch/$s_!ZoQT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png 1272w, https://substackcdn.com/image/fetch/$s_!ZoQT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZoQT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png" width="1372" height="624" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:624,&quot;width&quot;:1372,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:179078,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/175007734?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZoQT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png 424w, https://substackcdn.com/image/fetch/$s_!ZoQT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png 848w, https://substackcdn.com/image/fetch/$s_!ZoQT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png 1272w, https://substackcdn.com/image/fetch/$s_!ZoQT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9ef715b4-ee05-42e2-b28a-fb0448fa62f2_1372x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here, <code>mycompany</code> is an implicit namespace shared by two subpackages. To ensure <code>defaults.yaml</code> travels with <code>mycompany.analytics</code>, declare it under that subpackage.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0dFk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0dFk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png 424w, https://substackcdn.com/image/fetch/$s_!0dFk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png 848w, https://substackcdn.com/image/fetch/$s_!0dFk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png 1272w, https://substackcdn.com/image/fetch/$s_!0dFk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0dFk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png" width="1372" height="624" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:624,&quot;width&quot;:1372,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:200030,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/175007734?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!0dFk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png 424w, https://substackcdn.com/image/fetch/$s_!0dFk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png 848w, https://substackcdn.com/image/fetch/$s_!0dFk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png 1272w, https://substackcdn.com/image/fetch/$s_!0dFk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56a9a2f2-e785-402a-9ffc-284edb1e75a6_1372x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This guarantees that only <code>mycompany.analytics</code> carries <code>defaults.yaml</code>, while <code>mycompany.ml</code> remains unaffected.</p><h3>Shipping The Millet</h3><p>The package manifest is the measure of completeness. If you omit declarations, your distribution will carry only dust. When crafting Python packages, verify that every essential file (code or data) travels with it.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-14-the-missing-grain?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! If you enjoyed this post, share it with your friends!</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-14-the-missing-grain?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://pythonkoans.substack.com/p/koan-14-the-missing-grain?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;69165189-580b-4f35-be34-08c2a3dcd156&quot;,&quot;caption&quot;:&quot;In monasteries bowls are often used for meditation rituals. Some are empty, others hold offerings: coins, water, and small tokens of care. In Python, dataclasses behave much like these bowls.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 13: The Empty Bowl&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-09-24T00:01:18.803Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!9qv7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-13-the-empty-bowl&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:170840236,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:4,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Koan 13: The Empty Bowl]]></title><description><![CDATA[Understanding Python dataclasses and how fields determine equality and hashing.]]></description><link>https://pythonkoans.substack.com/p/koan-13-the-empty-bowl</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-13-the-empty-bowl</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Wed, 24 Sep 2025 00:01:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!9qv7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9qv7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9qv7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png 424w, https://substackcdn.com/image/fetch/$s_!9qv7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png 848w, https://substackcdn.com/image/fetch/$s_!9qv7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png 1272w, https://substackcdn.com/image/fetch/$s_!9qv7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9qv7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png" width="1456" height="1523" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1523,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:233791,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!9qv7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png 424w, https://substackcdn.com/image/fetch/$s_!9qv7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png 848w, https://substackcdn.com/image/fetch/$s_!9qv7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png 1272w, https://substackcdn.com/image/fetch/$s_!9qv7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F35067486-bcc0-4e38-9e6b-52a47cfae099_1470x1538.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In monasteries bowls are often used for meditation rituals. Some are empty, others hold offerings: coins, water, and small tokens of care. In Python, dataclasses behave much like these bowls. </p><p>Each dataclass instance is a bowl; the data it carries are the offerings inside. How Python evaluates equality and hashing depends on both the contents and the form of the bowl itself.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3>Part 1: What is a Dataclass?  </h3><p>Dataclasses, introduced in Python 3.7, are a convenience feature. They save you from writing boilerplate code when you need simple classes that hold data.  </p><p>For example, without dataclasses you might write:  </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!5F9B!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5F9B!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png 424w, https://substackcdn.com/image/fetch/$s_!5F9B!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png 848w, https://substackcdn.com/image/fetch/$s_!5F9B!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png 1272w, https://substackcdn.com/image/fetch/$s_!5F9B!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5F9B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png" width="1456" height="806" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:806,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:120251,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!5F9B!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png 424w, https://substackcdn.com/image/fetch/$s_!5F9B!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png 848w, https://substackcdn.com/image/fetch/$s_!5F9B!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png 1272w, https://substackcdn.com/image/fetch/$s_!5F9B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cbae8d0-a4c0-49d6-8e4a-99637698c9e6_1470x814.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And with a dataclass it becomes:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YkAl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YkAl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png 424w, https://substackcdn.com/image/fetch/$s_!YkAl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png 848w, https://substackcdn.com/image/fetch/$s_!YkAl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png 1272w, https://substackcdn.com/image/fetch/$s_!YkAl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!YkAl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png" width="1456" height="555" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:555,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:53049,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!YkAl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png 424w, https://substackcdn.com/image/fetch/$s_!YkAl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png 848w, https://substackcdn.com/image/fetch/$s_!YkAl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png 1272w, https://substackcdn.com/image/fetch/$s_!YkAl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbc2edb06-eced-40a5-b2a8-a50357118b23_1470x560.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Python automatically creates the <code>__init__</code>, <code>__eq__</code>, and <code>__repr__</code> functions for you when you use the dataclass decorator. </p><h3>Part 2: The Empty Bowl</h3><p>Consider a bowl with no marked offerings:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OUI9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OUI9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png 424w, https://substackcdn.com/image/fetch/$s_!OUI9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png 848w, https://substackcdn.com/image/fetch/$s_!OUI9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png 1272w, https://substackcdn.com/image/fetch/$s_!OUI9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OUI9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png" width="1456" height="555" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:555,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:57522,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!OUI9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png 424w, https://substackcdn.com/image/fetch/$s_!OUI9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png 848w, https://substackcdn.com/image/fetch/$s_!OUI9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png 1272w, https://substackcdn.com/image/fetch/$s_!OUI9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9f7d793b-a10d-46d0-9315-cb432453fb40_1470x560.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Although values are assigned on the class, there are no annotated fields. When Python evaluates this bowl:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1fBi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1fBi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png 424w, https://substackcdn.com/image/fetch/$s_!1fBi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png 848w, https://substackcdn.com/image/fetch/$s_!1fBi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png 1272w, https://substackcdn.com/image/fetch/$s_!1fBi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1fBi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png" width="1456" height="386" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/add82696-e967-4684-89c2-c009a6f2d615_1470x390.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:386,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54716,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1fBi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png 424w, https://substackcdn.com/image/fetch/$s_!1fBi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png 848w, https://substackcdn.com/image/fetch/$s_!1fBi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png 1272w, https://substackcdn.com/image/fetch/$s_!1fBi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fadd82696-e967-4684-89c2-c009a6f2d615_1470x390.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Only attributes declared with annotations are considered the recognized contents of the bowl, contributing to equality and hash calculations. Adding type annotations transforms the bowl:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EDHo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EDHo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png 424w, https://substackcdn.com/image/fetch/$s_!EDHo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png 848w, https://substackcdn.com/image/fetch/$s_!EDHo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png 1272w, https://substackcdn.com/image/fetch/$s_!EDHo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!EDHo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png" width="1456" height="469" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/695a6260-4426-4788-aa45-acf54753baa4_1470x474.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:469,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:46451,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!EDHo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png 424w, https://substackcdn.com/image/fetch/$s_!EDHo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png 848w, https://substackcdn.com/image/fetch/$s_!EDHo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png 1272w, https://substackcdn.com/image/fetch/$s_!EDHo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F695a6260-4426-4788-aa45-acf54753baa4_1470x474.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Now the offerings are acknowledged, and hashing reflects their presence. Two bowls with identical annotated fields are equal, and their hashes correspond to their contents.</p><h3>Part 2: Comparing Different Bowls</h3><p>Next, imagine two bowls, each holding the same offerings:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!58R5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!58R5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png 424w, https://substackcdn.com/image/fetch/$s_!58R5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png 848w, https://substackcdn.com/image/fetch/$s_!58R5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png 1272w, https://substackcdn.com/image/fetch/$s_!58R5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!58R5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png" width="1456" height="681" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:681,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:78656,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!58R5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png 424w, https://substackcdn.com/image/fetch/$s_!58R5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png 848w, https://substackcdn.com/image/fetch/$s_!58R5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png 1272w, https://substackcdn.com/image/fetch/$s_!58R5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4a3e5dfc-b406-4e66-9e1d-7b1fbd1f257c_1470x688.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The bowls may contain identical coins and water, yet they differ in form. Python compares both the contents and the type of the object:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4nzY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4nzY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png 424w, https://substackcdn.com/image/fetch/$s_!4nzY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png 848w, https://substackcdn.com/image/fetch/$s_!4nzY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png 1272w, https://substackcdn.com/image/fetch/$s_!4nzY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!4nzY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png" width="1456" height="428" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:428,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:59270,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!4nzY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png 424w, https://substackcdn.com/image/fetch/$s_!4nzY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png 848w, https://substackcdn.com/image/fetch/$s_!4nzY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png 1272w, https://substackcdn.com/image/fetch/$s_!4nzY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82bb997b-08ce-4d8f-85cc-584a2b849880_1470x432.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Equality requires both the offerings and the vessel to match. Hashing, on the other hand, considers only the annotated fields.</p><h3>Part 3: Fields vs Class Variables</h3><p>The distinction between annotated fields and class variables is crucial. Only annotated fields are considered offerings within the bowl. Class variables exist on the outside: they do not contribute to equality or hashing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XUcj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XUcj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png 424w, https://substackcdn.com/image/fetch/$s_!XUcj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png 848w, https://substackcdn.com/image/fetch/$s_!XUcj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png 1272w, https://substackcdn.com/image/fetch/$s_!XUcj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XUcj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png" width="1456" height="511" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/eef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:511,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:72243,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!XUcj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png 424w, https://substackcdn.com/image/fetch/$s_!XUcj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png 848w, https://substackcdn.com/image/fetch/$s_!XUcj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png 1272w, https://substackcdn.com/image/fetch/$s_!XUcj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Feef8cce3-4a77-4219-96ca-b508ce92e118_1470x516.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><div><hr></div><h3>Part 4: Mutable vs Frozen Dataclasses</h3><p>You may have noticed that we are delcaring classes with <code>frozen=True. </code>Dataclasses can be created <strong>mutable</strong> or <strong>frozen</strong>:</p><ul><li><p><strong>Mutable dataclasses</strong> allow their contents to change after creation. This is the default.</p></li><li><p><strong>Frozen dataclasses</strong> make the contents immutable, like sealing the offerings inside a bowl.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aCJO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aCJO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png 424w, https://substackcdn.com/image/fetch/$s_!aCJO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png 848w, https://substackcdn.com/image/fetch/$s_!aCJO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png 1272w, https://substackcdn.com/image/fetch/$s_!aCJO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!aCJO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png" width="1456" height="681" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:681,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:72783,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!aCJO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png 424w, https://substackcdn.com/image/fetch/$s_!aCJO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png 848w, https://substackcdn.com/image/fetch/$s_!aCJO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png 1272w, https://substackcdn.com/image/fetch/$s_!aCJO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03d024b3-a1d0-4c25-8854-5b6197e75e22_1470x688.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Frozenness also affects hashability.  Only frozen dataclasses are hashable by default, because mutable bowls could change after being placed in a set or used as dict keys.</p><p>In <a href="https://pythonkoans.substack.com/p/koan-8-the-shifting-seal">Koan 8</a> we learnt that the hashability of a class is determined by the implementation of the <code>__hash__ </code>function. When a dataclass is declared frozen, Python automatically creates a <code>__hash__ </code>function for you.</p><div><hr></div><h3>Part 5: Default Values and Factories</h3><p>Default values make bowls easier to create without specifying every offering:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nzzZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nzzZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png 424w, https://substackcdn.com/image/fetch/$s_!nzzZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png 848w, https://substackcdn.com/image/fetch/$s_!nzzZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png 1272w, https://substackcdn.com/image/fetch/$s_!nzzZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nzzZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png" width="1456" height="469" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:469,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:44571,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nzzZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png 424w, https://substackcdn.com/image/fetch/$s_!nzzZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png 848w, https://substackcdn.com/image/fetch/$s_!nzzZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png 1272w, https://substackcdn.com/image/fetch/$s_!nzzZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6c8f8b1-2379-4dd1-a60f-d7064c3b3dc3_1470x474.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>For mutable fields like lists or dictionaries, a <strong>default factory</strong> is necessary. Using a default argument with a mutable object can lead to <strong>shared state</strong> between instances:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fpOK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fpOK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png 424w, https://substackcdn.com/image/fetch/$s_!fpOK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png 848w, https://substackcdn.com/image/fetch/$s_!fpOK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png 1272w, https://substackcdn.com/image/fetch/$s_!fpOK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fpOK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png" width="1456" height="469" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:469,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:51787,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fpOK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png 424w, https://substackcdn.com/image/fetch/$s_!fpOK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png 848w, https://substackcdn.com/image/fetch/$s_!fpOK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png 1272w, https://substackcdn.com/image/fetch/$s_!fpOK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff8e3fb0e-ab75-43ad-9bf2-0f60a51bb9ec_1470x474.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This is because default arguments are evaluated once at definition time, not execution time, as we learnt in <a href="https://pythonkoans.substack.com/p/koan-3-the-ringing-bell">Koan 3</a>.</p><p>Instead, a <code>default_factory</code> creates a <strong>new object for each instance</strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tK_p!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tK_p!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png 424w, https://substackcdn.com/image/fetch/$s_!tK_p!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png 848w, https://substackcdn.com/image/fetch/$s_!tK_p!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png 1272w, https://substackcdn.com/image/fetch/$s_!tK_p!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!tK_p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png" width="1456" height="511" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/056f3849-5874-4770-855a-8dad0a50c996_1470x516.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:511,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:58978,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170840236?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!tK_p!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png 424w, https://substackcdn.com/image/fetch/$s_!tK_p!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png 848w, https://substackcdn.com/image/fetch/$s_!tK_p!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png 1272w, https://substackcdn.com/image/fetch/$s_!tK_p!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F056f3849-5874-4770-855a-8dad0a50c996_1470x516.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Now each bowl has its own independent list of offerings. Python calls the factory function at the time the instance is created, ensuring the contents of each bowl remain separate.</p><p>This distinction prevents subtle bugs and preserves the integrity of each bowl&#8217;s contents.</p><div><hr></div><h3>Offering the Bowl</h3><p>A bowl without marked offerings is indistinguishable from another empty bowl of the same type. Two bowls may contain identical offerings, yet remain separate if their forms differ. Hashing depends only on the contents, while equality considers both the contents and the form.</p><p>Through careful attention to fields, mutability, defaults, and the auto-generated methods, dataclasses provide a simple, predictable structure for Python data objects.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;272ef012-120e-4364-948d-f1bc8c3d38b0&quot;,&quot;caption&quot;:&quot;The Peril of Unquoted Arguments&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 12: The Blacksmith's Hammer&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-09-15T21:01:08.257Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!vTd7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-12-the-blacksmiths-hammer&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:173651799,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:1,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Koan 12: The Blacksmith's Hammer]]></title><description><![CDATA[Exploring the dangerous power of unquoted Python strings, and how they caused CVE-2024-9287]]></description><link>https://pythonkoans.substack.com/p/koan-12-the-blacksmiths-hammer</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-12-the-blacksmiths-hammer</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Mon, 15 Sep 2025 21:01:08 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!vTd7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vTd7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vTd7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png 424w, https://substackcdn.com/image/fetch/$s_!vTd7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png 848w, https://substackcdn.com/image/fetch/$s_!vTd7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png 1272w, https://substackcdn.com/image/fetch/$s_!vTd7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vTd7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png" width="1456" height="1124" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1124,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:591609,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173651799?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vTd7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png 424w, https://substackcdn.com/image/fetch/$s_!vTd7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png 848w, https://substackcdn.com/image/fetch/$s_!vTd7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png 1272w, https://substackcdn.com/image/fetch/$s_!vTd7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5dee58aa-3407-4e39-8701-e68e92db04a1_1536x1186.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>The Peril of Unquoted Arguments</strong></h3><p>We often have the need to run commands in <em><strong>shells<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-1" href="#footnote-1" target="_self">1</a> </strong></em>using Python. <a href="https://docs.python.org/3/library/subprocess.html">Subprocess</a> is a cross-platform<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-2" href="#footnote-2" target="_self">2</a> python module which helps you do this.</p><p>Shells commands are separated by <em><strong>command delimiters</strong></em> (such as <code>&#8216;;&#8217;</code> <code>&#8216;&amp;&amp;&#8217;</code> <code>&#8216;||&#8217;</code> and <code>&#8216;\n&#8217;</code> in POSIX<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-3" href="#footnote-3" target="_self">3</a><code>)</code>. <em><strong>Argument delimiters</strong></em> on the other hand define how a single command&#8217;s arguments are split. On POSIX-compliant systems the <code>IFS</code><a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-4" href="#footnote-4" target="_self">4</a><code> </code>environment variable defines the characters used to split arguments. By default, IFS is set to split on spaces, newlines and tabs.</p><p>When a path or argument to a command contains a space, the shell does not see a single continuous entity. It sees two distinct things. A single path has become two arguments.</p><p>Let us begin with a simple example.</p><h3><strong>Part 1: The Space as a Separator</strong></h3><p>Consider the creation of a directory with a space in its name.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WQvo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WQvo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!WQvo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!WQvo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!WQvo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WQvo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:405929,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173651799?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WQvo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!WQvo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!WQvo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!WQvo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F565e57f6-1a96-4f58-b60f-320daecf26d9_1536x624.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When we use the <code>os</code> module it understands the path as a single string because it does not involve the shell's interpretation. The directory is created as intended with a space in its name.</p><p>Now let us use the <code>subprocess</code> module with the <code>shell=True</code> flag. This flag instructs Python to pass our command to the shell for execution as a single string.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!geRb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!geRb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!geRb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!geRb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!geRb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!geRb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:411335,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173651799?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!geRb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!geRb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!geRb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!geRb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fccca0d7c-913a-43b7-941d-56217aa924d7_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When this code runs, the shell sees the command as <code>mkdir my new path</code>. The shell interprets this as a command to create a directory named <code>my</code> a second directory named <code>new</code> and a third named <code>path</code>. The single path becomes three paths.</p><h3><strong>Part 2: The Command Injection</strong></h3><p>The danger is not only in misinterpretation but also in <strong>malicious injection</strong>.</p><p>Consider if the path came from an external source such as a user defined argument for example.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!2JNI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!2JNI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!2JNI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!2JNI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!2JNI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!2JNI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/aec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:397522,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173651799?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!2JNI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!2JNI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!2JNI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!2JNI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Faec13524-19af-4a6b-b52a-d6d43fd88054_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The shell sees <code>mkdir my; rm -rf /</code>. The semicolon is a command separator in the shell. The shell will first execute <code>mkdir my</code> and then it will execute <code>rm -rf /</code> which deletes the root directory.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>The unquoted path has allowed the user to inject a new command. This is a profound and dangerous failure of boundary. A simple space or semicolon can shatter the integrity of the system.</p><h3><strong>Part 3: The Principle of Quoting</strong></h3><p>To prevent this we must use <em><strong>quoting</strong></em>. Quoting places a protective barrier around the string telling the shell to treat it as a single unit regardless of its contents.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Rgis!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Rgis!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!Rgis!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!Rgis!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!Rgis!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Rgis!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:394380,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173651799?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Rgis!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!Rgis!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!Rgis!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!Rgis!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9dd6da37-edf9-4414-b21c-c7df19e2643a_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The shell now sees <code>mkdir "my; rm -rf /"</code>. The entire string is treated as a single argument for <code>mkdir</code>. No new directories are created. No commands are executed. The semicolon is rendered harmless a mere character within the string.</p><h3><strong>Part 4: The Path of Wisdom</strong></h3><p>The wise path is the one that avoids the shell entirely when not needed. Most linters (like <a href="https://docs.astral.sh/ruff/">ruff</a>) will <a href="https://docs.astral.sh/ruff/rules/subprocess-popen-with-shell-equals-true/">detect this</a> for you.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ybL2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ybL2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!ybL2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!ybL2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!ybL2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ybL2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:404874,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173651799?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ybL2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!ybL2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!ybL2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!ybL2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bbf0494-65b4-4a87-8f85-c740cf5527ec_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here we pass a list of arguments to <code>subprocess.run</code>. Python does not pass a single string to the shell. Instead it executes <code>mkdir</code> directly as a separate process and passes <code>user_input</code> as its first argument. The shell is never involved and the risk is eliminated.</p><p>This is the preferred way. It is clean and safe.</p><h4>Part 5: A Real-World Command Injection (CVE-2024-9287)</h4><p>Command Injection is not just a theoretical problem. Last year, a <a href="https://www.cvedetails.com/cve/CVE-2024-9287/">high severity vulnerability</a> was found to affect all Python versions &lt;= 3.13:</p><blockquote><p>A vulnerability has been found in the CPython `venv` module and CLI where path names provided when creating a virtual environment were not quoted properly, allowing the creator to inject commands into virtual environment "activation" scripts (ie "source venv/bin/activate"). This means that attacker-controlled virtual environments are able to run commands when the virtual environment is activated. Virtual environments which are not created by an attacker or which aren't activated before being used (ie "./venv/bin/python") are not affected.</p></blockquote><p>Previously, when a virtual environment was created, the activation scripts (<code>activate</code>, <code>activate.bat</code>, etc.) would use the environment name provided by the user to construct the <code>venv</code> path without enclosing it in quotation marks. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!memv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!memv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png 424w, https://substackcdn.com/image/fetch/$s_!memv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png 848w, https://substackcdn.com/image/fetch/$s_!memv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png 1272w, https://substackcdn.com/image/fetch/$s_!memv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!memv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png" width="1456" height="726" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:726,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:512125,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173651799?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!memv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png 424w, https://substackcdn.com/image/fetch/$s_!memv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png 848w, https://substackcdn.com/image/fetch/$s_!memv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png 1272w, https://substackcdn.com/image/fetch/$s_!memv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe1ecf6dd-6e0e-49ca-a8d0-09862e75451c_1536x766.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>For example, a name like <code>my test venv</code> would be written into the script as <code>/home/user/my test venv</code>. An attacker could craft a virtual environment name like <code>my-venv-with-space-and-command; malicious_command</code> which would be interpreted by the shell as a path followed by an additional command to execute.</p><p>The fix<a class="footnote-anchor" data-component-name="FootnoteAnchorToDOM" id="footnote-anchor-5" href="#footnote-5" target="_self">5</a> (see summarized code below) was to ensure that all paths written into the <code>venv</code> activation scripts are properly <em><strong>quoted </strong></em>using the <code>shlex</code> module. The fix uses <code>shlex.quote</code> to ensure that any special characters or spaces in the path are escaped or enclosed in single quotes. This prevents the shell from misinterpreting the path as separate arguments or commands.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZZrN!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZZrN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png 424w, https://substackcdn.com/image/fetch/$s_!ZZrN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png 848w, https://substackcdn.com/image/fetch/$s_!ZZrN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png 1272w, https://substackcdn.com/image/fetch/$s_!ZZrN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZZrN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png" width="1456" height="1350" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1350,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:683849,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173651799?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ZZrN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png 424w, https://substackcdn.com/image/fetch/$s_!ZZrN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png 848w, https://substackcdn.com/image/fetch/$s_!ZZrN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png 1272w, https://substackcdn.com/image/fetch/$s_!ZZrN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff323da82-fd5c-4add-9a57-afb99f348a3a_1536x1424.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4>Forging the Blade</h4><p>The Master Blacksmith&#8217;s lesson was simple. Just as a piece of metal may appear to be a single piece of steel, but splits into shards when struck by a hammer; unquoted command strings are split into different arguments or commands by the shell.</p><p>When constructing commands in Python:</p><ul><li><p>Avoid <code>shell=True</code> and use <code>subprocess.run([&#8230;])</code> instead</p></li><li><p>If you must use <code>subprocess</code> with <code>shell=True</code>, quote the command string</p></li><li><p>When constructing shell commands outside of <code>subprocess,</code> use <code>shlex</code> to avoid command injection from untrusted input.</p></li></ul><p>The blacksmith does not strike a piece of steel without thought. So too should the developer not pass a path to the shell without care. </p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-12-the-blacksmiths-hammer?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! If you enjoyed this post, share it with your friends :)</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-12-the-blacksmiths-hammer?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://pythonkoans.substack.com/p/koan-12-the-blacksmiths-hammer?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-1" href="#footnote-anchor-1" class="footnote-number" contenteditable="false" target="_self">1</a><div class="footnote-content"><p>A <em><strong>shell</strong> </em>is a program that provides an interface between the user and the operating system (OS). It&#8217;s called a <em>&#8220;shell&#8221;</em> because it surrounds the kernel (the &#8220;core&#8221;) and lets you interact with it. The shell takes <em><strong>commands</strong></em> (from your keyboard, a script, or another program), interprets them, and asks the OS to run the corresponding programs or built-in functions.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-2" href="#footnote-anchor-2" class="footnote-number" contenteditable="false" target="_self">2</a><div class="footnote-content"><p>The <code>subprocess</code> module is available on all platforms <em><strong>except</strong></em> mobile (i.e. Android, iOS) and webassembly (i.e. WASI).</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-3" href="#footnote-anchor-3" class="footnote-number" contenteditable="false" target="_self">3</a><div class="footnote-content"><p>POSIX is an IEEE standard (IEEE 1003) defining a common API and shell behavior for Unix-like systems. It ensures that programs and scripts written on one POSIX-compliant system will work on another.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-4" href="#footnote-anchor-4" class="footnote-number" contenteditable="false" target="_self">4</a><div class="footnote-content"><p>IFS can be made to split on other characters by changing it&#8217;s value before running a command. For example: <code>IFS=, read a b c &lt;&lt;&lt; "one,two,three"; echo "$a | $b | $c"</code> will split the comma-delimited string into the three variables a, b and c.</p></div></div><div class="footnote" data-component-name="FootnoteToDOM"><a id="footnote-5" href="#footnote-anchor-5" class="footnote-number" contenteditable="false" target="_self">5</a><div class="footnote-content"><p>Because the issue affected all versions of Python, a patch was created for all 3.x versions. <a href="https://github.com/python/cpython/commit/8450b2482586857d689b6658f08de9c8179af7db#diff-bcc6e36b2a636da9443a637b6c16d09c90225eedbf058cdaba308b8f963c859f">The commit diff for Python 3.12 can be found here</a>.</p><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;856adcfd-524d-4572-90e7-82ab49916013&quot;,&quot;caption&quot;:&quot;Last week we discovered a new tool to inspect Python programs. This week, we shall use it to understand what is happening inside list comprehensions between Python 3.10 and Python 3.12.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 11: The Flowing River (Part 2)&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-09-09T00:01:18.355Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!OF07!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-11-the-flowing-river-part-2&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:173081451,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:4,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div></div></div>]]></content:encoded></item><item><title><![CDATA[Koan 11: The Flowing River (Part 2)]]></title><description><![CDATA[Understanding how Python's list comprehensions work under the hood]]></description><link>https://pythonkoans.substack.com/p/koan-11-the-flowing-river-part-2</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-11-the-flowing-river-part-2</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Tue, 09 Sep 2025 00:01:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!OF07!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!OF07!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OF07!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png 424w, https://substackcdn.com/image/fetch/$s_!OF07!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png 848w, https://substackcdn.com/image/fetch/$s_!OF07!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png 1272w, https://substackcdn.com/image/fetch/$s_!OF07!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!OF07!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png" width="1456" height="1323" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1323,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:474267,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173081451?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!OF07!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png 424w, https://substackcdn.com/image/fetch/$s_!OF07!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png 848w, https://substackcdn.com/image/fetch/$s_!OF07!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png 1272w, https://substackcdn.com/image/fetch/$s_!OF07!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcb2ca996-23d3-4f7e-8f8b-97fc83b89e8b_1536x1396.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p><a href="https://pythonkoans.substack.com/p/koan-10-the-flowing-river-part-1">Last week</a> we <a href="https://docs.python.org/3/library/dis.html">dis</a>covered a new tool to inspect Python programs. This week, we shall use it to understand what is happening inside list comprehensions between Python 3.10 and Python 3.12.</p><h3>A Gentle Reminder</h3><p>The CPython virtual machine is a <em><strong>stack-based machine</strong></em>. This means it performs most of its operations by pushing and popping values onto a data structure called the <strong>stack</strong>.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p><code>dis.dis</code> disassembles Python code into the individual bytecode instructions used by the interpreter to operate on the stack. For example:</p><ul><li><p>Instructions like <code>LOAD_FAST</code> or <code>LOAD_CONST</code> push values onto the stack.</p></li><li><p>Instructions like <code>BINARY_ADD</code> or <code>CALL_FUNCTION</code> pop values from the stack to perform an operation and then push the result back.</p></li></ul><p>This allows us to infer the state of the stack at each step.</p><h3>Part 3: Python 3.10: The Old Way</h3><p>Let&#8217;s start with a simple example: <code>[x for x in range(5)]</code></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vslm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vslm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png 424w, https://substackcdn.com/image/fetch/$s_!vslm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png 848w, https://substackcdn.com/image/fetch/$s_!vslm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png 1272w, https://substackcdn.com/image/fetch/$s_!vslm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vslm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png" width="1456" height="1283" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1283,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:469709,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173081451?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vslm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png 424w, https://substackcdn.com/image/fetch/$s_!vslm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png 848w, https://substackcdn.com/image/fetch/$s_!vslm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png 1272w, https://substackcdn.com/image/fetch/$s_!vslm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4cf80180-acc1-4c0d-9ce1-28736a0f063f_1536x1354.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When we observe the output, we can see two sections. The first refers to the outer code (or main program), but what about the second? This is actually a <em><strong>new hidden function </strong></em>that Python creates for the list comprehension. Let&#8217;s break down exactly what it does:</p><h4>The Outer Code (Main Program)</h4><p>This section shows what the main program does.</p><ul><li><p><code>0 LOAD_CONST 0 (&lt;code object &lt;listcomp&gt;...&gt;)</code>: Python first loads the compiled code for the list comprehension itself. It's a separate, self-contained piece of code.</p></li><li><p><code>2 LOAD_CONST 1 ('&lt;listcomp&gt;')</code>: Loads the name <code>&lt;listcomp&gt;</code> to identify the function.</p></li><li><p><code>4 MAKE_FUNCTION 0</code>: <em><strong>This is the crucial step</strong></em>. This instruction creates a new &#8220;hidden&#8221; function object from the code object loaded in the first step.</p></li><li><p><code>6 LOAD_NAME 0 (range)</code>: Loads the built-in <code>range</code> function.</p></li><li><p><code>8 LOAD_CONST 2 (5)</code>: Loads the constant value <code>5</code>.</p></li><li><p><code>10 CALL_FUNCTION 1</code>: Calls the <code>range</code> function with the argument <code>5</code> to create a range object.</p></li><li><p><code>12 GET_ITER</code>: Gets an iterator from the <code>range(5)</code> object.</p></li><li><p><code>14 CALL_FUNCTION 1</code>:  This calls the list comprehension function that was created earlier. The iterator from <code>range(5)</code> is passed to it as an argument.</p></li><li><p><code>16 RETURN_VALUE</code>: The function returns <code>None</code> to indicate completion.</p></li></ul><h4>The Inner Code (The List Comprehension Function)</h4><p>This is the actual "hidden" function that was created by Python to build the list. It's a separate, compiled block of code.</p><ul><li><p><code>0 BUILD_LIST 0</code>: Creates an empty list on the stack to hold the results of the comprehension.</p></li><li><p><code>2 LOAD_FAST 0 (.0)</code>: Loads the iterator that was passed into this function from the outer code. It's stored in a local variable named <code>.0</code>.</p></li><li><p><code>&gt;&gt; 4 FOR_ITER 4 (to 14)</code>: This is the start of the loop. It iterates over the loaded iterator. If there are no more items, it jumps to instruction <code>14</code> to exit the loop.</p></li><li><p><code>6 STORE_FAST 1 (x)</code>: The <code>FOR_ITER</code> instruction gets the next item from the iterator and stores it in a local variable named <code>x</code>.</p></li><li><p><code>8 LOAD_FAST 1 (x)</code>: Loads the value of <code>x</code> back onto the stack.</p></li><li><p><code>10 LIST_APPEND 2</code>: Appends the value on the top of the stack (which is <code>x</code>) to the list that was created in the first step. The <code>2</code> refers to the number of items it has to inspect on the stack.</p></li><li><p><code>12 JUMP_ABSOLUTE 2 (to 4)</code>: Jumps back to the top of the loop (<code>FOR_ITER</code>) to get the next item.</p></li><li><p><code>&gt;&gt; 14 RETURN_VALUE</code>: Once the loop is finished, this instruction returns the final list back to the outer code.</p></li></ul><p>Now we can begin to understand why the code in the original Koan might have failed. We&#8217;re getting a <code>NameError</code> because the list comprehension is being run within a hidden function, and creating it&#8217;s own scope which doesn&#8217;t know about the <code>river</code> variable.</p><h3>Part 4: Python 3.11: The New Way</h3><p>But why don&#8217;t we get the <code>NameError</code> in Python 3.12? </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WVD_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WVD_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png 424w, https://substackcdn.com/image/fetch/$s_!WVD_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png 848w, https://substackcdn.com/image/fetch/$s_!WVD_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png 1272w, https://substackcdn.com/image/fetch/$s_!WVD_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WVD_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png" width="1456" height="1350" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1350,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:458902,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173081451?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WVD_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png 424w, https://substackcdn.com/image/fetch/$s_!WVD_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png 848w, https://substackcdn.com/image/fetch/$s_!WVD_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png 1272w, https://substackcdn.com/image/fetch/$s_!WVD_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F84e0c434-3a93-44dc-872b-db0eea214d22_1536x1424.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Because the entire process happens within the main code block, without creating a hidden function. The process is:</p><ul><li><p><code>2 PUSH_NULL</code>: A <code>NULL</code> value is pushed to the stack. This is part of the new calling convention for functions in Python 3.11+.</p></li><li><p><code>4 LOAD_NAME 0 (range)</code> and <code>6 LOAD_CONST 0 (5)</code>: The <code>range</code> function and the integer <code>3</code> are loaded onto the stack.</p></li><li><p><code>8 CALL 1</code>: The <code>range</code> function is called with one argument,<code> 5</code>, returning a <code>range(5)</code> object.</p></li><li><p><code>16 GET_ITER</code>: An iterator is created from the <code>range(5)</code> object.</p></li><li><p><code>18 LOAD_FAST_AND_CLEAR 0 (x)</code>: This is a key instruction for the new approach. It efficiently handles the "isolation" of the loop variable <code>x</code>. If a variable named <code>x</code> already exists in this scope, its value is saved to the stack, and the local variable <code>x</code> is set to <code>NULL</code>. This "pushes" the clashing local variable out of the way.</p></li><li><p><code>20 SWAP 2</code> and <code>22 BUILD_LIST 0</code>: The <code>BUILD_LIST</code> instruction creates a new empty list. The <code>SWAP</code> instructions are used to organize the stack, ensuring the empty list and the iterator are in the correct positions for the loop to begin.</p></li><li><p><code>26 FOR_ITER 4 (to 38)</code>: The start of the loop. It gets the next item from the iterator and pushes it to the stack. If there are no more items, the loop ends, and execution jumps to line 38.</p></li><li><p><code>30 STORE_FAST 0 (x)</code>: The value from the iterator is stored into the local variable <code>x</code>. This is the loop variable.</p></li><li><p><code>32 LOAD_FAST 0 (x)</code> and <code>34 LIST_APPEND 2</code>: The value of <code>x</code> is loaded and then appended directly to the list.</p></li><li><p><code>36 JUMP_BACKWARD 6 (to 26)</code>: Jumps back to the top of the loop to get the next item.</p></li><li><p><code>38 END_FOR</code>: The loop is finished.</p></li><li><p><code>40 SWAP 2</code> and <code>42 STORE_FAST 0 (x)</code>: This is the <strong>"pop"</strong> part of the stack manipulation. The <code>SWAP</code> and <code>STORE_FAST</code> instructions restore the original value of <code>x</code> that was saved in step 18.</p></li><li><p>The remaining instructions handle printing the result and returning from the function.</p></li></ul><p>This disassembly clearly shows that there is no separate code block for the list comprehension. The entire process, from creating the iterator to building the list and appending items, happens in one continuous flow of instructions. </p><p>The use of <code>LOAD_FAST_AND_CLEAR</code> and <code>SWAP</code> instructions handles the necessary variable isolation without the overhead of creating an entirely new function frame. This change, known as <em><strong>Inlined Comprehensions</strong></em> was introduced in Python 3.12 with <a href="https://peps.python.org/pep-0709/">PEP 709</a>.</p><h3>Part 5: The Two List Comprehensions</h3><p>Now we can see exactly what happened in our original Koan. In Python 3.10:</p><ul><li><p><code>exec()</code> does not have access to the local scope of the surrounding code.</p></li><li><p>In the traceback, you can see a separate <code>&lt;listcomp&gt;</code> frame, which acts as a barrier.</p></li><li><p>The <code>exec("river*single_drop")</code> statement tries to find the variable <code>river</code> in its own scope (which is the <code>&lt;listcomp&gt;</code> function's scope) and then the global scope. It cannot access <code>river</code> from the <code>lambda</code>'s scope, leading to the <code>NameError</code>.</p></li></ul><p>In Python 3.12 and later, where the list comprehension is <em><strong>inlined</strong></em>:</p><ul><li><p>The list comprehension runs in the same frame as the surrounding <code>lambda</code> function.</p></li><li><p><code>exec()</code> can now access the local variables of the surrounding scope, including the variable <code>river</code>.</p></li><li><p>The code runs successfully, and since <code>exec()</code> returns <code>None</code> and the list comprehension produces a list containing <code>None</code>.</p></li></ul><h3>Part 6: Making it work on Python 3.10</h3><p>There is in fact a way to stop the error from occurring in Python 3.10. the <code>exec </code>function accepts an optional dictionary of <code>local</code> and or <code>global</code> variables. So we can explicitly provide the variables missing in the list comprehension scope. And we can use the trick we learnt in <a href="https://pythonkoans.substack.com/p/koan-5-the-silent-harp">Koan 5</a> to define and run the lambda in the one statement: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!bUiH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bUiH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png 424w, https://substackcdn.com/image/fetch/$s_!bUiH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png 848w, https://substackcdn.com/image/fetch/$s_!bUiH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png 1272w, https://substackcdn.com/image/fetch/$s_!bUiH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bUiH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png" width="1456" height="846" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:846,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:312572,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/173081451?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!bUiH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png 424w, https://substackcdn.com/image/fetch/$s_!bUiH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png 848w, https://substackcdn.com/image/fetch/$s_!bUiH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png 1272w, https://substackcdn.com/image/fetch/$s_!bUiH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffbac4345-68dc-4889-8978-c58eef9f6e81_1536x892.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Drinking the water</h3><p>Just as the water in one cup flowed through a sieve, and the other was sourced directly from the river; the difference between the two Python outputs is due to a change in how list comprehensions are implemented under the hood by CPython.</p><ul><li><p>In Python 3.10 list comprehension act as a separate, nested function.</p></li><li><p>In Python 3.12 and later, the list comprehension is inlined.</p></li></ul><p>While the two cups of water may appear identical, the methods used to obtain them are profoundly different.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-11-the-flowing-river-part-2?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! If you enjoyed this post, share it with your friends.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-11-the-flowing-river-part-2?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://pythonkoans.substack.com/p/koan-11-the-flowing-river-part-2?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div>]]></content:encoded></item><item><title><![CDATA[Koan 10: The Flowing River (Part 1)]]></title><description><![CDATA[Understanding how Python's list comprehensions work under the hood]]></description><link>https://pythonkoans.substack.com/p/koan-10-the-flowing-river-part-1</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-10-the-flowing-river-part-1</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Tue, 02 Sep 2025 03:29:58 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!6czw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6czw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6czw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png 424w, https://substackcdn.com/image/fetch/$s_!6czw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png 848w, https://substackcdn.com/image/fetch/$s_!6czw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png 1272w, https://substackcdn.com/image/fetch/$s_!6czw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6czw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png" width="1456" height="1323" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1323,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:474267,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/172478339?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6czw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png 424w, https://substackcdn.com/image/fetch/$s_!6czw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png 848w, https://substackcdn.com/image/fetch/$s_!6czw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png 1272w, https://substackcdn.com/image/fetch/$s_!6czw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F89e338e2-8d8f-40ad-9d81-53a1374f5736_1536x1396.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>List Comprehensions</h3><p>List comprehensions are one of the most popular features in Python, and it allows us to write idiomatic (or Pythonic) code.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vwXR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vwXR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png 424w, https://substackcdn.com/image/fetch/$s_!vwXR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png 848w, https://substackcdn.com/image/fetch/$s_!vwXR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png 1272w, https://substackcdn.com/image/fetch/$s_!vwXR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vwXR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png" width="1456" height="607" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:607,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:191885,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/172478339?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vwXR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png 424w, https://substackcdn.com/image/fetch/$s_!vwXR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png 848w, https://substackcdn.com/image/fetch/$s_!vwXR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png 1272w, https://substackcdn.com/image/fetch/$s_!vwXR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F237e528e-743e-4792-a50a-8f12cc5dc971_1536x640.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>But, as the student discovered, although the end result may be the same in the above example, the process it took to arrive at the solution is very different.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>In fact, in Python 3.12, the process used to implement list comprehension changed significantly.</p><p>Let us begin at the river.</p><h3><strong>Part 1: The Inner World of the For Loop</strong></h3><p>In <a href="https://pythonkoans.substack.com/p/koan-4-the-grand-library">Koan 4</a> we learnt that Python has 4 scopes (Local, Enclosing, Global and Builtin). However, there is also another &#8220;hidden&#8221; scope. Consider this loop:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eGjv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eGjv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!eGjv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!eGjv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!eGjv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eGjv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a4453cad-96b0-418a-813b-093dd5247930_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:177643,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/172478339?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eGjv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!eGjv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!eGjv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!eGjv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa4453cad-96b0-418a-813b-093dd5247930_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The loop above reassigns the value of <code>x</code> in the enclosing scope. After the loop runs, <code>x</code> is no longer <code>10</code>. Its value is now <code>2</code>. The loop's variable <code>x</code> "leaked" into the surrounding code.</p><p>Now consider the same code implemented as a list comprehension:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1Vrz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1Vrz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!1Vrz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!1Vrz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!1Vrz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1Vrz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png" width="1456" height="592" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:592,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:173825,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/172478339?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!1Vrz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png 424w, https://substackcdn.com/image/fetch/$s_!1Vrz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png 848w, https://substackcdn.com/image/fetch/$s_!1Vrz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png 1272w, https://substackcdn.com/image/fetch/$s_!1Vrz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8cfa8b8e-ada3-47d8-9ef3-9d828bba681e_1536x624.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This code prints <code>10</code>. The <code>x</code> in the comprehension is a new <code>x</code>. It does not touch the outer <code>x</code>. The list comprehension creates its own hidden scope.</p><h3>Part 2: Peering into the water</h3><p>But how does Python ensure that list comprehension has a distinct scope? To observe what is happening, we must first gather some tools to help us peek inside the code.</p><p>When you run a Python script, the CPython interpreter performs two main steps:</p><ol><li><p><strong>Compilation:</strong> The source code (the <code>.py</code> file you wrote) is compiled into a stream of bytecode instructions. This bytecode is cached into a <code>.pyc</code> file (pyc stands for "Python Compiled").</p></li><li><p><strong>Execution:</strong> The CPython virtual machine (a program written in C) reads and executes the bytecode instructions one by one. If the source file has changed, the bytecode is re-created, and if not, the cached <code>.pyc</code> file is run directly</p></li></ol><p>Inspecting the bytecode can inform us about how the program is run by the interpreter. However, the bytecode is stored in an efficient binary format that is not human readable.</p><p>To help us, we can use two functions:</p><ul><li><p><code>compile()</code> to compile a python source code string into a <code>code</code> object (also known as bytecode), with the <a href="https://docs.python.org/3/library/functions.html#compile">following arguments</a>:</p><ul><li><p><em><strong>filename</strong></em>: the filename from which the source code was read. If we are using the REPL, then it can be any string.</p></li><li><p><em><strong>mode</strong></em>: use &#8220;exec&#8221; for multi-line statements, &#8220;eval&#8221; for single line statements, and &#8220;single&#8221; for single line interactive statements.</p></li></ul></li><li><p><code>dis.dis</code> to disassemble the bytecode and print it in a readable format</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!C290!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!C290!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png 424w, https://substackcdn.com/image/fetch/$s_!C290!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png 848w, https://substackcdn.com/image/fetch/$s_!C290!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png 1272w, https://substackcdn.com/image/fetch/$s_!C290!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!C290!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png" width="1456" height="766" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:766,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:255085,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/172478339?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!C290!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png 424w, https://substackcdn.com/image/fetch/$s_!C290!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png 848w, https://substackcdn.com/image/fetch/$s_!C290!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png 1272w, https://substackcdn.com/image/fetch/$s_!C290!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcefb9e50-2b60-494f-9aa3-0abc88dffcc3_1536x808.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The output of <code>dis.dis</code> typically consists of several columns:</p><ul><li><p><strong>Line Number:</strong> This is the line number from the original Python source code. Note that a single line of Python code can compile into many bytecode instructions.</p></li><li><p><strong>Offset:</strong> This is the byte offset of the instruction within the bytecode stream. It's used by jump instructions to navigate the code.</p></li><li><p><strong>Instruction:</strong> This is the name of the bytecode instruction (e.g., <code>LOAD_CONST</code>, <code>CALL_FUNCTION</code>, <code>RETURN_VALUE</code>).</p></li><li><p><strong>Argument:</strong> This is a value or a reference used by the instruction. It might be an index into a table of constants, variables, or names.</p></li><li><p><strong>Argument Mnemonic:</strong> This provides a human-readable name for the argument, making it easier to understand what the instruction is doing (e.g., <code>(range)</code>, <code>(3)</code>, <code>(None)</code>).</p></li></ul><p>We now have all the tools we need to peek inside the list comprehension, and to investigate why Python &lt; 3.12 and Python &gt;= 3.12, behave so differently.</p><p>Until next time, may your stillness reveal the unseen flow.</p><h4><a href="https://pythonkoans.substack.com/p/koan-11-the-flowing-river-part-2?r=5yt43c">Continue to Part 2</a></h4><p></p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-10-the-flowing-river-part-1?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! If you enjoyed this post, feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-10-the-flowing-river-part-1?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://pythonkoans.substack.com/p/koan-10-the-flowing-river-part-1?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;75c5d25a-277d-4ded-ba97-8e8729ac87e4&quot;,&quot;caption&quot;:&quot;The Hidden Teaching: The Flow of Assignment&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 9: The Unfired Pot&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-25T23:56:14.032Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!_2Uu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-9-the-unfired-pot&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:171793208,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:1,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Koan 9: The Unfired Pot]]></title><description><![CDATA[Exploring chained operations and order of evaluation in python expressions]]></description><link>https://pythonkoans.substack.com/p/koan-9-the-unfired-pot</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-9-the-unfired-pot</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Mon, 25 Aug 2025 23:56:14 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!_2Uu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_2Uu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_2Uu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png 424w, https://substackcdn.com/image/fetch/$s_!_2Uu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png 848w, https://substackcdn.com/image/fetch/$s_!_2Uu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png 1272w, https://substackcdn.com/image/fetch/$s_!_2Uu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_2Uu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png" width="1456" height="1060" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1060,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:139437,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/171793208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!_2Uu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png 424w, https://substackcdn.com/image/fetch/$s_!_2Uu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png 848w, https://substackcdn.com/image/fetch/$s_!_2Uu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png 1272w, https://substackcdn.com/image/fetch/$s_!_2Uu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc65e068b-3d9d-4715-a5af-7ca9e997c434_1470x1070.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>The Hidden Teaching: The Flow of Assignment</strong></h3><p>Just as a master potter knows that some steps must precede others regardless of the order they&#8217;re written, a seasoned Python developer understands that a seemingly simple assignment is not a singular event. It&#8217;s a flow. The value does not &#8220;flow&#8221; from left to right. Python evaluates the right-hand side first and binds that result to each target from left to right.</p><h3>Part 1: Assignment Chains</h3><p>Consider a chain of assignments:</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!m1fE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!m1fE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png 424w, https://substackcdn.com/image/fetch/$s_!m1fE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png 848w, https://substackcdn.com/image/fetch/$s_!m1fE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png 1272w, https://substackcdn.com/image/fetch/$s_!m1fE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!m1fE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png" width="1456" height="386" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:386,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:22662,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/171793208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!m1fE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png 424w, https://substackcdn.com/image/fetch/$s_!m1fE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png 848w, https://substackcdn.com/image/fetch/$s_!m1fE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png 1272w, https://substackcdn.com/image/fetch/$s_!m1fE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F109e9171-cfa2-4cd6-96bf-852361644812_1470x390.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This may appear to assign <code>x + 2</code> to <code>x</code>, <code>y</code>, and <code>z</code> simultaneously. But Python does not work that way. The expression <code>x + 2</code> is evaluated once, producing the value <code>12</code>, which is then sequentially bound to <code>z</code>, <code>y</code>, and <code>x</code>. Assignment in Python is a statement, not an expression, so it does not return a value during this process.</p><h3>Part 2: Identity and Comparisons</h3><p>Consider the following assignment chain:</p><pre><code>list2 = list3 = list1 = [1,2,3]</code></pre><p>On the surface, this appears simple. It creates a single list object <code>[1, 2, 3]</code> and binds <code>list1</code>, <code>list3</code>, and <code>list2</code> to that same object.</p><p>This is a <em><strong>shared reference</strong></em>, not a copy.</p><p>Modifying one of these variables will affect all others. We can confirm this by checking the identity of the objects using the <code>id() </code>function. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!XB7j!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XB7j!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png 424w, https://substackcdn.com/image/fetch/$s_!XB7j!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png 848w, https://substackcdn.com/image/fetch/$s_!XB7j!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png 1272w, https://substackcdn.com/image/fetch/$s_!XB7j!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!XB7j!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png" width="1456" height="638" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:638,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:81993,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/171793208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!XB7j!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png 424w, https://substackcdn.com/image/fetch/$s_!XB7j!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png 848w, https://substackcdn.com/image/fetch/$s_!XB7j!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png 1272w, https://substackcdn.com/image/fetch/$s_!XB7j!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9b867b53-5dc4-46ec-9ebc-4ed3ae77064e_1470x644.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Part 3: Comparison Chains</h3><p>The same principle of sharing values does not apply to chained comparison operators such as <code>&lt;</code>, <code>&gt;</code> and <code>==</code>.</p><pre><code><code>1 &lt; x &lt; 10</code></code></pre><p>This expression is not evaluated from right to left. Instead, the interpreter performs a series of <em><strong>distinct comparisons</strong></em> and joins them with an implicit <code>and</code> operator.</p><p>The expression <code>1 &lt; x &lt; 10</code> is not shorthand for a single operation. It is shorthand for two separate operations:</p><pre><code><code>(1 &lt; x) and (x &lt; 10)</code></code></pre><p>The interpreter is smart enough to perform the minimal number of checks. If <code>1 &lt; x</code> is <code>False</code>, the expression <code>x &lt; 10</code> is not evaluated at all because the entire <code>and</code> expression will be <code>False</code>. This is known as <em><strong>short-circuiting </strong></em>and<em><strong> </strong></em>you can use this to your advantage when writing logical expressions:</p><pre><code>(high_probability_of_being_false) and (low_probability_of_being_false)</code></pre><p>If you write the expression with the higher likelihood of being <code>False</code> first, then you avoid the second expression from being executed. This is something you might have to consider when writing performance sensitive code. </p><h3><strong>Part 4: Chained Comparisons with Side Effects</strong></h3><p>What about chained comparisons containing functions with side effects? While Python evaluates <code>a &lt; b &lt; c</code> as <code>(a &lt; b) and (b &lt; c)</code>, what happens if <code>b</code> is the result of a function call? Consider the following example:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iMgq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iMgq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png 424w, https://substackcdn.com/image/fetch/$s_!iMgq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png 848w, https://substackcdn.com/image/fetch/$s_!iMgq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png 1272w, https://substackcdn.com/image/fetch/$s_!iMgq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iMgq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png" width="1456" height="555" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:555,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:56152,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/171793208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!iMgq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png 424w, https://substackcdn.com/image/fetch/$s_!iMgq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png 848w, https://substackcdn.com/image/fetch/$s_!iMgq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png 1272w, https://substackcdn.com/image/fetch/$s_!iMgq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7df5dea8-d110-47ae-9568-db4c8df3034d_1470x560.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The output will be <code>Getting B's value...</code> followed by <code>The truth holds</code>. The function <code>get_val_b</code> is called <em><strong>once </strong></em>and its returned value <code>5</code> is used for both <code>1 &lt; 5</code> and <code>5 &lt; 10</code>.</p><p>The comparison is evaluated as a logical <code>and</code>, but the function call that produces the shared value for both comparisons is only executed once. </p><h3>Firing the pot</h3><p>The master potter&#8217;s lesson was simple. The order in which instructions are given are not the order in which they must be executed. In Python, chained instructions are executed according to the following rules:</p><ul><li><p>Assignment chains evaluate the right-hand side once and bind that result sequentially to each target.</p></li><li><p>Comparison chains are logical combinations of individual comparisons.</p></li></ul><p>When you chain operators you are creating a silent understanding of how values will flow and how logic will be judged.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption"></p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-9-the-unfired-pot?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">If you enjoyed reading this post, consider sharing it with your friends!</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-9-the-unfired-pot?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://pythonkoans.substack.com/p/koan-9-the-unfired-pot?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;f5e1510f-19b5-4b73-b5d9-37efde079ca9&quot;,&quot;caption&quot;:&quot;When we speak of hashing in Python, we are entering a realm where identity, equality, and performance converge. In Koan 2, we learnt the difference between Identity and Equality. Hashing in Python uses equality rather than identity. It promises that two objects that are equal will share the same mark.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 8: The Shifting Seal&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-19T00:01:37.048Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!vrex!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-8-the-shifting-seal&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:171187140,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Koan 8: The Shifting Seal]]></title><description><![CDATA[Understanding Python&#8217;s rules for hashing]]></description><link>https://pythonkoans.substack.com/p/koan-8-the-shifting-seal</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-8-the-shifting-seal</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Tue, 19 Aug 2025 00:01:37 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!vrex!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vrex!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vrex!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png 424w, https://substackcdn.com/image/fetch/$s_!vrex!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png 848w, https://substackcdn.com/image/fetch/$s_!vrex!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png 1272w, https://substackcdn.com/image/fetch/$s_!vrex!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!vrex!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png" width="1456" height="862" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:862,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:101280,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/171187140?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vrex!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png 424w, https://substackcdn.com/image/fetch/$s_!vrex!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png 848w, https://substackcdn.com/image/fetch/$s_!vrex!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png 1272w, https://substackcdn.com/image/fetch/$s_!vrex!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3b17fd52-aa35-4fda-b6bd-f9e3ba502f8a_1470x870.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>When we speak of hashing in Python, we are entering a realm where identity, equality, and performance converge. In <a href="https://pythonkoans.substack.com/p/koan-2-the-tale-of-two-scrolls">Koan 2</a>, we learnt the difference between Identity and Equality. Hashing in Python uses equality rather than identity. It promises that two objects that are equal will share the same mark.</p><p>But the promise is not perfect.  </p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><p>The koan shows us two NaNs ("Not a Number"). They cannot be equal to each other, by mathematical rule. Yet their hashes are equal. How can two things be marked the same, yet not be the same?  </p><p>Let us examine the seals carefully.  </p><h3>Part 1: What is a Hash?  </h3><p>A hash is a value produced by a function designed to uniquely represent an object.  In Python, the built-in hash() function returns an integer, and it is used by dictionaries and sets to test membership. When you do: </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!rFrq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rFrq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png 424w, https://substackcdn.com/image/fetch/$s_!rFrq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png 848w, https://substackcdn.com/image/fetch/$s_!rFrq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png 1272w, https://substackcdn.com/image/fetch/$s_!rFrq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!rFrq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png" width="1456" height="525" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:525,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:44362,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/171187140?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!rFrq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png 424w, https://substackcdn.com/image/fetch/$s_!rFrq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png 848w, https://substackcdn.com/image/fetch/$s_!rFrq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png 1272w, https://substackcdn.com/image/fetch/$s_!rFrq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1d0d800d-ae30-419b-830a-8c69bfa3147c_1470x530.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Python does not search through all the keys each time. Instead, it computes a hash of <code>"key"</code>, uses it to jump to the right location in memory, and then checks equality to confirm.</p><p>So the rule is:</p><ol><li><p><strong>If </strong><code>a == b</code><strong>, then </strong><code>hash(a) == hash(b)</code><strong>.</strong></p></li><li><p>But the reverse is not guaranteed: <strong>if </strong><code>hash(a) == hash(b)</code><strong>, </strong><code>a</code><strong> and </strong><code>b</code><strong> may not be equal.</strong></p></li></ol><p>The first rule is what allows dictionaries and sets to function correctly.</p><h3>Part 2: The Strange Case of NaN</h3><p>Mathematically, NaN is defined so that:</p><pre><code><code>float('nan') == float('nan')  # False</code></code></pre><blockquote><p>float accepts the strings &#8220;nan&#8221; and &#8220;inf&#8221; with an optional prefix &#8220;+&#8221; or &#8220;-&#8221; for Not a Number (NaN) and positive or negative infinity.  (from <a href="https://docs.python.org/3/library/stdtypes.html#numeric-types-int-float-complex">Python Docs</a>)</p></blockquote><p>This is deliberate: NaN is not equal to anything, not even itself.</p><p>Yet Python ensures:</p><pre><code><code>hash(float('nan')) == hash(float('nan'))</code></code></pre><p>Why? Because hash-based collections require a consistent contract: objects that are equal must share the same hash, but Python<em><strong> does not forbid unequal objects from sharing a hash</strong></em>.</p><h3>Part 3: Hashing and Equality in User-Defined Classes</h3><p>When you define your own class, you may decide what equality and hashing mean.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AFOy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AFOy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png 424w, https://substackcdn.com/image/fetch/$s_!AFOy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png 848w, https://substackcdn.com/image/fetch/$s_!AFOy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png 1272w, https://substackcdn.com/image/fetch/$s_!AFOy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AFOy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png" width="1456" height="652" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/234b92b1-6037-4785-b85c-068012e32890_1470x658.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:652,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:82904,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/171187140?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!AFOy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png 424w, https://substackcdn.com/image/fetch/$s_!AFOy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png 848w, https://substackcdn.com/image/fetch/$s_!AFOy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png 1272w, https://substackcdn.com/image/fetch/$s_!AFOy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F234b92b1-6037-4785-b85c-068012e32890_1470x658.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Now two scrolls with the same text are considered equal, and they share the same hash:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mble!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mble!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png 424w, https://substackcdn.com/image/fetch/$s_!mble!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png 848w, https://substackcdn.com/image/fetch/$s_!mble!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png 1272w, https://substackcdn.com/image/fetch/$s_!mble!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!mble!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png" width="1456" height="481" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:481,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:50741,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/171187140?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!mble!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png 424w, https://substackcdn.com/image/fetch/$s_!mble!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png 848w, https://substackcdn.com/image/fetch/$s_!mble!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png 1272w, https://substackcdn.com/image/fetch/$s_!mble!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F55675a36-7dc4-46e8-ba06-bc7372ae996a_1470x486.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>If you override <code>__eq__</code> but forget to also override <code>__hash__</code>, Python will often make your object <strong>unhashable</strong>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!O5GJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!O5GJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png 424w, https://substackcdn.com/image/fetch/$s_!O5GJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png 848w, https://substackcdn.com/image/fetch/$s_!O5GJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png 1272w, https://substackcdn.com/image/fetch/$s_!O5GJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!O5GJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png" width="1456" height="481" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:481,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:54417,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/171187140?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!O5GJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png 424w, https://substackcdn.com/image/fetch/$s_!O5GJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png 848w, https://substackcdn.com/image/fetch/$s_!O5GJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png 1272w, https://substackcdn.com/image/fetch/$s_!O5GJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4db585b1-30b3-4af3-9aa2-9e3536c8d409_1470x486.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>If you define them inconsistently like returning different hashes for equal objects, your code may behave strangely or inefficiently.</p><p>These are the guidelines for implementation from the python docs:</p><blockquote><ul><li><p>If a class does not define an <code>__eq__()</code> method it should not define a <code>__hash__()</code> operation either</p></li><li><p>if it defines <code>__eq__()</code> but not <code>__hash__()</code>, its instances will not be usable as items in hashable collections. </p></li><li><p>If a class defines mutable objects and implements an <code>__eq__()</code> method, it should not implement <code>__hash__()</code>, since the implementation of <a href="https://docs.python.org/3/glossary.html#term-hashable">hashable</a> collections requires that a key&#8217;s hash value is immutable (if the object&#8217;s hash value changes, it will be in the wrong hash bucket).</p></li></ul></blockquote><h3>Part 4: Other Gotchas</h3><h4>4.1 Equality Across Types</h4><p>Python strives for consistency across related types:</p><pre><code><code>print(1 == 1.0)      # True
print(hash(1) == hash(1.0))  # True</code></code></pre><p>Despite being different types, the value of <code>1</code> and <code>1.0</code> are equal, so their hashes are also equal.</p><pre><code><code>d = {1: "integer"}
d[1.0]   # "integer"</code></code></pre><p>At first glance this is elegant, but it means different numeric types may collapse into the same bucket, even if their meanings diverge in your domain. In scientific or financial code, this subtle equality can introduce surprising behaviour if you intended to distinguish <code>int</code> from <code>float</code>.</p><h4>4.2 Immutable vs Mutable</h4><p>Hashes are meant to be stable. If the contents of an object could change after being placed in a dictionary or set, the mapping would fall apart.</p><p>This is why:</p><ul><li><p><strong>Immutable containers</strong> (like tuples) are hashable &#8212; but only if all their contents are hashable.</p></li><li><p><strong>Mutable containers</strong> (like lists and dicts) are not hashable.</p></li></ul><pre><code><code>hash((1, 2, (3, 4)))  # Works
hash((1, [2, 3]))     # TypeError</code></code></pre><p>The error is not arbitrary. It protects you from placing an unstable key into a dictionary. Imagine changing the list inside a tuple after it has been used as a key &#8212; the hash would no longer reflect the object&#8217;s state.</p><h3>The Final Seal</h3><p>The novice saw two NaNs and said: "The seals are the same, so the things must be the same." The master corrected him: "The ink is the same, but the seal is broken."</p><p>Hashing is a symbol, not a proof. Equality and hashing may touch, but they are not bound. To see clearly, we must hold both the symbol, and the substance it points to.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the previous issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;f11bde0c-c591-42fd-ad76-c57fe3f18fc8&quot;,&quot;caption&quot;:&quot;The Hidden Teaching: The Nature of the Path&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 7: The Unburdened Village&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-08-12T00:01:13.852Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wWx_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-7-the-unburdened-village&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:170140933,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:7,&quot;comment_count&quot;:2,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Koan 7: The Unburdened Village]]></title><description><![CDATA[Navigating Python's import system and namespace packages]]></description><link>https://pythonkoans.substack.com/p/koan-7-the-unburdened-village</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-7-the-unburdened-village</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Tue, 12 Aug 2025 00:01:13 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!wWx_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!wWx_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wWx_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png 424w, https://substackcdn.com/image/fetch/$s_!wWx_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png 848w, https://substackcdn.com/image/fetch/$s_!wWx_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png 1272w, https://substackcdn.com/image/fetch/$s_!wWx_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!wWx_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png" width="1456" height="1325" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1325,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:204852,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170140933?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!wWx_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png 424w, https://substackcdn.com/image/fetch/$s_!wWx_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png 848w, https://substackcdn.com/image/fetch/$s_!wWx_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png 1272w, https://substackcdn.com/image/fetch/$s_!wWx_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F091b392b-d3f7-4e8b-b2c1-332b8de5dc44_1470x1338.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3><strong>The Hidden Teaching: The Nature of the Path</strong></h3><p>The student believes that a village must be a single, bounded place. But the master knows that a village can be a <strong>concept</strong>, defined by its connections and the paths that lead to it.</p><p>In Python, the import system follows a similar principle. You may think of packages as walled villages with a clear boundary. Yet the true nature of the path (<code>sys.path</code>) allows for the creation of unburdened villages: namespace packages, where a single logical package is assembled from components scattered across the filesystem.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><h3><strong>Part 1: The Walled Village and the Path</strong></h3><p>The Python interpreter, when asked to <code>import</code> a package, follows a simple rule: it searches along a predefined path. This path, known as <code>sys.path</code>, is a list of directories.</p><p>A <strong>traditional package</strong>, or a "walled village," is a directory containing an <code>__init__.py</code> file. This file marks the directory as a package and provides its clear boundary. When you import this package, Python finds the directory on its path and all its contents are then accessible.</p><p>Consider a simple structure:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!o-Ho!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!o-Ho!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png 424w, https://substackcdn.com/image/fetch/$s_!o-Ho!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png 848w, https://substackcdn.com/image/fetch/$s_!o-Ho!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png 1272w, https://substackcdn.com/image/fetch/$s_!o-Ho!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!o-Ho!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png" width="1134" height="410" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/984d5350-0347-439c-9057-f4583073e8a0_1134x410.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:410,&quot;width&quot;:1134,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:37880,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170140933?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!o-Ho!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png 424w, https://substackcdn.com/image/fetch/$s_!o-Ho!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png 848w, https://substackcdn.com/image/fetch/$s_!o-Ho!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png 1272w, https://substackcdn.com/image/fetch/$s_!o-Ho!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F984d5350-0347-439c-9057-f4583073e8a0_1134x410.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>To use this, the directory containing <code>my_village</code> must be on <code>sys.path</code>. If you run Python from the directory above <code>my_village</code>, it is on the path by default.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!afRA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!afRA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png 424w, https://substackcdn.com/image/fetch/$s_!afRA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png 848w, https://substackcdn.com/image/fetch/$s_!afRA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png 1272w, https://substackcdn.com/image/fetch/$s_!afRA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!afRA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png" width="1234" height="298" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:298,&quot;width&quot;:1234,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:48815,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170140933?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!afRA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png 424w, https://substackcdn.com/image/fetch/$s_!afRA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png 848w, https://substackcdn.com/image/fetch/$s_!afRA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png 1272w, https://substackcdn.com/image/fetch/$s_!afRA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F138dc7b0-857a-456c-a61b-7d5f4b69a7c7_1234x298.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>The <code>__init__.py</code> is the village gate; it tells the interpreter, "This is the start of the journey."</p><h3><strong>Part 2: The Unseen Path and the Root of Confusion</strong></h3><p>The monk's confusion was not about the village itself, but about the assumption of a single starting point. The same confusion arises when a package is not directly on the path.</p><p>Consider the following:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fh09!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fh09!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png 424w, https://substackcdn.com/image/fetch/$s_!fh09!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png 848w, https://substackcdn.com/image/fetch/$s_!fh09!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png 1272w, https://substackcdn.com/image/fetch/$s_!fh09!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!fh09!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png" width="1234" height="494" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:494,&quot;width&quot;:1234,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:51750,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170140933?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!fh09!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png 424w, https://substackcdn.com/image/fetch/$s_!fh09!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png 848w, https://substackcdn.com/image/fetch/$s_!fh09!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png 1272w, https://substackcdn.com/image/fetch/$s_!fh09!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9f2e239-ebaf-4329-b0a7-1b50635c7df9_1234x494.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>If you run Python from a location that contains both <code>project1</code> and <code>project2</code>, the <code>my_village</code> directories are <strong>not</strong> directly on <code>sys.path</code>. The path only contains the top-level directory.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6lHc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6lHc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png 424w, https://substackcdn.com/image/fetch/$s_!6lHc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png 848w, https://substackcdn.com/image/fetch/$s_!6lHc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png 1272w, https://substackcdn.com/image/fetch/$s_!6lHc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!6lHc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png" width="1456" height="406" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:406,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:72886,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170140933?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!6lHc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png 424w, https://substackcdn.com/image/fetch/$s_!6lHc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png 848w, https://substackcdn.com/image/fetch/$s_!6lHc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png 1272w, https://substackcdn.com/image/fetch/$s_!6lHc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c51479f-4249-4e16-b2ef-3727079a4296_1470x410.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The interpreter's path is not a tangled vine that seeks out all nested directories. It is a straight road, and it only knows about <code>project1</code> and <code>project2</code>. It does not know to look inside them for other packages.</p><div><hr></div><h3><strong>Part 3: The Unburdened Village: A Shared Destination</strong></h3><p>The solution lies in understanding the path as a shared space. A <strong>namespace package</strong> is created when multiple directories with the same name, but <strong>without an </strong><code>__init__.py</code><strong> file</strong>, are all placed on <code>sys.path</code>.</p><p>By adding the parent directories (<code>project1</code> and <code>project2</code>) to the path, you instruct Python to consider them as valid starting points for imports.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UMqS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UMqS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png 424w, https://substackcdn.com/image/fetch/$s_!UMqS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png 848w, https://substackcdn.com/image/fetch/$s_!UMqS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png 1272w, https://substackcdn.com/image/fetch/$s_!UMqS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!UMqS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png" width="1456" height="701" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:701,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:129845,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170140933?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!UMqS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png 424w, https://substackcdn.com/image/fetch/$s_!UMqS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png 848w, https://substackcdn.com/image/fetch/$s_!UMqS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png 1272w, https://substackcdn.com/image/fetch/$s_!UMqS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd042b286-0f94-4fe0-8e15-69e0d216c9d7_1470x708.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The interpreter first looks on the path, finds <code>project1</code>, and sees a <code>my_village</code> directory inside. It then continues its search, finds <code>project2</code>, and sees another <code>my_village</code> directory. It then <strong>merges</strong> these two directories into a single logical package, the "unburdened village."</p><h3><strong>Part 4: The Path of the Confused Traveller</strong></h3><p>What if one part of the village has a wall and the other does not?</p><p>Consider if <code>project1</code>'s <code>my_village</code> directory contains an <code>__init__.py</code> file, but <code>project2</code>'s does not.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!yL38!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!yL38!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png 424w, https://substackcdn.com/image/fetch/$s_!yL38!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png 848w, https://substackcdn.com/image/fetch/$s_!yL38!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png 1272w, https://substackcdn.com/image/fetch/$s_!yL38!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!yL38!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png" width="1456" height="533" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:533,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:58927,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/170140933?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!yL38!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png 424w, https://substackcdn.com/image/fetch/$s_!yL38!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png 848w, https://substackcdn.com/image/fetch/$s_!yL38!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png 1272w, https://substackcdn.com/image/fetch/$s_!yL38!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb04156a1-9308-41d1-81bf-c4086de677f4_1470x538.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In this scenario, <code>my_village</code> is <strong>no longer a namespace package</strong>. Python's import system will find the first <code>my_village</code> directory on its search path (<code>sys.path</code>) that contains an <code>__init__.py</code> file, and it will treat that directory as the entire package.</p><p>When you run <code>import my_village.temple</code>, the interpreter will find the <code>my_village</code> directory in <code>project1</code>, but it will <strong>not</strong> continue to search for other <code>my_village</code> directories. It will only look for <code>temple.py</code> inside <code>project1/my_village</code>. The file will not be found, and you will get a <code>ModuleNotFoundError</code>.</p><p>The presence of the <code>__init__.py</code> file effectively "closes the gate" on the search for other parts of the package, turning it back into a traditional, "walled" package.</p><h3><strong>Part 5: The Power of the Unburdened Village</strong></h3><p>Why would one choose to build a village without walls?</p><ul><li><p><strong>Extensibility</strong>: Frameworks like <code>pytest</code> and <code>zope</code> use this pattern. The core library defines a namespace, for example <code>my_app.plugins</code>. Developers can then create their own packages, like <code>my_app.plugins.my_feature</code>, and the core application will automatically find and load them without any modification to the main codebase.</p></li><li><p><strong>Decomposition</strong>: A large project can be broken into smaller, independent libraries that are developed and versioned separately but still function as a single logical package.</p></li><li><p><strong>Modularity</strong>: It allows for a more distributed and modular architecture, where a project's components can be managed and installed from different locations.</p></li></ul><div><hr></div><h3><strong>Leaving the Village</strong></h3><p>The master's reply was a lesson in perspective. The village is not the directory itself but the <em>concept</em> of a shared space. The path is not a single location but a collection of all the roads one can travel.</p><p>Your confusion, like the monk's, arose from seeking a single physical truth. But Python's import system, like the master&#8217;s village, shows us that meaning can be constructed from disparate parts as long as you follow the right path.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div>]]></content:encoded></item><item><title><![CDATA[Koan 6: The Forgetful Calligrapher]]></title><description><![CDATA[Understanding Late Binding in Python Closures]]></description><link>https://pythonkoans.substack.com/p/the-forgetful-calligrapher</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/the-forgetful-calligrapher</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Tue, 05 Aug 2025 00:00:54 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!gdHE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gdHE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gdHE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png 424w, https://substackcdn.com/image/fetch/$s_!gdHE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png 848w, https://substackcdn.com/image/fetch/$s_!gdHE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png 1272w, https://substackcdn.com/image/fetch/$s_!gdHE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!gdHE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png" width="1456" height="1084" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1084,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:285913,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/169916254?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!gdHE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png 424w, https://substackcdn.com/image/fetch/$s_!gdHE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png 848w, https://substackcdn.com/image/fetch/$s_!gdHE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png 1272w, https://substackcdn.com/image/fetch/$s_!gdHE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6beae50-4f0d-4571-a3f2-0579c23ba879_1888x1406.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>In Python, a function is more than a list of commands, as we learnt in <a href="https://pythonkoans.substack.com/p/koan-5-the-silent-harp">Koan 5</a>. When a function is defined inside another, it becomes a <strong>closure</strong>, a small piece of code that remembers its parent's environment. This memory is powerful, but it's not a picture of the past. It's more like a window. It shows you the world as it is <em>right now</em>, not as it was when the window was first opened. This phenomenon is known as <strong>late binding</strong>.</p><p>Let's begin by observing the simplest expression of a closure.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!t9Pu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!t9Pu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png 424w, https://substackcdn.com/image/fetch/$s_!t9Pu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png 848w, https://substackcdn.com/image/fetch/$s_!t9Pu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png 1272w, https://substackcdn.com/image/fetch/$s_!t9Pu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!t9Pu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png" width="1360" height="458" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:458,&quot;width&quot;:1360,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:83487,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/169916254?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!t9Pu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png 424w, https://substackcdn.com/image/fetch/$s_!t9Pu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png 848w, https://substackcdn.com/image/fetch/$s_!t9Pu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png 1272w, https://substackcdn.com/image/fetch/$s_!t9Pu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fddd3fe6a-19dd-4ac9-9550-37462862f385_1360x458.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Here, <code>execute_commission</code> is the closure. It remembers the <code>item</code> variable from its parent function, <code>make_commission</code>. When we call <code>draw_sun()</code>, it returns "sun" as expected. The closure has a clear, singular memory of its purpose.</p><h3>Part 2: The Master's Three Commands</h3><p>Now, let's observe the lazy calligrapher's technique, as described in the koan. He waits until all instructions have been given before beginning his work.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!nhq1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nhq1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png 424w, https://substackcdn.com/image/fetch/$s_!nhq1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png 848w, https://substackcdn.com/image/fetch/$s_!nhq1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png 1272w, https://substackcdn.com/image/fetch/$s_!nhq1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!nhq1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png" width="1360" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:608,&quot;width&quot;:1360,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:117693,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/169916254?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!nhq1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png 424w, https://substackcdn.com/image/fetch/$s_!nhq1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png 848w, https://substackcdn.com/image/fetch/$s_!nhq1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png 1272w, https://substackcdn.com/image/fetch/$s_!nhq1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff6e8f7de-d01f-4fd3-a973-5fa71accb8a6_1360x608.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>One might expect the output to be "sun," "moon," and then "cloud." However, the code will print "cloud" three times.</p><p>This is the very essence of late binding. The <code>execute_commission</code> function doesn't capture the <em>value</em> of <code>instruction</code> at the time it's created. Instead, it holds a reference to the <strong>variable</strong> <code>instruction</code> itself. By the time we finally get around to executing the first function in the list, the <code>for</code> loop has already completed, and the variable <code>instruction</code> has a final value: "cloud."</p><p>All three closures refer to the same single <code>instruction</code> variable in the outer scope, which has finished its journey. </p><h3>Part 3: The Diligent Calligrapher</h3><p>To correct this behavior, we need a way for each closure to capture its own unique copy of the instruction at the moment it's created. We must teach the calligrapher to be diligent and remember each command individually.</p><p>One method to achieve this is by using a <strong>default argument</strong>. As we learnt in <a href="https://pythonkoans.substack.com/p/koan-3-the-ringing-bell">Koan 3</a>, default arguments are evaluated once, at the time the function is defined. We can modify our <code>make_commissions</code> function to use this technique.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!duEq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!duEq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png 424w, https://substackcdn.com/image/fetch/$s_!duEq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png 848w, https://substackcdn.com/image/fetch/$s_!duEq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png 1272w, https://substackcdn.com/image/fetch/$s_!duEq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!duEq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png" width="1360" height="608" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:608,&quot;width&quot;:1360,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:120963,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/169916254?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!duEq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png 424w, https://substackcdn.com/image/fetch/$s_!duEq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png 848w, https://substackcdn.com/image/fetch/$s_!duEq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png 1272w, https://substackcdn.com/image/fetch/$s_!duEq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9955247-72a4-442a-a01c-1718ad4a1e9d_1360x608.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This time, the output is as we first intended. By setting the default argument <code>item=instruction</code>, we force Python to evaluate <code>instruction</code> and bind its current value to the <code>item</code> parameter for each new function. Each closure now holds its own unique copy of the instruction, rather than sharing a single reference.</p><h3>Part 4: The Anonymous Calligrapher</h3><p>This principle of late binding also applies to <strong>lambda functions</strong>. As we learnt in <a href="https://pythonkoans.substack.com/p/koan-5-the-silent-harp">Koan 5</a>, lambdas are simply anonymous functions. The "lazy calligrapher" effect is very common when lambdas are created in a loop.</p><p>Here is the original problem, written with a lambda:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!TcIV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TcIV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png 424w, https://substackcdn.com/image/fetch/$s_!TcIV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png 848w, https://substackcdn.com/image/fetch/$s_!TcIV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png 1272w, https://substackcdn.com/image/fetch/$s_!TcIV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!TcIV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png" width="1360" height="534" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:534,&quot;width&quot;:1360,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:107691,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/169916254?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!TcIV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png 424w, https://substackcdn.com/image/fetch/$s_!TcIV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png 848w, https://substackcdn.com/image/fetch/$s_!TcIV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png 1272w, https://substackcdn.com/image/fetch/$s_!TcIV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdddb2d67-aef5-4187-a8df-5f36c6b18482_1360x534.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>Just like with the <code>def</code>-defined function, this will also return "cloud," because the lambda closes over the <code>instruction</code> variable, not its value.</p><p>To correct this, we use a default argument for the lambda function:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WNyY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WNyY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png 424w, https://substackcdn.com/image/fetch/$s_!WNyY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png 848w, https://substackcdn.com/image/fetch/$s_!WNyY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png 1272w, https://substackcdn.com/image/fetch/$s_!WNyY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WNyY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png" width="1360" height="534" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6671774a-d39f-4022-a655-701bff81aa91_1360x534.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:534,&quot;width&quot;:1360,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:109673,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/169916254?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!WNyY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png 424w, https://substackcdn.com/image/fetch/$s_!WNyY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png 848w, https://substackcdn.com/image/fetch/$s_!WNyY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png 1272w, https://substackcdn.com/image/fetch/$s_!WNyY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6671774a-d39f-4022-a655-701bff81aa91_1360x534.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>We can make this more concise and <em>pythonic</em> by using list comprehension to create all the commissions in a single stroke. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eN59!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eN59!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png 424w, https://substackcdn.com/image/fetch/$s_!eN59!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png 848w, https://substackcdn.com/image/fetch/$s_!eN59!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png 1272w, https://substackcdn.com/image/fetch/$s_!eN59!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!eN59!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png" width="1360" height="422" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:422,&quot;width&quot;:1360,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:89571,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/169916254?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!eN59!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png 424w, https://substackcdn.com/image/fetch/$s_!eN59!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png 848w, https://substackcdn.com/image/fetch/$s_!eN59!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png 1272w, https://substackcdn.com/image/fetch/$s_!eN59!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2a9a6084-a62f-4cb1-a825-dcb753f437d8_1360x422.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Part 5: The Master's Scrupulous Note</h3><p>What if we could not use a default argument? Is there another way to force the calligrapher to capture the instruction immediately? The solution lies in creating a new scope for each instruction, forcing each closure to "listen" to a unique voice.</p><p>We can achieve this by creating a factory function that takes the instruction as an argument, thus creating a new, isolated environment for each closure.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!P2k_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!P2k_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png 424w, https://substackcdn.com/image/fetch/$s_!P2k_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png 848w, https://substackcdn.com/image/fetch/$s_!P2k_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png 1272w, https://substackcdn.com/image/fetch/$s_!P2k_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!P2k_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png" width="1360" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1360,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:138799,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/169916254?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!P2k_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png 424w, https://substackcdn.com/image/fetch/$s_!P2k_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png 848w, https://substackcdn.com/image/fetch/$s_!P2k_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png 1272w, https://substackcdn.com/image/fetch/$s_!P2k_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff2b19c91-d217-4720-81f9-8b60a5972de3_1360x756.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>This code also yields the correct output. On each iteration of the loop, we call <code>create_executor(instruction)</code>. This function is given the <em>current value</em> of <code>instruction</code>. It then creates a new closure, <code>execute_commission</code>, which closes over <code>item</code>. Because <code>item</code> is a local variable within <code>create_executor</code>, its value is isolated from the outer loop's changes (as we learnt in <a href="https://pythonkoans.substack.com/p/koan-4-the-grand-library">Koan 4</a> about Python&#8217;s LEGB rule). Each call to <code>create_executor</code> creates a new, private memory for the closure it returns. It is as if the master wrote a small, specific note for each drawing, which the calligrapher could not forget.</p><h3>Part 6: The Customized Brush</h3><p>There are other, more concise or functional ways to achieve the same result. The choice of method often comes down to the clarity and style you prefer. We can use <code>functools.partial</code> to "pre-bind" the argument to a function. This is like preparing a special brush for each task, with the instruction already etched into its handle. </p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VQjC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VQjC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png 424w, https://substackcdn.com/image/fetch/$s_!VQjC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png 848w, https://substackcdn.com/image/fetch/$s_!VQjC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png 1272w, https://substackcdn.com/image/fetch/$s_!VQjC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!VQjC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png" width="1360" height="720" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:720,&quot;width&quot;:1360,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:134467,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/169916254?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!VQjC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png 424w, https://substackcdn.com/image/fetch/$s_!VQjC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png 848w, https://substackcdn.com/image/fetch/$s_!VQjC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png 1272w, https://substackcdn.com/image/fetch/$s_!VQjC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcda1562b-9a5f-426e-a119-2a9e0a44c3ab_1360x720.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>The Final Brushstroke</h3><p>The Master's teaching was simple: the calligrapher did not remember what was once said, only the command that was last spoken when the drawing finally began.</p><p>In your code, your functions are like the forgetful calligrapher. The closure does not remember the values the variable held when it was created, only the last value is recalled when the function is run.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;1c56c3ca-7434-4a35-a938-6dd405723320&quot;,&quot;caption&quot;:&quot;Functions as First-Class Citizens in Python&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 5: The Silent Harp&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-07-29T00:01:04.533Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!NhBB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-5-the-silent-harp&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:169448507,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:3,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Koan 5: The Silent Harp]]></title><description><![CDATA[Exploring how functions in Python are treated as first-class citizens, and the untapped potential they hold.]]></description><link>https://pythonkoans.substack.com/p/koan-5-the-silent-harp</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-5-the-silent-harp</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Tue, 29 Jul 2025 00:01:04 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!NhBB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NhBB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NhBB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png 424w, https://substackcdn.com/image/fetch/$s_!NhBB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png 848w, https://substackcdn.com/image/fetch/$s_!NhBB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png 1272w, https://substackcdn.com/image/fetch/$s_!NhBB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NhBB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png" width="1456" height="638" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:638,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:154005,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/169448507?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!NhBB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png 424w, https://substackcdn.com/image/fetch/$s_!NhBB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png 848w, https://substackcdn.com/image/fetch/$s_!NhBB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png 1272w, https://substackcdn.com/image/fetch/$s_!NhBB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F086fc16b-5abb-4b01-aa02-9f1e993744ca_1804x790.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Functions as First-Class Citizens in Python</h3><p>In Python, a <strong>function</strong> is much like a harp. An object that holds potential, a set of instructions waiting to be invoked and produce a harmonious result. This design choice makes functions "<strong>first-class citizens</strong>," opening up a world of elegant and powerful programming paradigms.</p><p>Let's begin with this fundamental understanding.</p><h3>Part 1: The Harp&#8217;s Existence</h3><p>What does it mean for a function to be a "first-class citizen"? It means that functions can be:</p><ul><li><p><strong>Assigned to variables</strong>.</p></li><li><p><strong>Passed as arguments</strong> to other functions.</p></li><li><p><strong>Returned as values</strong> from other functions.</p></li><li><p><strong>Stored in data structures</strong> (lists, dictionaries, etc.).</p></li></ul><p>This is distinct from languages where functions are merely blocks of code that can be called, but not manipulated like other data.</p><p>Consider a simple instruction for making music with our harp:</p><pre><code>def play_note(note):
    return f"The harp plays the note: {note}"</code></pre><p>In Python, <code>play_note</code> isn't just a command; it's an object. You can prove this by assigning it to another variable, much like one might refer to the harp by a different name in an orchestra:</p><pre><code>my_instrument = play_note
print(my_instrument("C major"))</code></pre><p>Here, <code>my_instrument</code> now refers to the same function object as <code>play_note</code>. The harp exists, and we have a way to access its potential for sound, even if no note has yet been played.</p><h3>Part 2: Passing the Harp to the Musician (Higher-Order Functions)</h3><p>One of the most powerful implications of functions being first-class is the ability to <em><strong>pass them as arguments</strong></em> to other functions. Functions that accept other functions as arguments are known as "<em><strong>higher-order functions</strong></em>." This is akin to handing our harp to a skilled musician, trusting them to play its strings when the moment is right.</p><p>A common example is the <code>map()</code> function, which applies a given function to all items in an input list and returns an iterator. Let's imagine we have a sequence of musical ideas, and we want to apply a transformation to each using our harp's capabilities:</p><pre><code>def harmonize_note(x):
    return f"{x} with harmony"

melody_notes = ["C", "G", "Am", "F"]
harmonized_melody = list(map(harmonize_note, melody_notes))
print(harmonized_melody)</code></pre><p>Here, <code>harmonize_note</code> is passed as an argument to <code>map</code>. <code>map</code> doesn't know <em>what</em> <code>harmonize_note</code> does, only that it's a callable object it can apply to each element. It simply knows how to take a series of musical ideas and apply the "play and harmonize" instruction to each.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3>Part 3: The Unnamed Chord (Lambdas)</h3><p>For simple, one-off musical expressions, Python offers "<em><strong>lambda expressions</strong></em>." These are small, anonymous functions that can be defined in a single line. They are particularly useful when you need a function object for a short period, often as an argument to a higher-order function, like a quick flourish instead of a formal composition.</p><p>Our koan's core, <code>lambda x: x + 1</code>, is an example of an anonymous function. It exists, it holds potential, but it doesn't have a formal name.</p><pre><code># Using a lambda with map to transpose notes:
base_frequencies = [440, 494, 523] # A4, B4, C5 frequencies
transposed_frequencies = list(map(lambda freq: freq + 50, base_frequencies))
print(transposed_frequencies)</code></pre><p>Lambdas are succinct and often improve readability for simple operations, avoiding the need to define a full <code>def</code> function for a trivial task. They are like a quickly improvised chord on the harp.</p><h3>Part 4: Plucking the String Immediately (Immediate Invocation)</h3><p>Just as we can assign a lambda to a variable and then play it, we can also play it immediately after it's defined.</p><p>Consider our simple <code>lambda</code> from the koan:</p><pre><code>lambda x: x + 1</code></pre><p>This defines a function object. It is the silent harp string. To make it produce a result, we need to "pluck" it by providing an argument. We typically do this by assigning it to a variable first, then calling that variable:</p><pre><code>increment_frequency = lambda x: x + 1
result = increment_frequency(10)
print(result)</code></pre><p>However, because the <code>lambda</code> expression itself <em>evaluates</em> to a function object, you can immediately apply arguments to it, just like you would with any other function reference.</p><p>The koan's code demonstrates this:</p><pre><code>(lambda x: x + 1)(10)</code></pre><p>Here, <code>(lambda x: x + 1)</code> creates the anonymous function object (the harp string), and <code>(10)</code> immediately calls that function with the argument <code>10</code> (plucks the string). The <strong>parentheses</strong> around the lambda expression are crucial here to ensure the lambda is fully defined before the invocation operator <code>()</code> attempts to call it. Without them, Python would expect a function name to call. </p><p>This pattern, sometimes seen as an Immediately Invoked Function Expression (IIFE), is less common in everyday Python than in JavaScript, but it is perfectly valid and can be seen in specialized contexts, often for creating self-contained scopes or for quick, single-use computations without cluttering the namespace.</p><h3>Closing the Circle</h3><p>The silent harp holds all its potential for music within. Only when a string is plucked does its melody emerge. And sometimes, the note is played the very moment the string is tied.</p><p>In Python, functions are not just commands; they are entities with identity, capable of being manipulated, stored, and passed around like any other piece of data.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-5-the-silent-harp?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! This post is public so feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-5-the-silent-harp?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://pythonkoans.substack.com/p/koan-5-the-silent-harp?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;bb9dd8e2-b571-4303-9c78-5f7e6ad3a94b&quot;,&quot;caption&quot;:&quot;Variable Scope and the Shadows They Cast&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 4: The Lamp's Shadow&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-07-22T00:00:17.149Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!iuLp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F538ceee8-a75f-4940-b22d-c97a491ba40f_1554x1526.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-4-the-grand-library&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:168688073,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:6,&quot;comment_count&quot;:0,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Koan 4: The Lamp's Shadow]]></title><description><![CDATA[Understanding Python&#8217;s LEGB rule, closures, and how names echo through nested functions]]></description><link>https://pythonkoans.substack.com/p/koan-4-the-grand-library</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-4-the-grand-library</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Tue, 22 Jul 2025 00:00:17 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!iuLp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F538ceee8-a75f-4940-b22d-c97a491ba40f_1554x1526.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ikfG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ikfG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png 424w, https://substackcdn.com/image/fetch/$s_!ikfG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png 848w, https://substackcdn.com/image/fetch/$s_!ikfG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png 1272w, https://substackcdn.com/image/fetch/$s_!ikfG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!ikfG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png" width="1456" height="949" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:949,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:190521,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/168688073?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!ikfG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png 424w, https://substackcdn.com/image/fetch/$s_!ikfG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png 848w, https://substackcdn.com/image/fetch/$s_!ikfG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png 1272w, https://substackcdn.com/image/fetch/$s_!ikfG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7ddcc158-48eb-4a63-8d29-5c6af991a205_1670x1088.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Variable Scope and the Shadows They Cast</h3><p>In Python, variables are not always where they appear to be.<br>When a function runs, it carries with it not just its own code, but the shadow of names it has seen, names that belong to outer scopes.</p><p>To understand this, we must learn to see how Python <em>resolves names</em>.</p><p>Let us begin simply.</p><h3><strong>Part 1: The Local Glow</strong></h3><p>The simplest form of scope is the local scope. When you define a variable inside a function, it exists only within that function's execution.</p><pre><code><code>def greet():
    message = "Hello, world!"
    print(message)

greet()
print(message)  # This would cause an error: NameError</code></code></pre><p>Here, <code>message</code> is born and dies within the <code>greet</code> function. It's like a lamp lit only inside a small room; its light doesn't extend beyond the doorway.</p><h3><strong>Part 2: The Enclosing Room</strong></h3><p>Now, let's open another door. Python has a concept called enclosing scope. This applies to nested functions. If a variable isn't found in the immediate local scope, Python looks outwards to any enclosing functions.</p><p>Consider this:</p><pre><code><code>def outer_function():
    outer_message = "From the outer room."

    def inner_function():
        print(outer_message)
    
    inner_function()

outer_function()
</code></code></pre><p>When <code>inner_function</code> is called, it first looks for <code>outer_message</code> within its own scope. It doesn't find it. So, it looks in the scope of <code>outer_function</code>, where <code>outer_message</code> resides. This works. The inner function can see the variables of its enclosing function, like seeing the light of a lamp in an adjacent room through an open door.</p><h3><strong>Part 3: The Global Stage</strong></h3><p>Beyond local and enclosing scopes, there is the global scope. Variables defined at the top level of a script or module are global. They can be accessed from anywhere within that module.</p><pre><code><code>global_message = "From the wide world."

def display_global():
    print(global_message)

display_global()</code></code></pre><p>Here, <code>display_global</code> can access <code>global_message</code> because it's in the global scope. This is like the sun's light, visible from every room.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3><strong>Part 4: The Built-in Universe</strong></h3><p>Finally, there's the built-in scope. This contains all the names that Python pre-defines, such as <code>print</code>, <code>len</code>, <code>str</code>, <code>True</code>, <code>False</code>, and <code>None</code>. These are always available.</p><p>The order in which Python searches for names is known as the LEGB rule:</p><ol><li><p><strong>L</strong>ocal (current function)</p></li><li><p><strong>E</strong>nclosing function locals (from inner to outer enclosing functions)</p></li><li><p><strong>G</strong>lobal (top-level of the module)</p></li><li><p><strong>B</strong>uilt-in (Python's pre-defined names)</p></li></ol><p>Python stops at the first place it finds the name.</p><h3><strong>Part 5: When Shadows Deceive - Variable Binding</strong></h3><p>The true complexity arises when you <em>assign</em> to a variable within a deeper scope. When Python encounters an assignment statement, it assumes you intend to create or modify a variable in the <em>current</em> scope, unless explicitly told otherwise.</p><p>Let's revisit our koan's example:</p><pre><code><code>shadow = 10  # Global shadow

def outer_lamp():
    shadow = 20  # This 'shadow' is local to outer_lamp()
    def inner_lamp():
        print(shadow)  # This 'shadow' refers to outer_lamp()'s shadow
    return inner_lamp

lamp = outer_lamp()
lamp() # Output: 20
</code></code></pre><p>Here's the crucial part:</p><ol><li><p><code>shadow = 10</code> establishes a global <code>shadow</code>.</p></li><li><p>Inside <code>outer_lamp()</code>, <code>shadow = 20</code> creates a <em>new</em>, <em>local variable</em> within <code>outer_lamp</code>'s scope. This <code>shadow</code> is entirely separate from the global <code>shadow</code>. It does not modify the global <code>shadow</code>.</p></li><li><p>Inside <code>inner_lamp()</code>, when <code>print(shadow)</code> is called, Python searches for <code>shadow</code> using the LEGB rule. It finds <code>shadow = 20</code> in its <em>enclosing</em> scope (<code>outer_lamp</code>), and that's the <code>shadow</code> it uses.</p></li></ol><p>The <code>lamp()</code> call, which executes <code>inner_lamp()</code>, thus prints 20. The global <code>shadow</code> (which remains 10) is untouched, and the <code>shadow</code> in <code>outer_lamp()</code> casts its own shadow, independent of the global lamp.</p><h3>Part 6: The Illusion of Locality</h3><p>Now, a subtle twist:</p><pre><code><code>shadow = "global"

def inner():
    print(shadow)
    shadow = "local"

inner()</code></code></pre><p>What happens here?</p><p>Python raises an error:</p><pre><code><code>UnboundLocalError: cannot access local variable 'shadow' before assignment</code></code></pre><p>Why?</p><p>Because Python sees the assignment <code>shadow = "local"</code> and <em>assumes</em> that <code>shadow</code> must be local to <code>inner</code>. It does not look outside anymore. So when you try to read <code>shadow</code> before assigning it, Python is confused. There is a local <code>shadow</code>, but it has no value yet.</p><p>In Python, <strong>any assignment to a variable within a function makes that variable local to that function</strong>, unless explicitly declared otherwise.</p><p>This leads us to the next teaching.</p><h3><strong>Part 7: </strong>Declaring Intent &#8211; <code>global</code> and <code>nonlocal</code></h3><p>If we wish to use or modify a variable from an outer scope, we must <em>declare</em> our intent.</p><p>Using <code>global</code>:</p><pre><code>shadow = 5

def modify():
    global shadow
    shadow = 10

modify()
print(shadow)  # 10</code></pre><p>Here, <code>global shadow</code> tells Python: &#8220;I mean the <code>shadow</code> from the module&#8217;s top level.&#8221;</p><p>When working with nested functions, and using <code>nonlocal</code>:</p><pre><code>def outer():
    shadow = 5
    def inner():
        nonlocal shadow
        shadow = 10
    inner()
    print(shadow)

outer()  # 10</code></pre><p>Without <code>nonlocal</code>, the assignment would create a new local <code>shadow</code> inside <code>inner</code>.<br>With it, Python understands: <em>use the variable from the enclosing function</em>.</p><h3><strong>Extinguishing The Lamp</strong></h3><p>The Master's second lamp illuminated the truth: each lamp casts its own shadow. Similarly, in Python, each scope can define its own variables, creating distinct 'lamps' of variables. Without explicit instruction (like <code>nonlocal</code> or <code>global</code>), an assignment always defaults to the current, innermost scope, safeguarding higher-level variables from unintended modification.</p><p>Understanding scope is not just about avoiding errors; it's about designing clear, predictable, and maintainable code. It's about knowing where your variables truly reside, and how their light extends, or does not extend, into the surrounding code.</p><div class="captioned-button-wrap" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-4-the-grand-library?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="CaptionedButtonToDOM"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! This post is public so feel free to share it.</p></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/p/koan-4-the-grand-library?utm_source=substack&utm_medium=email&utm_content=share&action=share&quot;,&quot;text&quot;:&quot;Share&quot;}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://pythonkoans.substack.com/p/koan-4-the-grand-library?utm_source=substack&utm_medium=email&utm_content=share&action=share"><span>Share</span></a></p></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;a1ffe2fa-bff4-47a6-aab2-6e89f18b3628&quot;,&quot;caption&quot;:&quot;Mutable Default Arguments and the Echoes of the Past&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 3: The Ringing Bell&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-07-15T00:00:40.904Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!pwqW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-3-the-ringing-bell&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:167969768,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:4,&quot;comment_count&quot;:2,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Koan 3: The Ringing Bell]]></title><description><![CDATA[Understanding how Python evaluates default arguments and why mutable defaults can carry unintended memory]]></description><link>https://pythonkoans.substack.com/p/koan-3-the-ringing-bell</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-3-the-ringing-bell</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Tue, 15 Jul 2025 00:00:40 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!pwqW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pwqW!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pwqW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png 424w, https://substackcdn.com/image/fetch/$s_!pwqW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png 848w, https://substackcdn.com/image/fetch/$s_!pwqW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png 1272w, https://substackcdn.com/image/fetch/$s_!pwqW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!pwqW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png" width="1394" height="872" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:872,&quot;width&quot;:1394,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:139031,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/167969768?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!pwqW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png 424w, https://substackcdn.com/image/fetch/$s_!pwqW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png 848w, https://substackcdn.com/image/fetch/$s_!pwqW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png 1272w, https://substackcdn.com/image/fetch/$s_!pwqW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F61c23f6f-4cd1-4341-aa7e-1235f58d3eeb_1394x872.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Mutable Default Arguments and the Echoes of the Past</h3><p>In Python, a function is not just a block of code, it is an object, alive with memory. And sometimes, that memory is louder than you expect.</p><p>We expect that every time we call <code>ring()</code>, it will create a new list and append <code>"clang"</code>. But instead, each call remembers the last. Why?</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h3>Part 1: When Are Defaults Evaluated?</h3><p>In Python, <strong>default arguments are evaluated only once</strong> &#8212; at the time the function is defined, not each time it is called.</p><p>So in:</p><pre><code><code>def ring(bell=[]):</code></code></pre><p>Python creates a new empty list <em>once</em> and binds it to the <code>bell</code> parameter&#8217;s default. All future calls to <code>ring()</code> without a <code>bell</code> argument will use <em>that same list</em>.</p><p>Thus:</p><pre><code>first = ring()
second = ring()
third = ring()

print(first is second is third)  # True</code></pre><p>They are all the same object.</p><p>This behavior often surprises beginners. It feels as if Python is remembering things it should forget. But it is not magic. It is memory: persistent, and shared.</p><h3>Part 2: Mutable vs Immutable Defaults: A Gentle Contrast</h3><p>The issue arises only with <strong>mutable</strong> default values, like lists or dictionaries. What if we used an <strong>immutable</strong> default, such as a tuple?</p><p>Consider:</p><pre><code><code>def ring(bell=()):
   bell += ("clang",)
   return bell</code></code></pre><p>What do you expect?</p><pre><code><code>ring() # ('clang',)
ring() # ('clang',)
ring() # ('clang',)</code></code></pre><p>Each call gives us a fresh result. There is no accumulation. No echo.</p><p>Why?</p><p>Because tuples are immutable. The <code>+=</code> operator cannot modify the existing tuple. Instead, it creates a new one. In Python, the <code>id() </code>function gives you the memory address of an object. You can use this to test if the objects are the same, but beware of the <a href="https://pythonkoans.substack.com/i/167246035/part-the-subtle-trap-of-immutable-types">CPython caching (also known as interning) we learnt about last week</a>. To avoid CPython interning, we need to assign the result to a new object:</p><pre><code><code>import time

def ring(bell=()):
    bell += (str(time.time()),)
    return bell

sound1 = ring(); print(id(sound1)) # 135080430662176
sound2 = ring(); print(id(sound2)) # 135080430179360
sound3 = ring(); print(id(sound3)) # 135080430181856</code></code></pre><div><hr></div><p>Want to explore how interning works in more detail? </p><p>I&#8217;m starting a new companion series where I explore advanced Python techniques in more detail and how they are actually used in open-source projects. It&#8217;s called &#8220;Python In The Wild&#8221;, and you can subscribe here to receive the first post when it comes out: </p><div class="embedded-publication-wrap" data-attrs="{&quot;id&quot;:5613759,&quot;name&quot;:&quot;Python In The Wild&quot;,&quot;logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!Tgw8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5409c8e4-e8f0-4115-ae5a-f00c8a5d6fd0_1024x1024.png&quot;,&quot;base_url&quot;:&quot;https://pythoninthewild.substack.com&quot;,&quot;hero_text&quot;:&quot;Explore how Python is used in the wild, through real-world examples from Open-Source projects&quot;,&quot;author_name&quot;:&quot;Vivis Dev&quot;,&quot;show_subscribe&quot;:true,&quot;logo_bg_color&quot;:&quot;#042f2e&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="EmbeddedPublicationToDOMWithSubscribe"><div class="embedded-publication show-subscribe"><a class="embedded-publication-link-part" native="true" href="https://pythoninthewild.substack.com?utm_source=substack&amp;utm_campaign=publication_embed&amp;utm_medium=web"><img class="embedded-publication-logo" src="https://substackcdn.com/image/fetch/$s_!Tgw8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5409c8e4-e8f0-4115-ae5a-f00c8a5d6fd0_1024x1024.png" width="56" height="56" style="background-color: rgb(4, 47, 46);"><span class="embedded-publication-name">Python In The Wild</span><div class="embedded-publication-hero-text">Explore how Python is used in the wild, through real-world examples from Open-Source projects</div><div class="embedded-publication-author-name">By Vivis Dev</div></a><form class="embedded-publication-subscribe" method="GET" action="https://pythoninthewild.substack.com/subscribe?"><input type="hidden" name="source" value="publication-embed"><input type="hidden" name="autoSubmit" value="true"><input type="email" class="email-input" name="email" placeholder="Type your email..."><input type="submit" class="button primary" value="Subscribe"></form></div></div><div><hr></div><p>Each time, Python builds a new object and returns it. The original default remains untouched.</p><p>This is why only mutable default arguments pose a problem. It is not the default itself that is dangerous, it is the possibility of mutation.</p><p>When an object can change, and you reuse that object across calls, you risk unintended persistence.</p><h3>Part 3: The Right Way: Use <code>None</code> as a Sentinel</h3><p>The conventional solution is this:</p><pre><code><code>def ring(bell=None):
    if bell is None:
        bell = []
    bell.append("clang")
    return bell</code></code></pre><p>Now:</p><pre><code><code>ring() # ['clang']
ring() # ['clang']</code></code></pre><p>Each call receives a fresh list.</p><p>Why use <code>None</code>?</p><p>Because <code>None</code> is immutable and unique. It makes an excellent sentinel, a marker that tells us, &#8220;No argument was provided.&#8221;</p><p>If you use this pattern, your functions will behave predictably. The echoes will fade when they should.</p><div><hr></div><h3>Part 4: When Might You Use Mutable Defaults?</h3><p>There <em>are</em> rare times when shared mutable state is intended. For example, a function that memoizes its own results:</p><pre><code><code>def factorial(n, cache={0: 1}):
    if n not in cache:
       cache[n] = n * factorial(n - 1)
    return cache[n]</code></code></pre><p>Here, the default dictionary acts as a persistent memory. But this is a deliberate choice, not an accident.</p><p>If you do this, document it clearly. Most of the time, such patterns are better handled with decorators or external caches.</p><p>Shared state is not inherently wrong, but it must be a conscious design, not an accidental side effect.</p><div><hr></div><h3>Best Practices: The Bellmaker&#8217;s Notes</h3><ul><li><p><strong>Avoid using mutable objects like lists or dicts as default arguments.</strong><br>They persist across calls and can lead to surprising behavior.</p></li><li><p><strong>Use </strong><code>None</code><strong> as a default when you want a fresh object each time.</strong><br>Inside the function, create a new object only when needed.</p></li><li><p><strong>Immutable defaults (like </strong><code>None</code><strong>, </strong><code>0</code><strong>, </strong><code>''</code><strong>, or </strong><code>()</code><strong>) are always safe.</strong><br>Operations like <code>+=</code> on them return new objects, leaving the default unchanged.</p></li><li><p><strong>If you </strong><em><strong>must</strong></em><strong> use a mutable default, document the behavior clearly.</strong><br>Treat it as shared state and ensure your design requires it.</p></li><li><p><strong>When debugging, use </strong><code>id()</code><strong> or logging to confirm whether the same object is reused, but beware of interning which can mislead you.</strong><br>If your function &#8220;remembers&#8221; things, ask yourself: &#8220;Did I mean to ring the same bell again?&#8221;</p></li></ul><div><hr></div><h3>Closing the Circle</h3><p>The novice asked, &#8220;Why does the bell grow louder each time I call for it?&#8221;</p><p>The master replied,</p><blockquote><p>&#8220;Because you never asked for a new bell.&#8221;</p></blockquote><p>In Python, if a default argument is mutable, it will grow, echo, and persist across calls.</p><p>To write clean Python is to know which bells echo, and when to ring a fresh one.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the last issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;ce61fcdd-edb5-448a-b9f4-18ccea1c7eda&quot;,&quot;caption&quot;:&quot;\&quot;is\&quot; vs. \&quot;==\&quot;: The Subtle Art of Identity and Equality in Python&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 2: The Tale of Two Scrolls&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-07-08T00:15:24.271Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!um0i!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-2-the-tale-of-two-scrolls&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:167246035,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:12,&quot;comment_count&quot;:2,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item><item><title><![CDATA[Koan 2: The Tale of Two Scrolls]]></title><description><![CDATA[Understanding the difference between identity and equality, and why it matters more than it seems.]]></description><link>https://pythonkoans.substack.com/p/koan-2-the-tale-of-two-scrolls</link><guid isPermaLink="false">https://pythonkoans.substack.com/p/koan-2-the-tale-of-two-scrolls</guid><dc:creator><![CDATA[Vivis Dev]]></dc:creator><pubDate>Tue, 08 Jul 2025 00:15:24 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!um0i!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!um0i!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!um0i!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png 424w, https://substackcdn.com/image/fetch/$s_!um0i!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png 848w, https://substackcdn.com/image/fetch/$s_!um0i!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png 1272w, https://substackcdn.com/image/fetch/$s_!um0i!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!um0i!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png" width="1170" height="1246" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1246,&quot;width&quot;:1170,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:158846,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://pythonkoans.substack.com/i/167246035?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!um0i!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png 424w, https://substackcdn.com/image/fetch/$s_!um0i!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png 848w, https://substackcdn.com/image/fetch/$s_!um0i!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png 1272w, https://substackcdn.com/image/fetch/$s_!um0i!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0de63204-a22d-4a57-886c-a10ab2e806b3_1170x1246.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>"is" vs. "==": The Subtle Art of Identity and Equality in Python</h3><p>When learning Python, it's common to encounter subtle distinctions that don&#8217;t make much sense at first. One of these is the difference between <code>is</code> and <code>==</code>. At a glance, they both seem to answer the same question: "Are these things the same?" But in truth, they answer very different questions.</p><p>Let us begin at the beginning.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><h4>Part 1: The Two Questions</h4><p>Python allows you to ask:</p><ul><li><p><strong>Do these two values have the same </strong><em><strong>contents</strong></em><strong>?</strong><br>You use <code>==</code> to ask this question.</p></li><li><p><strong>Do these two values refer to the </strong><em><strong>same object</strong></em><strong> in memory?</strong><br>You use <code>is</code> to ask this question.</p></li></ul><p>In simple terms:</p><ul><li><p><code>==</code> asks, <em>"Do they look the same?"</em></p></li><li><p><code>is</code> asks, <em>"Are they the same being?"</em></p></li></ul><p>Let&#8217;s look at a few examples:</p><pre><code><code>a = [1, 2, 3]
b = [1, 2, 3]

print(a == b) # True (same contents)
print(a is b) # False (different objects)</code></code></pre><p>At first, this might feel strange. If they&#8217;re both <code>[1, 2, 3]</code>, why wouldn&#8217;t they be the same?</p><p>Because Python has created two separate <em>lists</em> in memory. They hold the same values, but they are not the same object. Like two scrolls with identical text, one copied from the other. If you edit one, the other remains unchanged.</p><p>This is the heart of the difference between equality and identity.</p><div><hr></div><h4>Part 2: Why Use <code>is</code> At All?</h4><p>Why not always use <code>==</code>?</p><p>The <code>is</code> operator is not about equality of content, it is about <strong>identity</strong>. There are cases where identity matters deeply. One of them is checking for a sentinel object, such as <code>None</code>.</p><pre><code><code>if user_input is None:
    print("No input provided.")</code></code></pre><p>Here, you're not asking <em>"Does the input look like None?"</em>, but <em>"Is the input literally the None object?"</em></p><p>This distinction ensures clarity and precision when writing code that interacts with unique markers or singleton objects.</p><div><hr></div><h4>Part 3: The Subtle Trap of Immutable Types</h4><p>Now let&#8217;s tread into trickier ground. The behavior of <em>immutable types</em>, such as integers, strings, and tuples.</p><p>Consider:</p><pre><code><code>a = 1000
b = 1000

print(a == b) # True 
print(a is b) # False (on most systems)</code></code></pre><p>But then:</p><pre><code><code>x = 5
y = 5

print(x == y) # True 
print(x is y) # True</code></code></pre><p>Why the inconsistency?</p><p>This is due to <a href="https://bugs.python.org/issue34850">an implementation detail of CPython</a> (the most widely used Python interpreter). For performance, CPython caches small integers and some strings. So small values may end up pointing to the <em>same</em> object. But this is not something you should rely on. It's a quirk, not a guarantee.</p><p>In other words: the student sees that <code>1 is 1</code>, and assumes the same for <code>1000 is 1000</code>. But the truth changes subtly with scale, like mist lifting to reveal two paths instead of one.</p><div><hr></div><h4>Part 4: Containers and Identity</h4><p>Let&#8217;s go a step deeper. What about empty containers?</p><pre><code><code>print([] == []) # True - same contents (both empty)
print([] is []) # False - distinct list objects</code></code></pre><p>Python creates a new list each time you write <code>[]</code>. They are separate, though they appear the same. Like the student&#8217;s scrolls, word-for-word identical, yet changes to one do not touch the other.</p><p>And tuples?</p><pre><code><code>print( () == () ) # True 
print( () is () ) # True (usually)</code></code></pre><p>Here again, we encounter CPython&#8217;s caching. Because <code>()</code> is immutable and common, Python may reuse the same object. But this behavior is not mandated by the Python language specification, it is an implementation detail.</p><p>From Python 3.8 onwards, certain comparisons like <code>() is ()</code> even raise a <strong>SyntaxWarning</strong>, gently nudging the student to rethink their assumption.</p><div><hr></div><h4>Best Practices</h4><ol><li><p><strong>Use </strong><code>==</code> when comparing values.<br>You&#8217;re asking, <em>do these two things hold the same meaning or content?</em></p></li><li><p><strong>Use </strong><code>is</code> when checking for identity, especially for singletons like <code>None</code>, <code>True</code>, <code>False</code>, or a sentinel object you define.</p></li><li><p><strong>Avoid using </strong><code>is</code><strong> with literals or immutable values</strong>, unless you have a specific reason to care about identity, and even then, document that reason.</p></li></ol><div><hr></div><h4>Final Reflection</h4><p>The master&#8217;s lesson was simple:<br>Two scrolls may appear the same. But when you change one, the truth of their separation is revealed.</p><p>In Python, <code>==</code> and <code>is</code> teach us to look beneath the surface. Equality is about appearance. Identity is about essence. And understanding this difference is not just a technical detail, it is a practice in seeing things as they truly are.</p><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://pythonkoans.substack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe&quot;,&quot;language&quot;:&quot;en&quot;}" data-component-name="SubscribeWidgetToDOM"><div class="subscription-widget show-subscribe"><div class="preamble"><p class="cta-caption">Thanks for reading Python Koans! Subscribe for free to receive new posts and support my work.</p></div><form class="subscription-widget-subscribe"><input type="email" class="email-input" name="email" placeholder="Type your email&#8230;" tabindex="-1"><input type="submit" class="button primary" value="Subscribe"><div class="fake-input-wrapper"><div class="fake-input"></div><div class="fake-button"></div></div></form></div></div><div><hr></div><p>New here? Python Koans is a Python newsletter that helps you learn Python through short puzzles. Catch up on the first issue here:</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;ac6ad6b8-b5c8-4ee1-8e70-6e844a113f94&quot;,&quot;caption&quot;:&quot;The Hidden Teaching: __bool__ and the Design of Truth&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;size&quot;:&quot;lg&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Koan 1: The Empty Path&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:360796152,&quot;name&quot;:&quot;Vivis Dev&quot;,&quot;bio&quot;:&quot;Python lessons wrapped in koans. Small puzzles, deep truths. Not your usual tutorial thread.&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cb8c3fd5-687d-4613-b300-dd4d00137512_941x941.png&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-07-01T00:14:55.032Z&quot;,&quot;cover_image&quot;:&quot;https://substackcdn.com/image/fetch/$s_!hFw-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3272ad33-1830-42ea-8990-aaf78a5d3233_1360x678.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://pythonkoans.substack.com/p/koan-1-the-empty-path&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:167226912,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:21,&quot;comment_count&quot;:6,&quot;publication_id&quot;:5505104,&quot;publication_name&quot;:&quot;Python Koans&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!wNQ0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ae11423-3624-4e2b-9806-0886b9f340e6_992x992.png&quot;,&quot;belowTheFold&quot;:true,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div>]]></content:encoded></item></channel></rss>