<?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[The Python Coding Stack: The Python Coding Stack]]></title><description><![CDATA[The Python articles I wish I had when I was learning Python]]></description><link>https://www.thepythoncodingstack.com/s/the-python-coding-stack</link><image><url>https://substackcdn.com/image/fetch/$s_!Dn3k!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab4a59e8-e362-456b-8427-934e87c31a0d_600x600.png</url><title>The Python Coding Stack: The Python Coding Stack</title><link>https://www.thepythoncodingstack.com/s/the-python-coding-stack</link></image><generator>Substack</generator><lastBuildDate>Sun, 25 Oct 2026 15:19:57 GMT</lastBuildDate><atom:link href="https://www.thepythoncodingstack.com/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Stephen Gruppetta]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[thepythoncodingstack@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[thepythoncodingstack@substack.com]]></itunes:email><itunes:name><![CDATA[Stephen Gruppetta]]></itunes:name></itunes:owner><itunes:author><![CDATA[Stephen Gruppetta]]></itunes:author><googleplay:owner><![CDATA[thepythoncodingstack@substack.com]]></googleplay:owner><googleplay:email><![CDATA[thepythoncodingstack@substack.com]]></googleplay:email><googleplay:author><![CDATA[Stephen Gruppetta]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[The Potion Shop That Does Too Much • The S in SOLID]]></title><description><![CDATA[The Single Responsibility Principle &#8226; SOLID Ideas &#8226; #1]]></description><link>https://www.thepythoncodingstack.com/p/solid-single-responsibility-principle-srp-the-potion-shop-that-does-too-much</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/solid-single-responsibility-principle-srp-the-potion-shop-that-does-too-much</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Mon, 28 Sep 2026 17:17:11 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!HPEi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The potion shop had been doing well.</p><p>It had a small but loyal customer base, a reliable supply of moonflower, and<br>three owls that carried order confirmations and other notifications to customers across the kingdom.</p><p>The shop&#8217;s ordering system was simple:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-cwp!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-cwp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.png 424w, https://substackcdn.com/image/fetch/$s_!-cwp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.png 848w, https://substackcdn.com/image/fetch/$s_!-cwp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.png 1272w, https://substackcdn.com/image/fetch/$s_!-cwp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!-cwp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.png" width="1272" height="1974" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1974,&quot;width&quot;:1272,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:223247,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.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_!-cwp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.png 424w, https://substackcdn.com/image/fetch/$s_!-cwp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.png 848w, https://substackcdn.com/image/fetch/$s_!-cwp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.png 1272w, https://substackcdn.com/image/fetch/$s_!-cwp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fff0e151f-93f5-401f-a0a1-af29daaddb79_1272x1974.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">All code blocks are available in text format at the end of this article &#8226; #1</figcaption></figure></div><p>We&#8217;ll make significant changes to this code in this article, but bear with me for now.</p><p>A customer orders an invisibility potion:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QQSe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!QQSe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!QQSe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!QQSe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!QQSe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:16938,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.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_!QQSe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!QQSe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!QQSe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!QQSe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d0494de-a2c1-4470-8dfc-92ed9314cd08_1200x210.png 1456w" sizes="100vw"></picture><div></div></div></div><figcaption class="image-caption">#2</figcaption></figure></div><p>The output looks good:</p><pre><code>Invisibility  &#163;12.00
Owl dispatched to Merlin
12.00</code></pre><p>I&#8217;m using <code>Decimal</code> for the prices here as it&#8217;s a better data type for money than <code>float</code>. We discussed this a bit here, too: <a href="https://www.thepythoncodingstack.com/p/python-descriptors-the-price-is-right">The Weird and Wonderful World of Descriptors in Python &#8226; The Price is Right</a>.</p><p>The shop has sold a potion, updated its stock, recorded the sale, and notified the customer.</p><p>What could possibly go wrong?</p><h2><strong>A new label for the Moon Festival</strong></h2><p>The Moon Festival is approaching, and the shop owner wants special labels:</p><pre><code>&#127769; Moon Festival Invisibility &#127769;   &#163;12.00</code></pre><p>We could change <code>.sell()</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_!31sQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!31sQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png 424w, https://substackcdn.com/image/fetch/$s_!31sQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png 848w, https://substackcdn.com/image/fetch/$s_!31sQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png 1272w, https://substackcdn.com/image/fetch/$s_!31sQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!31sQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png" width="1200" height="1050" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1050,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:59952,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.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_!31sQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png 424w, https://substackcdn.com/image/fetch/$s_!31sQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png 848w, https://substackcdn.com/image/fetch/$s_!31sQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png 1272w, https://substackcdn.com/image/fetch/$s_!31sQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8aa6ccd0-32d1-4d5f-9229-a2162a15cfd6_1200x1050.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#3</figcaption></figure></div><p>You can read more about the &#8216;rogue asterisk&#8217; in the signature, a.k.a keyword-only arguments, in this post: <a href="https://www.thepythoncodingstack.com/p/python-function-parameters-arguments-args-kwargs-optional-positional-keyword">A Story About Parameters and Arguments in Python Functions &#8226; &#8220;AI Coffee&#8221; Grand Opening This Monday</a>.</p><p>Now this works:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tq_c!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!tq_c!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!tq_c!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!tq_c!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!tq_c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/daf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:21470,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.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_!tq_c!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!tq_c!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!tq_c!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!tq_c!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdaf8eb8c-47b7-4e64-b7a0-04ca1e29a34d_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#4</figcaption></figure></div><p>Here&#8217;s the output from this code:</p><pre><code>&#127769; Moon Festival Invisibility &#127769;  &#163;12.00
Owl dispatched to Merlin
12.00</code></pre><p>The change is small. Perhaps this class is still perfectly fine.</p><div><hr></div><p>The shop owner then asks for a test that checks the label without selling a potion. This is where you start to see the design problem.</p><p>At the moment, the only place that creates a label is inside <code>.sell()</code>. There is no suitable way to check the label policy independently. The code does not offer a way to ask for a label without also selling a potion.</p><p>The design problem is that <code>PotionShop</code> currently is in charge of label creation, even though the label policy can change independently of the policy that deals with sales. How about moving label creation to its own class?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!f2ZF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!f2ZF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!f2ZF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!f2ZF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!f2ZF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!f2ZF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:44323,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.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_!f2ZF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!f2ZF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!f2ZF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!f2ZF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5ed22447-ec77-4a10-a4fe-7531fa85be96_1200x630.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#5</figcaption></figure></div><p>Now you can check that the label is correct without having to sell an item in the first place:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ui07!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ui07!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!ui07!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!ui07!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!ui07!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ui07!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png" width="1200" height="336" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:336,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:29933,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.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_!ui07!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!ui07!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!ui07!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!ui07!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F317910d4-bfd7-4862-a8a8-1bf950b82877_1200x336.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#6</figcaption></figure></div><p>This code would raise an <code>AssertionError</code> if the string that <code>labels.make()</code> returns is not identical to the required output. In this case, there are no errors.</p><p>In a real project, you could use a testing platform to run these checks. But I&#8217;ll use plain <code>assert</code> statements throughout to keep things simpler in this tutorial.</p><p>The shop delegates label-making to this 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_!BzDn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BzDn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png 424w, https://substackcdn.com/image/fetch/$s_!BzDn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png 848w, https://substackcdn.com/image/fetch/$s_!BzDn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png 1272w, https://substackcdn.com/image/fetch/$s_!BzDn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!BzDn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png" width="1200" height="1134" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1134,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:56959,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.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_!BzDn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png 424w, https://substackcdn.com/image/fetch/$s_!BzDn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png 848w, https://substackcdn.com/image/fetch/$s_!BzDn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png 1272w, https://substackcdn.com/image/fetch/$s_!BzDn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9681634-69f0-4bfb-bee2-518186d87ea8_1200x1134.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#7</figcaption></figure></div><p>You should also remove the three lines that create a label you had further down within <code>.sell()</code>.</p><p>We&#8217;re using <em>composition</em> here. The Potion Shop <em>has a</em> label maker, and you pass a <code>LabelMaker</code> object to the <code>.label_maker</code> attribute in the <code>PotionShop</code> object. The <code>PotionShop</code> object can now delegate label making to an object dedicated to this task.</p><p>From this point onwards, the shop receives the label-making collaborator:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1U0D!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d8da646-9053-4d9d-88b2-685633a01914_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!1U0D!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d8da646-9053-4d9d-88b2-685633a01914_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!1U0D!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d8da646-9053-4d9d-88b2-685633a01914_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!1U0D!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d8da646-9053-4d9d-88b2-685633a01914_1200x168.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!1U0D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d8da646-9053-4d9d-88b2-685633a01914_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d8da646-9053-4d9d-88b2-685633a01914_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:9915,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d8da646-9053-4d9d-88b2-685633a01914_1200x168.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_!1U0D!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d8da646-9053-4d9d-88b2-685633a01914_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!1U0D!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d8da646-9053-4d9d-88b2-685633a01914_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!1U0D!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d8da646-9053-4d9d-88b2-685633a01914_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!1U0D!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d8da646-9053-4d9d-88b2-685633a01914_1200x168.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#8</figcaption></figure></div><p><code>PotionShop</code> still coordinates the sale, but the label policy can now change without changing <code>PotionShop</code>. We started separating responsibilities. Making labels is no longer the responsibility of the <code>PotionShop</code> object. But we still have a bit more to go.</p><div><hr></div><p>You got a taste of what the <em>Single Responsibility Principle</em> does in the example so far. But the code still has other transgressions of this principle. Let&#8217;s work through them in the rest of this post.</p><div class="pullquote"><p><em><strong>Coming soon:</strong> Let&#8217;s build a project from beginning to end in collaboration with AI agents. This will NOT be vibe coding. Instead, it&#8217;s a collaboration between knowledgeable humans and powerful AI.</em></p><p><em>This is the direction real programming is taking.</em></p><p><em>And we&#8217;ll explore SOLID principles in this project, which I&#8217;ll share as text and videos. Make sure you&#8217;re a premium subscriber so you don&#8217;t miss out.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p></div><h2><strong>The owls go on strike</strong></h2><p>A few days later, the owls refuse to fly during a thunderstorm. The potions can still be prepared, but the notification service is unavailable.</p><p>The shop needs to stop sending notifications temporarily.</p><p>Before changing the notification system, we first make the owl&#8217;s availability explicit:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ywHS!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ywHS!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png 424w, https://substackcdn.com/image/fetch/$s_!ywHS!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png 848w, https://substackcdn.com/image/fetch/$s_!ywHS!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png 1272w, https://substackcdn.com/image/fetch/$s_!ywHS!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ywHS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png" width="1200" height="1134" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1134,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:91432,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.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_!ywHS!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png 424w, https://substackcdn.com/image/fetch/$s_!ywHS!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png 848w, https://substackcdn.com/image/fetch/$s_!ywHS!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png 1272w, https://substackcdn.com/image/fetch/$s_!ywHS!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F24a036ca-c203-4a68-ae74-0e2e3f11c480_1200x1134.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#9</figcaption></figure></div><p>But you also want to add a test to check the price is correct.</p><p>Your code extracts the price from the <code>.recipes</code> class attribute as part of the <code>.sell()</code> method. So, this is how you can test the price is what you&#8217;re expecting:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6AgR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!6AgR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!6AgR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!6AgR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!6AgR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:24495,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.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_!6AgR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!6AgR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!6AgR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!6AgR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1a86c54-02c7-4d99-87c1-06bd5da51a9f_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#10</figcaption></figure></div><p>You get the following output and no <code>AssertionError</code> in this case:</p><pre><code>Invisibility  &#163;12.00
Owl dispatched to Merlin</code></pre><p>However, you should also test this when the owls are unavailable. Of course, this shouldn&#8217;t make any difference to the price:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aEei!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!aEei!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!aEei!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!aEei!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!aEei!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:27426,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.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_!aEei!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!aEei!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!aEei!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!aEei!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef5beef4-7fd7-4d40-afef-227762dab2fc_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#11</figcaption></figure></div><p>But, your code doesn&#8217;t get that far. The <code>.sell()</code> method calculates the price and prints the label. But the owl service raises <code>OwlUnavailable</code> and the code stops before you can verify the price is right:</p><pre><code>Invisibility  &#163;12.00
&#8203;
Traceback (most recent call last):
  ...
OwlUnavailable: The owls are currently unavailable</code></pre><p>The price is not the problem. The test cannot inspect the price without also triggering an owl notification.</p><p>The shop&#8217;s different jobs are now getting in each other&#8217;s way. But before we fix this problem, let&#8217;s make the mess bigger.</p><h2><strong>A discount for cauldron owners</strong></h2><p>The owner has another idea. Customers who bring their own cauldron should receive a 10% discount.</p><p>We add another parameter:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ibQ4!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ibQ4!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png 424w, https://substackcdn.com/image/fetch/$s_!ibQ4!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png 848w, https://substackcdn.com/image/fetch/$s_!ibQ4!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!ibQ4!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ibQ4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png" width="1362" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1362,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:59173,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.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_!ibQ4!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png 424w, https://substackcdn.com/image/fetch/$s_!ibQ4!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png 848w, https://substackcdn.com/image/fetch/$s_!ibQ4!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!ibQ4!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc0b67fc-59fc-4cd9-a6be-76544d9b83c5_1362x1092.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#12</figcaption></figure></div><p>You use <code>.quantize()</code>, which is a method in the <code>Decimal</code> class, to ensure the discounted value is rounded to two decimal places. Let&#8217;s try this with a shop whose notification service is available:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sdIw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sdIw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png 424w, https://substackcdn.com/image/fetch/$s_!sdIw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png 848w, https://substackcdn.com/image/fetch/$s_!sdIw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png 1272w, https://substackcdn.com/image/fetch/$s_!sdIw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!sdIw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png" width="1200" height="462" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:462,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:28783,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.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_!sdIw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png 424w, https://substackcdn.com/image/fetch/$s_!sdIw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png 848w, https://substackcdn.com/image/fetch/$s_!sdIw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png 1272w, https://substackcdn.com/image/fetch/$s_!sdIw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe7564fd2-685f-4bfe-93d4-c6439c3dc628_1200x462.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#13</figcaption></figure></div><p>The output shows the correct discounted price:</p><pre><code>Invisibility  &#163;10.80
Owl dispatched to Merlin
10.80</code></pre><p>Let&#8217;s see what happens if the owls are unavailable:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Dw6w!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Dw6w!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png 424w, https://substackcdn.com/image/fetch/$s_!Dw6w!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png 848w, https://substackcdn.com/image/fetch/$s_!Dw6w!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png 1272w, https://substackcdn.com/image/fetch/$s_!Dw6w!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Dw6w!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png" width="1200" height="462" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:462,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:31478,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.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_!Dw6w!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png 424w, https://substackcdn.com/image/fetch/$s_!Dw6w!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png 848w, https://substackcdn.com/image/fetch/$s_!Dw6w!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png 1272w, https://substackcdn.com/image/fetch/$s_!Dw6w!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5337853c-0ff3-4642-872e-6b731f750e26_1200x462.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#14</figcaption></figure></div><p>Your code raises an error since the owls aren&#8217;t flying:</p><pre><code>Invisibility  &#163;10.80
Traceback (most recent call last):
  ...
OwlUnavailable: The owls are currently unavailable</code></pre><p>But there&#8217;s an even bigger problem now. Can you spot it?</p><p>Even though the code stopped execution and raised an error, it had already changed the stock and recorded a sale. Let&#8217;s use a <code>try..except</code> block to see what&#8217;s happening:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!pZlb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pZlb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png 424w, https://substackcdn.com/image/fetch/$s_!pZlb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png 848w, https://substackcdn.com/image/fetch/$s_!pZlb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png 1272w, https://substackcdn.com/image/fetch/$s_!pZlb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!pZlb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png" width="1200" height="672" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:672,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:65045,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.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_!pZlb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png 424w, https://substackcdn.com/image/fetch/$s_!pZlb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png 848w, https://substackcdn.com/image/fetch/$s_!pZlb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png 1272w, https://substackcdn.com/image/fetch/$s_!pZlb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6644562f-b86e-47d0-bde4-617c8353062b_1200x672.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#15</figcaption></figure></div><p>Here&#8217;s the output:</p><pre><code>Invisibility  &#163;10.80
Catching the &#8216;OwlUnavailable&#8217; Exception
{&#8217;moonflower&#8217;: 8, &#8216;dragon_scale&#8217;: 0}
[(&#8217;Merlin&#8217;, &#8216;invisibility&#8217;, Decimal(&#8217;10.80&#8217;))]</code></pre><p>You started off with 10 units of moonflower and 2 units of dragon scales in the potion shop. These values are currently hardcoded in the class&#8217;s <code>.__init__()</code> special method (which is in itself not a good idea, but more on this later.)</p><p>The recipe uses two units of each, as shown in the <code>.recipes</code> class attribute (which will also change soon.)</p><p>So you end up using up the stock even though <code>.sell()</code> raised an exception! You can see from the output that the sale was also registered.</p><h2><strong>One failure too many</strong></h2><p>The <code>.sell()</code> method is now responsible for:</p><ul><li><p>Looking up recipes</p></li><li><p>Removing ingredients</p></li><li><p>Calculating prices</p></li><li><p>Applying discounts</p></li><li><p>Coordinating label creation*</p></li><li><p>Recording sales</p></li><li><p>Sending notifications</p></li></ul><p>* Creating labels is the one we have already improved. It&#8217;s the others that are still a problem!</p><p>And the owner has just mentioned loyalty points, premium labels, email notifications, and a special discount for customers who arrive by broomstick.</p><p>The <code>.sell()</code> method is becoming the place where every new request arrives.</p><p>And it&#8217;s not just <code>PotionShop.sell()</code> that&#8217;s trying to do too much. The <code>PotionShop</code> class also takes care of the recipes available in the <code>.recipes</code> class attribute and the stock available in the shop.</p><p>It is time to separate these responsibilities.</p><h2><strong>Separating the recipe book</strong></h2><p>Let&#8217;s start with the recipes. The shop should not need to know the details of every recipe. That is the recipe book&#8217;s job:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HRcc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HRcc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png 424w, https://substackcdn.com/image/fetch/$s_!HRcc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png 848w, https://substackcdn.com/image/fetch/$s_!HRcc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png 1272w, https://substackcdn.com/image/fetch/$s_!HRcc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!HRcc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png" width="1200" height="714" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/acf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:714,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:62038,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.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_!HRcc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png 424w, https://substackcdn.com/image/fetch/$s_!HRcc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png 848w, https://substackcdn.com/image/fetch/$s_!HRcc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png 1272w, https://substackcdn.com/image/fetch/$s_!HRcc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Facf26af5-53df-45d7-843c-7d3ac275be85_1200x714.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#16</figcaption></figure></div><p>This class is responsible for the recipe book. And nothing else. You add the <code>.find()</code> method to make it easier for a user to use the class without knowing the details of how it&#8217;s built. It&#8217;s usually best for a class to manage its own data. So, rather than requiring the user to know that the recipes are stored in a dictionary, you provide the <code>.find()</code> method that does the work.</p><p>Suppose the potion maker changes a recipe or adds a new potion. Those changes belong in <code>RecipeBook</code>; the steps for selling a potion don&#8217;t need to change.</p><p>We can test this class without creating a shop, changing stock, printing labels, or sending owls:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!wfR5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.png 424w, https://substackcdn.com/image/fetch/$s_!wfR5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.png 848w, https://substackcdn.com/image/fetch/$s_!wfR5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.png 1272w, https://substackcdn.com/image/fetch/$s_!wfR5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!wfR5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.png" width="1308" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1308,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:23471,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.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_!wfR5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.png 424w, https://substackcdn.com/image/fetch/$s_!wfR5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.png 848w, https://substackcdn.com/image/fetch/$s_!wfR5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.png 1272w, https://substackcdn.com/image/fetch/$s_!wfR5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe80f6283-149d-4af8-bcd0-7baa9e2905ee_1308x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#17</figcaption></figure></div><p>This code doesn&#8217;t raise an exception since the price is correct.</p><h2><strong>Separating inventory</strong></h2><p>Inventory management also doesn&#8217;t belong to the <code>PotionShop</code> class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!EpzM!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!EpzM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png 424w, https://substackcdn.com/image/fetch/$s_!EpzM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png 848w, https://substackcdn.com/image/fetch/$s_!EpzM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png 1272w, https://substackcdn.com/image/fetch/$s_!EpzM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!EpzM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png" width="1456" height="749" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:749,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:107051,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.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_!EpzM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png 424w, https://substackcdn.com/image/fetch/$s_!EpzM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png 848w, https://substackcdn.com/image/fetch/$s_!EpzM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png 1272w, https://substackcdn.com/image/fetch/$s_!EpzM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf29f6b0-9f20-4050-ad34-e5d17e0d5c01_1470x756.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#18</figcaption></figure></div><p>The two loops in <code>.remove_stock()</code> are deliberate. If we reduced each quantity as we went, we could use some ingredients and then discover that there isn&#8217;t enough of another. The sale would fail, but the stock would already be partly changed. Checking every quantity first avoids that partial update.</p><p>We can see what happens when there isn&#8217;t enough stock:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YB2b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YB2b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png 424w, https://substackcdn.com/image/fetch/$s_!YB2b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png 848w, https://substackcdn.com/image/fetch/$s_!YB2b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png 1272w, https://substackcdn.com/image/fetch/$s_!YB2b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!YB2b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png" width="1200" height="882" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:882,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:59029,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.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_!YB2b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png 424w, https://substackcdn.com/image/fetch/$s_!YB2b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png 848w, https://substackcdn.com/image/fetch/$s_!YB2b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png 1272w, https://substackcdn.com/image/fetch/$s_!YB2b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcab5d3f7-32dc-47d0-8d8c-bb4876d4c4cd_1200x882.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#19</figcaption></figure></div><p>The operation fails before changing any stock:</p><pre><code>Not enough dragon_scale
{&#8217;moonflower&#8217;: 10, &#8216;dragon_scale&#8217;: 2}</code></pre><p>After a successful sale, a delivery can add stock again:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!s9HI!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!s9HI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!s9HI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!s9HI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!s9HI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!s9HI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/dfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:40617,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.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_!s9HI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!s9HI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!s9HI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!s9HI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdfd3e641-3a13-4a8f-8e9f-7a2b57d89040_1200x630.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#20</figcaption></figure></div><p>Here&#8217;s the output from this code:</p><pre><code>{&#8217;moonflower&#8217;: 13, &#8216;dragon_scale&#8217;: 0}</code></pre><p><code>Inventory</code> owns both the stock data and the operations that change its quantities. It does not need to know who bought the potion or whether the label is festive.</p><h2><strong>Separating prices and labels</strong></h2><p>Pricing has its own rules:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Eyj_!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Eyj_!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png 424w, https://substackcdn.com/image/fetch/$s_!Eyj_!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png 848w, https://substackcdn.com/image/fetch/$s_!Eyj_!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png 1272w, https://substackcdn.com/image/fetch/$s_!Eyj_!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Eyj_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png" width="1200" height="546" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:546,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:50656,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.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_!Eyj_!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png 424w, https://substackcdn.com/image/fetch/$s_!Eyj_!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png 848w, https://substackcdn.com/image/fetch/$s_!Eyj_!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png 1272w, https://substackcdn.com/image/fetch/$s_!Eyj_!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b369b2-2630-4406-8f3b-c6b8457415f4_1200x546.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#21</figcaption></figure></div><p>Once again, this class now has just one responsibility: to deal with the pricing.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!n5HU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!n5HU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png 424w, https://substackcdn.com/image/fetch/$s_!n5HU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png 848w, https://substackcdn.com/image/fetch/$s_!n5HU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png 1272w, https://substackcdn.com/image/fetch/$s_!n5HU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!n5HU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png" width="1200" height="420" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:420,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:31661,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.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_!n5HU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png 424w, https://substackcdn.com/image/fetch/$s_!n5HU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png 848w, https://substackcdn.com/image/fetch/$s_!n5HU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png 1272w, https://substackcdn.com/image/fetch/$s_!n5HU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6cd761b-90fb-435c-8180-34a4bafb4d8c_1200x420.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#22</figcaption></figure></div><p>You can check the pricing strategy works without having to sell a product and everything else.</p><pre><code>10.80</code></pre><p>Labels have their own rules too. You dealt with this earlier in the tutorial when you created <code>LabelMaker</code></p><p><code>PriceCalculator</code> and <code>LabelMaker</code> could both be functions here. We&#8217;re using classes because they act as collaborators that the shop receives from outside. Later, we&#8217;ll see how protocols or abstract base classes can describe interchangeable collaborators more explicitly. For now, the important point is the separation of responsibilities and not the fact that each responsibility has become a class.</p><p>Neither class needs an inventory, a sales ledger, or an owl.</p><h2><strong>Putting the shop back together</strong></h2><p>We still need something to coordinate the sale. First, we give the sales ledger and the notifier small, focused interfaces:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!w-Av!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!w-Av!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png 424w, https://substackcdn.com/image/fetch/$s_!w-Av!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png 848w, https://substackcdn.com/image/fetch/$s_!w-Av!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png 1272w, https://substackcdn.com/image/fetch/$s_!w-Av!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!w-Av!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png" width="1200" height="966" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:966,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:104177,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.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_!w-Av!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png 424w, https://substackcdn.com/image/fetch/$s_!w-Av!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png 848w, https://substackcdn.com/image/fetch/$s_!w-Av!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png 1272w, https://substackcdn.com/image/fetch/$s_!w-Av!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3ed530fd-6b12-4d0e-bf0e-ea09410a5101_1200x966.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#23</figcaption></figure></div><p>Notice the <code>"pending"</code> state in the ledger. Separating responsibilities does not make the sale process independent of anything else. Inventory has already changed before later steps run. Here, the narrower goal is to make notification failure visible so that the recorded sale can be investigated.</p><p>Now we can keep <code>PotionShop</code> as a thin coordinator. It still represents the sale process, but it delegates each part of that process to the object that owns the relevant behaviour:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FlUh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FlUh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png 424w, https://substackcdn.com/image/fetch/$s_!FlUh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png 848w, https://substackcdn.com/image/fetch/$s_!FlUh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png 1272w, https://substackcdn.com/image/fetch/$s_!FlUh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!FlUh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png" width="1254" height="1680" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1680,&quot;width&quot;:1254,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:174356,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.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_!FlUh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png 424w, https://substackcdn.com/image/fetch/$s_!FlUh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png 848w, https://substackcdn.com/image/fetch/$s_!FlUh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png 1272w, https://substackcdn.com/image/fetch/$s_!FlUh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F16815ce0-0924-4d23-a6ae-9e95af69305b_1254x1680.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#24</figcaption></figure></div><p>We can now assemble the shop and sell a potion:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!g4Hl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!g4Hl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png 424w, https://substackcdn.com/image/fetch/$s_!g4Hl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png 848w, https://substackcdn.com/image/fetch/$s_!g4Hl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png 1272w, https://substackcdn.com/image/fetch/$s_!g4Hl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!g4Hl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png" width="1200" height="1008" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1008,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:89560,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.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_!g4Hl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png 424w, https://substackcdn.com/image/fetch/$s_!g4Hl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png 848w, https://substackcdn.com/image/fetch/$s_!g4Hl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png 1272w, https://substackcdn.com/image/fetch/$s_!g4Hl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6b29ad29-0a9e-4e3d-aa41-e28050629c6c_1200x1008.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#25</figcaption></figure></div><p>Here&#8217;s the output:</p><pre><code>&#127769; Moon Festival Invisibility &#127769; &#163;10.80
Owl dispatched to Merlin
10.80
{&#8217;customer&#8217;: &#8216;Merlin&#8217;, &#8216;potion&#8217;: &#8216;invisibility&#8217;, &#8216;price&#8217;: Decimal(&#8217;10.80&#8217;), &#8216;notification&#8217;: &#8216;sent&#8217;}</code></pre><p>If notification fails after the ledger records the sale, the sale remains<br>visible with a pending notification:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FPq9!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FPq9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png 424w, https://substackcdn.com/image/fetch/$s_!FPq9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png 848w, https://substackcdn.com/image/fetch/$s_!FPq9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png 1272w, https://substackcdn.com/image/fetch/$s_!FPq9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!FPq9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png" width="1272" height="1008" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1008,&quot;width&quot;:1272,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:117521,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.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_!FPq9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png 424w, https://substackcdn.com/image/fetch/$s_!FPq9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png 848w, https://substackcdn.com/image/fetch/$s_!FPq9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png 1272w, https://substackcdn.com/image/fetch/$s_!FPq9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc9df1a3-caa7-46a3-accb-e566eefa5157_1272x1008.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#26</figcaption></figure></div><p>Here&#8217;s the output:</p><pre><code>Invisibility  &#163;12.00
{&#8217;customer&#8217;: &#8216;Merlin&#8217;, &#8216;potion&#8217;: &#8216;invisibility&#8217;, 
 &#8216;price&#8217;: Decimal(&#8217;12.00&#8217;), &#8216;notification&#8217;: &#8216;pending&#8217;}
&#8203;</code></pre><p>The coordinator still changes if the business process changes. That&#8217;s fine: coordinating a sale is its responsibility. But recipe changes belong in <code>RecipeBook</code>, inventory changes belong in <code>Inventory</code>, pricing changes belong in <code>PriceCalculator</code>, label changes belong in <code>LabelMaker</code>, and notification changes belong in <code>Notifier</code>.</p><h2><strong>The Single Responsibility Principle</strong></h2><p>This is the idea behind the Single Responsibility Principle:</p><blockquote><p>A class should have one reason to change.</p></blockquote><p>I always find these &#8220;official&#8221; definitions a bit cryptic when I read them at first. Here, &#8220;reason&#8221; is about the policy or stakeholder driving the change. The pricing rules may change because the shop owner changes the discounts. The label design may change because the person responsible for packaging wants something different. The notification service may change because the owls are on strike.</p><p>That does not mean that every class should have one method. Nor does it mean that every noun in the story needs its own class.</p><p><code>PriceCalculator</code> can have several related methods. <code>Inventory</code> can have several operations. The important question is whether the methods belong to the same coherent responsibility.</p><p>The thin <code>PotionShop</code> coordinator is also a class with a responsibility. It coordinates the sale. A change to that business process may quite reasonably affect it.</p><p>When unrelated changes keep arriving at the same class, the class becomes harder to test and more likely to break. Extract a collaborator when it may need to change for a different reason from the surrounding code, or when separating it makes an important test simpler. A good class name alone isn&#8217;t a reason to create one.</p><p>The potion shop did not become troublesome because it had a particular number of lines. It became troublesome because recipes, inventory, pricing, labels, sales, and notifications all had different reasons to change.</p><p>A useful question to ask is:</p><blockquote><p>What different kinds of change could affect this class?</p></blockquote><p>If the answers are &#8220;the pricing rules&#8221;, &#8220;the label design&#8221;, &#8220;the storage system&#8221;, and &#8220;the notification service&#8221;, you may have several responsibilities sharing one home.</p><p>And if the project keeps growing, we may need to rethink the floor plan.</p><div><hr></div><p><em>This is the first article in a series on the SOLID principles. I&#8217;ll look at what each principle means, but more importantly, why it matters and what can go wrong when we ignore it.</em></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!HPEi!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!HPEi!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!HPEi!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!HPEi!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!HPEi!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!HPEi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png" width="662" height="441.4848901098901" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:971,&quot;width&quot;:1456,&quot;resizeWidth&quot;:662,&quot;bytes&quot;:2668799,&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://www.thepythoncodingstack.com/i/217824232?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.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_!HPEi!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png 424w, https://substackcdn.com/image/fetch/$s_!HPEi!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png 848w, https://substackcdn.com/image/fetch/$s_!HPEi!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png 1272w, https://substackcdn.com/image/fetch/$s_!HPEi!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a545304-1e1b-4be2-a573-7abea67516c4_1536x1024.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em>Code in this article uses Python 3.14.</em></p><div><hr></div><p><em>Do you want to keep up with how Python programming and the art of making things are changing in this rapidly changing world? Then don&#8217;t miss out on the exclusive content for premium members here on The Python Coding Stack.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><p>I&#8217;ll be sharing more about how my programming, my daily work, and everything has changed over the recent months.</p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com/?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com/?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p><div><hr></div><h2><strong>Appendix: Code Blocks</strong></h2><h5><strong>Code Block #1</strong></h5><pre><code>from decimal import Decimal
&#8203;
class PotionShop:
    recipes = {
        &#8220;invisibility&#8221;: {
            &#8220;ingredients&#8221;: {
                &#8220;moonflower&#8221;: 2,
                &#8220;dragon_scale&#8221;: 2,
            },
            &#8220;price&#8221;: Decimal(&#8221;12.00&#8221;),
        }
    }
&#8203;
    def __init__(self):
        self.stock = {
            &#8220;moonflower&#8221;: 10,
            &#8220;dragon_scale&#8221;: 2,
        }
        self.sales = []
&#8203;
    def sell(self, potion_name, customer):
        potion = self.recipes[potion_name]
&#8203;
        for ingredient, quantity in potion[&#8221;ingredients&#8221;].items():
            if self.stock[ingredient] &lt; quantity:
                raise ValueError(f&#8221;Not enough {ingredient}&#8221;)
&#8203;
        for ingredient, quantity in potion[&#8221;ingredients&#8221;].items():
            self.stock[ingredient] -= quantity
&#8203;
        price = potion[&#8221;price&#8221;]
        self.sales.append((customer, potion_name, price))
&#8203;
        print(f&#8221;{potion_name.title()}\t&#163;{price:.2f}&#8221;)
        self.send_owl(
            customer,
            {&#8221;potion_name&#8221;: potion_name, &#8220;price&#8221;: price},
        )
&#8203;
        return price
&#8203;
    def send_owl(self, customer, message_content):
        print(f&#8221;Owl dispatched to {customer}&#8221;)
        return message_content</code></pre><h5><strong>Code Block #2</strong></h5><pre><code>shop = PotionShop()
print(shop.sell(&#8221;invisibility&#8221;, &#8220;Merlin&#8221;))</code></pre><h5><strong>Code Block #3</strong></h5><pre><code># ...
&#8203;
class PotionShop:
    # ...
&#8203;
    def sell(
            self,
            potion_name,
            customer,
            *,
            moon_festival=False,
    ):
        # ...
&#8203;
        label = potion_name.title()
        if moon_festival:
            label = f&#8221;&#127769; Moon Festival {label} &#127769;&#8221;
&#8203;
        print(f&#8221;{label}\t&#163;{price:.2f}&#8221;)
&#8203;
        # ...
    # ...</code></pre><h5><strong>Code Block #4</strong></h5><pre><code>shop = PotionShop()
print(shop.sell(&#8221;invisibility&#8221;, &#8220;Merlin&#8221;, moon_festival=True))</code></pre><h5><strong>Code Block #5</strong></h5><pre><code># ...
&#8203;
class LabelMaker:
    def make(self, potion_name, moon_festival=False):
        label = potion_name.title()
&#8203;
        if moon_festival:
            label = f&#8221;&#127769; Moon Festival {label} &#127769;&#8221;
&#8203;
        return label
&#8203;
# ...</code></pre><h5><strong>Code Block #6</strong></h5><pre><code>labels = LabelMaker()
assert labels.make(
    &#8220;invisibility&#8221;,
    moon_festival=True,
) == &#8220;&#127769; Moon Festival Invisibility &#127769;&#8221;</code></pre><h5><strong>Code Block #7</strong></h5><pre><code># ...
&#8203;
class PotionShop:
    # ...
&#8203;
    def __init__(self, label_maker):
        self.label_maker = label_maker
        # ...
&#8203;
    def sell(
            self,
            potion_name,
            customer,
            *,
            moon_festival=False,
    ):
        # ...
        label = self.label_maker.make(
            potion_name,
            moon_festival=moon_festival,
        )
        # ...
&#8203;
    # ...</code></pre><h5><strong>Code Block #8</strong></h5><pre><code>shop = PotionShop(LabelMaker())</code></pre><h5><strong>Code Block #9</strong></h5><pre><code># ...
&#8203;
class OwlUnavailable(Exception):
    pass
&#8203;
# ...
&#8203;
class PotionShop:
    # ...
&#8203;
    def __init__(self, label_maker, owl_available=True):
        self.label_maker = label_maker
        self.owl_available = owl_available
        # ...
&#8203;
    # ...
&#8203;
    def send_owl(self, customer, message_content):
        if not self.owl_available:
            raise OwlUnavailable(
                &#8220;The owls are currently unavailable&#8221;
            )
        print(f&#8221;Owl dispatched to {customer}&#8221;)
        return message_content</code></pre><h5><strong>Code Block #10</strong></h5><pre><code>shop = PotionShop(LabelMaker())
&#8203;
assert shop.sell(&#8221;invisibility&#8221;, &#8220;Merlin&#8221;) == Decimal(&#8221;12.00&#8221;)</code></pre><h5><strong>Code Block #11</strong></h5><pre><code>shop = PotionShop(LabelMaker(), owl_available=False)
&#8203;
assert shop.sell(&#8221;invisibility&#8221;, &#8220;Merlin&#8221;) == Decimal(&#8221;12.00&#8221;)</code></pre><h5><strong>Code Block #12</strong></h5><pre><code>class PotionShop:
    # ...
&#8203;
    def sell(
        self,
        potion_name,
        customer,
        *,
        moon_festival=False,
        own_cauldron=False,
    ):
        # ...
&#8203;
        price = potion[&#8221;price&#8221;]
&#8203;
        if own_cauldron:
            price = (price * Decimal(&#8221;0.90&#8221;)).quantize(Decimal(&#8221;0.01&#8221;))
&#8203;
        # ...
&#8203;
        return price
&#8203;
    # ...</code></pre><h5><strong>Code Block #13</strong></h5><pre><code>shop = PotionShop(LabelMaker())
print(
    shop.sell(
        &#8220;invisibility&#8221;,
        &#8220;Merlin&#8221;,
        own_cauldron=True,
    )
)</code></pre><h5><strong>Code Block #14</strong></h5><pre><code>shop = PotionShop(LabelMaker(), owl_available=False)
print(
    shop.sell(
        &#8220;invisibility&#8221;,
        &#8220;Merlin&#8221;,
        own_cauldron=True,
    )
)</code></pre><h5><strong>Code Block #15</strong></h5><pre><code>shop = PotionShop(LabelMaker(), owl_available=False)
try:
    print(
        shop.sell(
            &#8220;invisibility&#8221;,
            &#8220;Merlin&#8221;,
            own_cauldron=True,
        )
    )
except OwlUnavailable:
    print(&#8221;Catching the &#8216;OwlUnavailable&#8217; Exception&#8221;)
    print(shop.stock)
    print(shop.sales)</code></pre><h5><strong>Code Block #16</strong></h5><pre><code>class RecipeBook:
    def __init__(self):
        self.recipes = {
            &#8220;invisibility&#8221;: {
                &#8220;ingredients&#8221;: {
                    &#8220;moonflower&#8221;: 2,
                    &#8220;dragon_scale&#8221;: 2,
                },
                &#8220;price&#8221;: Decimal(&#8221;12.00&#8221;),
            }
        }
&#8203;
    def find(self, potion_name):
        return self.recipes[potion_name]</code></pre><h5><strong>Code Block #17</strong></h5><pre><code>recipe_book = RecipeBook()
assert recipe_book.find(&#8221;invisibility&#8221;)[&#8221;price&#8221;] == Decimal(&#8221;12.00&#8221;)</code></pre><h5><strong>Code Block #18</strong></h5><pre><code>class Inventory:
    def __init__(self, stock):
        self.stock = stock
&#8203;
    def remove_stock(self, ingredients):
        for ingredient, quantity in ingredients.items():
            if self.stock[ingredient] &lt; quantity:
                raise ValueError(f&#8221;Not enough {ingredient}&#8221;)
&#8203;
        for ingredient, quantity in ingredients.items():
            self.stock[ingredient] -= quantity
&#8203;
    def add_stock(self, ingredients):
        for ingredient, quantity in ingredients.items():
            self.stock[ingredient] = self.stock.get(ingredient, 0) + quantity</code></pre><h5><strong>Code Block #19</strong></h5><pre><code>inventory = Inventory({
    &#8220;moonflower&#8221;: 10,
    &#8220;dragon_scale&#8221;: 2,
})
&#8203;
try:
    inventory.remove_stock({
        &#8220;moonflower&#8221;: 2,
        &#8220;dragon_scale&#8221;: 3,
    })
except ValueError as error:
    print(error)
&#8203;
print(inventory.stock)</code></pre><h5><strong>Code Block #20</strong></h5><pre><code>inventory.remove_stock({
    &#8220;moonflower&#8221;: 2,
    &#8220;dragon_scale&#8221;: 2,
})
inventory.add_stock({&#8221;moonflower&#8221;: 5})
print(inventory.stock)</code></pre><h5><strong>Code Block #21</strong></h5><pre><code>class PriceCalculator:
    def calculate(self, recipe, own_cauldron=False):
        price = recipe[&#8221;price&#8221;]
&#8203;
        if own_cauldron:
            price = (
                price * Decimal(&#8221;0.90&#8221;)
            ).quantize(Decimal(&#8221;0.01&#8221;))
&#8203;
        return price</code></pre><h5><strong>Code Block #22</strong></h5><pre><code>pricing = PriceCalculator()
print(
    pricing.calculate(
        {&#8221;price&#8221;: Decimal(&#8221;12.00&#8221;)},
        own_cauldron=True,
    )
)</code></pre><h5><strong>Code Block #23</strong></h5><pre><code>class SalesLedger:
    def __init__(self):
        self.sales = []
&#8203;
    def record(self, customer, potion_name, price):
        sale = {
            &#8220;customer&#8221;: customer,
            &#8220;potion&#8221;: potion_name,
            &#8220;price&#8221;: price,
            &#8220;notification&#8221;: &#8220;pending&#8221;,
        }
        self.sales.append(sale)
        return sale
&#8203;
    def mark_notified(self, sale):
        sale[&#8221;notification&#8221;] = &#8220;sent&#8221;
&#8203;
class Notifier:
    def send(self, customer, potion_name, price):
        print(f&#8221;Owl dispatched to {customer}&#8221;)</code></pre><h5><strong>Code Block #24</strong></h5><pre><code>class PotionShop:
    def __init__(
        self,
        recipe_book,
        inventory,
        pricing,
        labels,
        ledger,
        notifier,
    ):
        self.recipe_book = recipe_book
        self.inventory = inventory
        self.pricing = pricing
        self.labels = labels
        self.ledger = ledger
        self.notifier = notifier
&#8203;
    def sell(self, potion_name, customer, *, moon_festival=False,
             own_cauldron=False):
        recipe = self.recipe_book.find(potion_name)
        self.inventory.remove_stock(recipe[&#8221;ingredients&#8221;])
&#8203;
        price = self.pricing.calculate(
            recipe,
            own_cauldron=own_cauldron,
        )
        label = self.labels.make(
            potion_name,
            moon_festival=moon_festival,
        )
        sale = self.ledger.record(customer, potion_name, price)
&#8203;
        print(f&#8221;{label}\t&#163;{price:.2f}&#8221;)
        self.notifier.send(customer, potion_name, price)
        self.ledger.mark_notified(sale)
&#8203;
        return price</code></pre><h5><strong>Code Block #25</strong></h5><pre><code>ledger = SalesLedger()
shop = PotionShop(
    RecipeBook(),
    Inventory({&#8221;moonflower&#8221;: 10, &#8220;dragon_scale&#8221;: 2}),
    PriceCalculator(),
    LabelMaker(),
    ledger,
    Notifier(),
)
&#8203;
print(
    shop.sell(
        &#8220;invisibility&#8221;,
        &#8220;Merlin&#8221;,
        moon_festival=True,
        own_cauldron=True,
    )
)
&#8203;
assert ledger.sales[0][&#8221;notification&#8221;] == &#8220;sent&#8221;
print(ledger.sales[0])</code></pre><h5><strong>Code Block #26</strong></h5><pre><code>class FailingNotifier:
    def send(self, customer, potion_name, price):
        raise OwlUnavailable(&#8221;The owls are currently unavailable&#8221;)
&#8203;
ledger = SalesLedger()
shop = PotionShop(
    RecipeBook(),
    Inventory({&#8221;moonflower&#8221;: 10, &#8220;dragon_scale&#8221;: 2}),
    PriceCalculator(),
    LabelMaker(),
    ledger,
    FailingNotifier(),
)
&#8203;
try:
    shop.sell(&#8221;invisibility&#8221;, &#8220;Merlin&#8221;)
except OwlUnavailable:
    pass
&#8203;
print(ledger.sales[0])
assert ledger.sales[0][&#8221;notification&#8221;] == &#8220;pending&#8221;</code></pre><p><em><a href="https://stephengruppetta.com/?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p>]]></content:encoded></item><item><title><![CDATA[Down The Iterator Rabbit Hole]]></title><description><![CDATA[Following the trail when you have a chain of iterators]]></description><link>https://www.thepythoncodingstack.com/p/down-the-iterator-rabbit-hole-python</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/down-the-iterator-rabbit-hole-python</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Thu, 04 Jun 2026 12:50:32 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!vA2Z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You know that street game where the performer (con artist?) has three opaque cups and a small ball. He places the cups upside down on the table, with the ball under one of the cups. He quickly shuffles the cups around and then asks the player to guess which cup has the ball. You&#8217;ve seen the game on TV, even if you&#8217;ve not seen it in real life.</p><p>Following what&#8217;s happening when you have a chain of iterators in Python can feel like playing that game. But, unlike the street game, there are no scams when you&#8217;re playing the iterator game. Let&#8217;s make sure you&#8217;ll always win.</p><p>I&#8217;ll keep this article short. I wrote many articles about iterables and iterators. If you need to refresh your memory, have a look at <a href="https://www.thepythoncodingstack.com/p/the-anatomy-of-a-for-loop">The Anatomy of a for Loop</a> and <a href="https://www.thepythoncodingstack.com/p/iterators-in-python-data-structure-6">A One-Way Stream of Data &#8226; Iterators in Python (Data Structure Categories #6)</a>.</p><h2><strong>Follow The Data in a Chain of Iterators</strong></h2><p>Let&#8217;s keep the example simple. Start with this list in a REPL session:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!bqeu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!bqeu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!bqeu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!bqeu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!bqeu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12687,&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://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.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_!bqeu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!bqeu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!bqeu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!bqeu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F946268b4-b00d-4e66-82b0-cd9ad1e673dc_1200x168.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></div><figcaption class="image-caption">All code blocks are available in text format at the end of this article &#8226; #1</figcaption></figure></div><p>A list is iterable. You can create an iterator from any iterable. Let&#8217;s create an iterator from this list:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0vvp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!0vvp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!0vvp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!0vvp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!0vvp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:10876,&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://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.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_!0vvp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!0vvp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!0vvp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!0vvp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a484c85-613d-458b-a515-0a18b8a22f7d_1200x210.png 1456w" sizes="100vw"></picture><div></div></div></div><figcaption class="image-caption">#2</figcaption></figure></div><p>The built-in function <code>iter()</code> creates an iterator from an iterable. Iterators don&#8217;t contain data. They don&#8217;t create copies of the data. They&#8217;re lightweight objects that create a stream. They&#8217;ll fetch data from the original source, which is the list <code>boring_numbers</code> in this case, as and when needed.</p><p>Iterators can only fetch an item once. So, they&#8217;re a one-way stream. Once you use an item, it&#8217;s gone from the iterator &#8211; but not from the original list, which remains unchanged.</p><p>Therefore, <code>first_iter</code> is an iterator that relies on data from the list <code>boring_numbers</code>. But let&#8217;s not fetch any items from the <code>first_iter</code> iterator. Not yet, anyway.</p><p>Create a second iterator. This time, you&#8217;ll use a generator expression. Generators are iterators, so you create a second iterator with this code:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gh5b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!gh5b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!gh5b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!gh5b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!gh5b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:13203,&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://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.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_!gh5b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!gh5b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!gh5b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!gh5b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc69303a5-8ecb-4676-b2ec-e8fe71412506_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#3</figcaption></figure></div><p>Note that the expression on the right-hand side of the equals sign is enclosed in parentheses &#8211; the round ones, to be clear. This is a generator expression, which creates a generator iterator. Read <a href="https://www.thepythoncodingstack.com/p/generators-in-python-data-structure-7">Pay As You Go &#8226; Generate Data Using Generators (Data Structure Categories #7)</a> for more on generators.</p><p>As we said, generators are iterators.</p><p>The <code>second_iter</code> iterator generates data from <code>first_iter</code>, which is itself an iterator. Iterators are also iterable, which is why you can use them directly in a <code>for</code> clause or anywhere else you&#8217;d generally use an iterable. The <code>second_iter</code> iterator will yield the values as floats. But you&#8217;ve not yielded any value from this iterator either. Not yet.</p><p>Let&#8217;s go a step further and create a third iterator, which is also a generator in this case. You build this third iterator from the second one, <code>second_iter</code>:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MiBd!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!MiBd!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!MiBd!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!MiBd!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!MiBd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:11981,&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://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.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_!MiBd!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!MiBd!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!MiBd!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!MiBd!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46aa982e-6786-4085-91d9-80ebcaf38bbd_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#4</figcaption></figure></div><p>The generator iterator <code>third_iter</code> yields the sum of <code>0.5</code> and the value yielded by <code>second_iter</code>.</p><p>Incidentally, I used a &#8220;standard&#8221; iterator and two generator iterators in this example. However, for the journey we&#8217;re following in this article, it doesn&#8217;t matter whether we&#8217;re using a basic iterator or a generator iterator. If you prefer, you can repeat this exercise with iterators you get from <code>iter()</code> directly.</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://buy.stripe.com/00g3de2iGdgg4gg7su&quot;,&quot;text&quot;:&quot;Support The Python Coding Stack&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://buy.stripe.com/00g3de2iGdgg4gg7su"><span>Support The Python Coding Stack</span></a></p><h2><strong>Don&#8217;t Blink &#8226; Follow the Data</strong></h2><p>You started with a list called <code>boring_numbers</code>. This data structure contains* the data. It&#8217;s where the data lives. We&#8217;ll be following the data in this section. So it&#8217;s important to know where it&#8217;s stored!</p><div><hr></div><p><em>*Note: Lists, like all data structures, don&#8217;t really contain data in the purest sense of the word. See <a href="https://www.thepythoncodingstack.com/p/whats-really-in-a-python-list">What&#8217;s In A List&#8212;Yes, But What&#8217;s Really In A Python List</a> for more on this. But in general, it&#8217;s fine to talk about a list &#8216;containing&#8217; items of data.</em></p><div><hr></div><p>You then create three iterators. The first uses data from <code>boring_numbers</code>. The second iterator uses data from the first. And the third iterator uses data from the second.</p><p>But you haven&#8217;t tried to fetch any value from any of the iterators yet.</p><p>Let&#8217;s look at what each iterator is doing at the moment before you fetch any values. The first iterator, <code>first_iter</code>, is pointing at the first item in <code>boring_numbers</code>. It&#8217;s ready to read this value and yield it.</p><p>The second iterator, <code>second_iter</code>, is pointing at the first item in <code>first_iter</code>. But <code>first_iter</code> doesn&#8217;t have any data. Iterators don&#8217;t have their own data. But that&#8217;s OK. Whenever <code>second_iter</code> needs to fetch the value, it will ask <code>first_iter</code> to fetch and yield its &#8220;first&#8221; value. I put &#8220;first&#8221; in quotation marks because you&#8217;ll see later that this may or may not be the first value.</p><p>Finally, <code>third_iter</code> is pointing at the first item in <code>second_iter</code>. The same logic applies. When <code>third_iter</code> needs the first item, it will ask <code>second_iter</code> for its &#8220;first&#8221; item, and <code>second_iter</code> will need to ask <code>first_iter</code> for its &#8220;first&#8221; item. And <code>first_iter</code> is pointing at the first item in the list <code>boring_numbers</code>.</p><p>Are you with me? Let&#8217;s complicate things a bit&#8230;</p><p>Note how your code so far includes the following lines:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!QrUQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!QrUQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!QrUQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!QrUQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!QrUQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:39100,&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://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.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_!QrUQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!QrUQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!QrUQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!QrUQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc6a8d744-1eb6-4ed5-aeff-7ce7b7a291c0_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#5</figcaption></figure></div><p>None of the iterators has yielded any value. For now.</p><p>Let&#8217;s jumble things up and start by fetching the first value from <code>second_iter</code>:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cSUf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!cSUf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!cSUf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!cSUf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!cSUf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:11072,&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://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.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_!cSUf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!cSUf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!cSUf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!cSUf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F603a95ea-8bc3-4566-ac9c-66e579caf0cc_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#6</figcaption></figure></div><p>You ask for the next value in <code>second_iter</code>, which is the first one since you haven&#8217;t yielded any values yet.</p><p>As you&#8217;ve seen earlier, <code>second_iter</code> needs the first value from <code>first_iter</code>. So, behind the scenes, Python calls <code>next(first_iter)</code>, which yields the first item from <code>boring_numbers</code>.</p><p>So, <code>first_iter</code> reads the first value from <code>boring_numbers</code>, which is the integer <code>1</code>, and it yields it to <code>second_iter</code>, which then yields the transformed version to the REPL as the return value of <code>next(second_iter)</code>. That&#8217;s why the output is the float <code>1.0</code>. The first iterator, <code>first_iter</code>, now moves to point at the second item in <code>boring_numbers</code>, ready for when it&#8217;s needed.</p><p>Note that <code>boring_numbers</code> doesn&#8217;t change in this process. The first item in <code>boring_numbers</code> remains there. It doesn&#8217;t disappear.</p><p>So far, so good?</p><p>Continue in the same REPL session and try the following:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ROlh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!ROlh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!ROlh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!ROlh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ROlh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:9739,&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://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.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_!ROlh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!ROlh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!ROlh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!ROlh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7bb21a58-a80e-404e-9d5d-5921f2b2e278_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#7</figcaption></figure></div><p>You ask <code>third_iter</code> to give you its &#8220;next&#8221; value. You haven&#8217;t used <code>third_iter</code> anywhere so far. So, you might expect it to yield the &#8220;first&#8221; value.</p><p>And it does.</p><p>But its interpretation of what&#8217;s the &#8220;first&#8221; item may be different to what you expect.</p><p>Let&#8217;s follow the data. When you call <code>next(third_iter)</code>, the third iterator asks <code>second_iter</code> for its <em>next</em> item. The second iterator, <code>second_iter</code>, relies on <code>first_iter</code>, so it asks <code>first_iter</code> for its <em>next</em> item. And <code>first_iter</code>, as you may recall, is currently pointing at the second item in <code>boring_numbers</code>, which is the integer <code>2</code>.</p><p>So:</p><ol><li><p>The first iterator <code>first_iter</code> gets the integer <code>2</code> from <code>boring_numbers</code> and yields it to <code>second_iter</code>. And <code>first_iter</code> now points at the third item in <code>boring_numbers</code>.</p></li><li><p>Then, <code>second_iter</code> transforms this value into a float and yields <code>2.0</code> to <code>third_iter</code>.</p></li><li><p>Finally, <code>third_iter</code> adds <code>0.5</code> to this value and yields <code>2.5</code>, which is what you see displayed in the REPL.</p></li></ol><p>When you called <code>next(second_iter)</code> earlier in the code, you used up the first item in <code>second_iter</code>, which in turn used up the first item in <code>first_iter</code>. Since this first value is gone and since <code>third_iter</code> depends on the data yielded by <code>second_iter</code> and <code>first_iter</code>, the earlier call to <code>next(second_iter)</code> also affected the iterator that&#8217;s downstream, <code>third_iter</code>.</p><p>What will happen if you call <code>next(first_iter)</code> now? Try to follow the data in your head before trying it out or reading on.</p><p>.</p><p>.</p><p>Have you worked it out?</p><p>.</p><p>.</p><p>Let&#8217;s run the code:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Bknm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!Bknm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!Bknm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!Bknm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Bknm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:9303,&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://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.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_!Bknm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!Bknm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!Bknm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!Bknm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F57a33a2d-b878-40d8-85b7-86e89d89411e_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#8</figcaption></figure></div><p>Although it&#8217;s the first time you explicitly use <code>first_iter</code> in your code, you already used two of its values when your code yielded values from iterators downstream. Therefore, the <em>next</em> item in <code>first_iter</code> is the third item in <code>boring_numbers</code>, the integer <code>3</code>.</p><p>Let&#8217;s finish with one more expression, still running in the same REPL session:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!s8bc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!s8bc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!s8bc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!s8bc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!s8bc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:9602,&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://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.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_!s8bc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!s8bc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!s8bc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!s8bc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fd3c45c-e3ff-4874-adcb-fa0ab2493900_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#9</figcaption></figure></div><p>You call <code>next(third_iter)</code>, which asks <code>second_iter</code> for its <em>next</em> item. And <code>second_iter</code> asks <code>first_iter</code> for its <em>next</em> item. At this stage in the process, <code>first_iter</code> is pointing at the fourth item in the original source of data, which is the list <code>boring_numbers</code>. That&#8217;s why the output is <code>4.5</code>.</p><h3><strong>Independent Iterators</strong></h3><p>Consider the following code, which is similar to the one you wrote above but has one extra line:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SapE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SapE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!SapE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!SapE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!SapE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!SapE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png" width="1200" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:82830,&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://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.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_!SapE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!SapE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!SapE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!SapE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe4459cfa-8992-4175-8fa1-93794bcfac01_1200x756.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#11</figcaption></figure></div><p>The iterators <code>first_iter</code> and <code>another_first_iter</code> both use the same source of data, <code>boring_numbers</code>. However, they are independent iterators. Note that when you use up some of the elements in <code>first_iter</code>, the independent <code>another_first_iter</code> is not affected. The first time you ask for the first item in <code>another_first_iter</code>, you get the integer <code>1</code>.</p><h2><strong>Final Words</strong></h2><p>Iterators don&#8217;t contain data. They rely on data that&#8217;s stored elsewhere. But you can have a chain of iterators, each asking the previous one to yield a value. Weird things can happen if you&#8217;re not careful. But now you know how to follow the data when you have a chain of iterators.</p><p>As a rule of thumb, if you create an iterator that depends on another iterator, you should only use the final iterator to avoid these issues. So, in the example above, you should only yield values from <code>third_iter</code>.</p><p>Have a play with this example and make your own chains of iterators, too. And once you&#8217;re comfortable with this, get ready to be confused again with my next article, which will discuss <code>itertools.tee()</code>!</p><p>And next time you pass by someone in the street offering to let you play the three-cups-and-ball game, don&#8217;t feel overconfident because of your iterator knowledge &#8211; it won&#8217;t help you find the ball.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vA2Z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vA2Z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp 424w, https://substackcdn.com/image/fetch/$s_!vA2Z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp 848w, https://substackcdn.com/image/fetch/$s_!vA2Z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp 1272w, https://substackcdn.com/image/fetch/$s_!vA2Z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!vA2Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp" width="1456" height="819" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:819,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1030348,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/webp&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.thepythoncodingstack.com/i/200605229?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!vA2Z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp 424w, https://substackcdn.com/image/fetch/$s_!vA2Z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp 848w, https://substackcdn.com/image/fetch/$s_!vA2Z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp 1272w, https://substackcdn.com/image/fetch/$s_!vA2Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0f16f6-ea62-451b-9915-7c01b45de7f8_2048x1152.webp 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em>Code in this article uses Python 3.14</em></p><p><em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify</a>.</em> <em>[Affiliate link]</em></p><p><em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts</a>, videos, a members&#8217; forum, and more.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p><p>Further reading related to this article&#8217;s topic:</p><ul><li><p><a href="https://www.thepythoncodingstack.com/p/the-anatomy-of-a-for-loop">The Anatomy of a for Loop</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/iterators-in-python-data-structure-6">A One-Way Stream of Data &#8226; Iterators in Python (Data Structure Categories #6)</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/generators-in-python-data-structure-7">Pay As You Go &#8226; Generate Data Using Generators (Data Structure Categories #7)</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/whats-really-in-a-python-list">What&#8217;s In A List&#8212;Yes, But What&#8217;s </a><em><a href="https://www.thepythoncodingstack.com/p/whats-really-in-a-python-list">Really</a></em><a href="https://www.thepythoncodingstack.com/p/whats-really-in-a-python-list"> In A Python List</a></p></li></ul><div><hr></div><h2><strong>Appendix: Code Blocks</strong></h2><h5><strong>Code Block #1</strong></h5><pre><code>boring_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]</code></pre><h5><strong>Code Block #2</strong></h5><pre><code># ...
first_iter = iter(boring_numbers)</code></pre><h5><strong>Code Block #3</strong></h5><pre><code># ...
second_iter = (float(number) for number in first_iter)</code></pre><h5><strong>Code Block #4</strong></h5><pre><code># ...
third_iter = (num + 0.5 for num in second_iter)</code></pre><h5><strong>Code Block #5</strong></h5><pre><code>boring_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
first_iter = iter(boring_numbers)
second_iter = (float(number) for number in first_iter)
third_iter = (num + 0.5 for num in second_iter)</code></pre><h5><strong>Code Block #6</strong></h5><pre><code># ...
next(second_iter)
# 1.0</code></pre><h5><strong>Code Block #7</strong></h5><pre><code># ...
next(third_iter)
# 2.5</code></pre><h5><strong>Code Block #8</strong></h5><pre><code># ...
next(first_iter)
# 3</code></pre><h5><strong>Code Block #9</strong></h5><pre><code># ...
next(third_iter)
# 4.5</code></pre><h5><strong>Code Block #10</strong></h5><pre><code>boring_numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
first_iter = iter(boring_numbers)
another_first_iter = iter(boring_numbers)
second_iter = (float(number) for number in first_iter)
third_iter = (num + 0.5 for num in second_iter)
next(second_iter)
# 1.0
next(third_iter)
# 2.5
next(first_iter)
# 3
next(third_iter)
# 4.5
next(another_first_iter)
# 1</code></pre><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p>]]></content:encoded></item><item><title><![CDATA[Do You Get It Now?]]></title><description><![CDATA[Python's `.__getitem__()`, `.__getattr__()`, `.__getattribute__()`, and `.__get__()` &#8226; What's The Difference? &#8226; Let's clear the confusion]]></description><link>https://www.thepythoncodingstack.com/p/do-you-get-it-now-getitem-getattr-getattribute-get</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/do-you-get-it-now-getitem-getattr-getattribute-get</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Mon, 04 May 2026 11:59:43 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!FUK2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When you decide to learn about Python&#8217;s special methods, you have to choose which ones to learn first. Some are more straightforward than others. It makes sense to prioritise them.</p><p>However, there are some headaches and rabbit holes along the way.</p><p>And one of these challenges is when you start exploring the &#8220;get*&#8221; dunder methods. You come across <code>.__getitem__()</code>, <code>.__getattr__()</code>, <code>.__getattribute__()</code>, and <code>.__get__()</code> and you think:</p><blockquote><p>&#8220;Aren&#8217;t they all the same thing? They&#8217;re all &#8216;getting&#8217; stuff, right?&#8221;</p></blockquote><p>Well, yes, they&#8217;re all &#8220;getting stuff&#8221;, which is why they have &#8220;get&#8221; in their names. But, as you probably guessed by now, they do different things.</p><h2><strong>One Deals With </strong><code>[]</code><strong> &#8226; The Others Deal With </strong><code>.</code></h2><p>Let&#8217;s start with the odd one out, which is also possibly the least challenging of the lot. The <code>.__getitem__()</code> special method deals with the square bracket notation, <code>[]</code>, which you place after an object&#8217;s name. These are the square brackets you use to get an item from a list or a dictionary, say. You&#8217;ll see later that the other special methods with &#8220;get&#8221; in their name deal with the dot, <code>.</code>, which you use in a different context in Python.</p><p>With lists, or any other sequence, you use the square brackets with an index that represents the position of an item within the data structure. So, <code>numbers[0]</code> gives you the value of the first item in <code>numbers</code> if <code>numbers</code> is a sequence.</p><p>With dictionaries, or mappings in general, you place the key inside the square brackets to fetch the value associated with that key, such as <code>points["Sam"]</code>, which gives the value associated with the key <code>"Sam"</code> if it exists.</p><p>Let&#8217;s explore a custom class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Jsas!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Jsas!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!Jsas!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!Jsas!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!Jsas!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Jsas!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:41152,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.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_!Jsas!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!Jsas!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!Jsas!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!Jsas!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd238b6ff-1c70-43c9-9eb3-0ec3e0640304_1200x630.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">All code blocks are available in text format at the end of this article &#8226; #1</figcaption></figure></div><p>You pass a mapping to <code>PointsTable</code> when creating an instance of the class. The data is stored as a dictionary in the <code>._data</code> attribute.</p><p>Now, let&#8217;s say you&#8217;d like to access points from a <code>PointsTable</code> instance using the square bracket notation, as you would do with a dictionary:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UacJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!UacJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!UacJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!UacJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!UacJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:9725,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.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_!UacJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!UacJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!UacJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!UacJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2ed7c264-0362-4b9e-8c92-5bfd4eafb883_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#2</figcaption></figure></div><p>Unfortunately, this doesn&#8217;t work:</p><pre><code>Traceback (most recent call last):
  ...
    print(table[&#8221;Mark&#8221;])
          ~~~~~^^^^^^^^
TypeError: &#8216;PointsTable&#8217; object is not subscriptable</code></pre><p>The <code>PointsTable</code> instance is not a dictionary. It includes a dictionary as a data attribute. The <code>PointsTable</code> object itself is not subscriptable, which means you can&#8217;t use the square bracket notation to fetch an item.</p><p>When Python sees the square bracket notation after an object identifier, such as <code>table</code>, it calls the class&#8217;s <code>.__getitem__()</code> special method. If it&#8217;s not there, as in this case, Python raises a <code>TypeError</code> saying the object is not subscriptable.</p><p>But what does this tell you? If you want to use the square brackets notation, you just need to define <code>.__getitem__()</code> in the class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WK4y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WK4y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png 424w, https://substackcdn.com/image/fetch/$s_!WK4y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png 848w, https://substackcdn.com/image/fetch/$s_!WK4y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png 1272w, https://substackcdn.com/image/fetch/$s_!WK4y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!WK4y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png" width="1200" height="840" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:840,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:61146,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.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_!WK4y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png 424w, https://substackcdn.com/image/fetch/$s_!WK4y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png 848w, https://substackcdn.com/image/fetch/$s_!WK4y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png 1272w, https://substackcdn.com/image/fetch/$s_!WK4y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0fdd839-3e4b-4cf7-a6b1-47e7e05195ef_1200x840.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#3</figcaption></figure></div><p>Now, Python finds the <code>.__getitem__()</code> special method. It takes whatever you placed within the square brackets and passes it as an argument to <code>.__getitem__()</code>. Therefore, <code>table["Mark"]</code> returns whatever the call to <code>PointsTable.__getitem__(table, "Mark")</code> returns:</p><pre><code>17</code></pre><p>The code outputs Mark&#8217;s points. The <code>PointsTable</code> class is now subscriptable since it has a <code>.__getitem__()</code> special method. The term <em>item</em> generally refers to the objects contained within a data structure. Therefore, <code>__getitem__()</code> is there to let you <em>get an item</em> from within a data structure.</p><p>Let&#8217;s make this example a bit more interesting before we move on to the other special methods with &#8220;get&#8221; in their name.</p><p>Try the following:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tkur!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!tkur!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!tkur!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!tkur!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!tkur!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12188,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.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_!tkur!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!tkur!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!tkur!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!tkur!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf45cd02-ccb8-49cd-b722-045b4f629ed7_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#4</figcaption></figure></div><p>This raises an error:</p><pre><code>Traceback (most recent call last):
  File ..., line 18, in &lt;module&gt;
    print(table[&#8221;Mark&#8221;, &#8220;Stephen&#8221;])
          ~~~~~^^^^^^^^^^^^^^^^^^^
  File ..., line 6, in __getitem__
    return self._data[item]
           ~~~~~~~~~~^^^^^^
KeyError: (&#8217;Mark&#8217;, &#8216;Stephen&#8217;)</code></pre><p>There&#8217;s no key equal to <code>("Mark", "Stephen")</code>. So, you get a <code>KeyError</code>. Note how Python places parentheses around the two names when showing you the <code>KeyError</code>, even though you didn&#8217;t use the parentheses within the square brackets in <code>table["Mark", "Stephen"]</code>. This gives you a clue to what&#8217;s happening. But let&#8217;s explore this so we&#8217;re sure and we don&#8217;t just rely on our hunches:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!eCzw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eCzw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png 424w, https://substackcdn.com/image/fetch/$s_!eCzw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png 848w, https://substackcdn.com/image/fetch/$s_!eCzw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png 1272w, https://substackcdn.com/image/fetch/$s_!eCzw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!eCzw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png" width="1200" height="714" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:714,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:61008,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.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_!eCzw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png 424w, https://substackcdn.com/image/fetch/$s_!eCzw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png 848w, https://substackcdn.com/image/fetch/$s_!eCzw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png 1272w, https://substackcdn.com/image/fetch/$s_!eCzw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F976f6780-c9c5-4ba1-90fd-53ae281eae8d_1200x714.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#5</figcaption></figure></div><p>You add two <code>print()</code> calls in <code>.__getitem__()</code>. Here&#8217;s what they print out before Python raises the <code>KeyError</code>:</p><pre><code>item=(&#8217;Mark&#8217;, &#8216;Stephen&#8217;)
type(item)=&lt;class &#8216;tuple&#8217;&gt;</code></pre><p>The object Python passes to <code>.__getitem__()</code> is the tuple <code>("Mark", "Stephen")</code>. You decide to make your <code>PointsTable</code> class super-flexible so you can include more than one name within the square brackets notation:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GN9V!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GN9V!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png 424w, https://substackcdn.com/image/fetch/$s_!GN9V!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png 848w, https://substackcdn.com/image/fetch/$s_!GN9V!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png 1272w, https://substackcdn.com/image/fetch/$s_!GN9V!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!GN9V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png" width="1200" height="798" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:798,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:80562,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.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_!GN9V!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png 424w, https://substackcdn.com/image/fetch/$s_!GN9V!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png 848w, https://substackcdn.com/image/fetch/$s_!GN9V!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png 1272w, https://substackcdn.com/image/fetch/$s_!GN9V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3f5248c-f575-409f-9317-f1d096d3d981_1200x798.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#6</figcaption></figure></div><p>The <code>.__getitem__()</code> method now checks whether <code>item</code> is a tuple first. If it is, then <code>.__getitem__()</code> returns a tuple with all the values. If <code>item</code> is not a tuple, then it must be just a single key, and the square brackets behave in the normal way:</p><pre><code>(17, 20)
(22, 20, 19)
17</code></pre><p>But note that you can no longer use an actual tuple as a dictionary key. This is fine in this example since all the keys are strings with people&#8217;s names.</p><p>So, <code>.__getitem__()</code> gives you full control over what happens when you use the square brackets notation to fetch an item from an object. Now, let&#8217;s move on to the other &#8220;get*&#8221; special methods.</p><div><hr></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://buy.stripe.com/00g3de2iGdgg4gg7su&quot;,&quot;text&quot;:&quot;Support The Python Coding Stack&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://buy.stripe.com/00g3de2iGdgg4gg7su"><span>Support The Python Coding Stack</span></a></p><div><hr></div><h2><strong>Accessing Data Using The Dot Notation, </strong><code>.</code></h2><p>You decide you also want <code>PointsTable</code> to work with the dot notation, so that you can use <code>table.Mark</code> to get the number of points Mark has.</p><p>Note that I&#8217;m adding more features to this class to demonstrate various special methods in this article. I&#8217;m not suggesting it&#8217;s necessarily always desirable to try to be too fancy with your classes!</p><p>Let&#8217;s try it out directly first, without making any changes to the class:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!nohu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc743712-9d55-4eac-9780-240c7c76a2db_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!nohu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc743712-9d55-4eac-9780-240c7c76a2db_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!nohu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc743712-9d55-4eac-9780-240c7c76a2db_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!nohu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc743712-9d55-4eac-9780-240c7c76a2db_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!nohu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc743712-9d55-4eac-9780-240c7c76a2db_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cc743712-9d55-4eac-9780-240c7c76a2db_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8794,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc743712-9d55-4eac-9780-240c7c76a2db_1200x210.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_!nohu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc743712-9d55-4eac-9780-240c7c76a2db_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!nohu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc743712-9d55-4eac-9780-240c7c76a2db_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!nohu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc743712-9d55-4eac-9780-240c7c76a2db_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!nohu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc743712-9d55-4eac-9780-240c7c76a2db_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#7</figcaption></figure></div><p>Unfortunately, <code>table.Mark</code> raises an error:</p><pre><code>Traceback (most recent call last):
  File ..., line 32, in &lt;module&gt;
    print(table.Mark)
          ^^^^^^^^^^
AttributeError: &#8216;PointsTable&#8217; object has no attribute &#8216;Mark&#8217;</code></pre><p>Python is looking for an attribute called <code>Mark</code>. Attributes are the things you can access using the dot notation in Python. Typically, these are data attributes, methods, properties, and other things you can access using the dot. However, as with everything else, Python provides special methods to handle this. But this is where it gets a bit complicated.</p><h3><code>.__getattr__()</code></h3><p>Let&#8217;s take this one step at a time. Let&#8217;s add the <code>.__getattr__()</code> special method. You can guess that this special method name stands for <em>get attribute</em> (but it&#8217;s not the only special method that stands for <em>get attribute</em>!) Let&#8217;s add this method:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tgaB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tgaB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png 424w, https://substackcdn.com/image/fetch/$s_!tgaB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png 848w, https://substackcdn.com/image/fetch/$s_!tgaB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png 1272w, https://substackcdn.com/image/fetch/$s_!tgaB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!tgaB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png" width="1200" height="1176" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1176,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:124295,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.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_!tgaB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png 424w, https://substackcdn.com/image/fetch/$s_!tgaB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png 848w, https://substackcdn.com/image/fetch/$s_!tgaB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png 1272w, https://substackcdn.com/image/fetch/$s_!tgaB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd594fd71-9cb2-4a19-b1ec-a5cf54680da4_1200x1176.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#8</figcaption></figure></div><p>The <code>.__getattr__()</code> special method has a <code>print()</code> call to show when it&#8217;s called. This line is not required, but it will help you figure out when Python calls this special method. It&#8217;s a way of peeking into Python&#8217;s inner workings! For completeness, I added a similar line to <code>.__getitem__()</code> as well.</p><p>There are two <code>print()</code> calls at the bottom: one uses the square brackets notation, which you dealt with in the previous section, and the other uses the dot notation. Now, both work:</p><pre><code>Calling __getitem__ with argument item=&#8217;Mark&#8217;
17
Calling __getattr__ with argument name=&#8217;Mark&#8217;
17</code></pre><p>As you&#8217;ve seen in the previous section, the square brackets notation relies on <code>.__getitem__()</code>.</p><p>And as the third and fourth lines in this printout show, Python used <code>.__getattr__()</code> to deal with <code>table.Mark</code>.</p><p>Python passed the attribute name to the <code>.__getattr__()</code> special method&#8217;s <code>name</code> parameter. This method then fetches the value associated with this name from the dictionary <code>._data</code>.</p><p>This trick only works for keys that are valid attribute names and that don&#8217;t clash with real attributes or methods. That&#8217;s one reason dictionary-style access is often preferable for arbitrary user data. But let&#8217;s stick with this exercise in this article.</p><p>Also, you wrote the code such that if <code>self._data[name]</code> raises a <code>KeyError</code>, then <code>.__getattr__()</code> raises an <code>AttributeError</code>, which is what you&#8217;d expect if you try to use a name that&#8217;s not an attribute after the dot:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UFQW!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!UFQW!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!UFQW!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!UFQW!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!UFQW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8922,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.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_!UFQW!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!UFQW!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!UFQW!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!UFQW!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe07165cb-89fe-48a3-9200-e21d9bc291ae_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#9</figcaption></figure></div><p>This raises an <code>AttributeError</code>:</p><pre><code>AttributeError: &#8216;PointsTable&#8217; object has no attribute &#8216;Matilda&#8217;</code></pre><p>It seems that <code>.__getattr__()</code> is analogous to <code>.__getitem__()</code> &#8211; the first deals with <code>.</code> and the second with <code>[]</code>. But...</p><p>But things are a bit more complex. What if you try to access a standard attribute, say a data attribute or a method? You haven&#8217;t defined any methods in this class, but you do have a data attribute, <code>._data</code>. It&#8217;s marked with a leading underscore, showing you shouldn&#8217;t access it directly. But you can &#8220;break the rules&#8221;. Python won&#8217;t stop you:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hBj-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!hBj-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!hBj-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!hBj-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!hBj-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8126,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.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_!hBj-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!hBj-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!hBj-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!hBj-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae2dc4d9-5285-4e91-aba6-09f5d5b915f0_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#10</figcaption></figure></div><p>The output is the following:</p><pre><code>{&#8217;Stephen&#8217;: 20, &#8216;Mark&#8217;: 17, &#8216;Kate&#8217;: 19, &#8216;Sarah&#8217;: 22}</code></pre><p>Perhaps, this is not surprising. But note that there&#8217;s no printout that says that <code>.__getattr__()</code> was called, as you got when you used <code>table.Mark</code>. Let&#8217;s look at both outputs together:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7mTC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!7mTC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!7mTC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!7mTC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!7mTC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:13926,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.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_!7mTC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!7mTC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!7mTC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!7mTC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F27b2ee66-3944-473f-a6b1-579871c9536b_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#11</figcaption></figure></div><p>The output now is the following:</p><pre><code>Calling __getattr__ with argument name=&#8217;Mark&#8217;
17
{&#8217;Stephen&#8217;: 20, &#8216;Mark&#8217;: 17, &#8216;Kate&#8217;: 19, &#8216;Sarah&#8217;: 22}</code></pre><p>Python called the <code>.__getattr__()</code> special method when you accessed <code>.Mark</code>, but not when you accessed <code>._data</code>.</p><p>This means there&#8217;s something else happening behind the scenes.</p><h3><code>.__getattribute__()</code></h3><p>This is where <code>.__getattribute__()</code> enters the scene. No prizes for guessing that this method name stands for <em>get attribute</em>, but then so did <code>.__getattr__()</code>. This is confusing.</p><p>And here&#8217;s the thing. It&#8217;s <code>.__getattribute__()</code> that gets called each and every time you use the dot notation with an instance. Let&#8217;s define it:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DwOO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DwOO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.png 424w, https://substackcdn.com/image/fetch/$s_!DwOO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.png 848w, https://substackcdn.com/image/fetch/$s_!DwOO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.png 1272w, https://substackcdn.com/image/fetch/$s_!DwOO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!DwOO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.png" width="1236" height="924" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d84a1462-4308-4235-adc5-6dea98293219_1236x924.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:924,&quot;width&quot;:1236,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:75526,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.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_!DwOO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.png 424w, https://substackcdn.com/image/fetch/$s_!DwOO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.png 848w, https://substackcdn.com/image/fetch/$s_!DwOO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.png 1272w, https://substackcdn.com/image/fetch/$s_!DwOO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd84a1462-4308-4235-adc5-6dea98293219_1236x924.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#12</figcaption></figure></div><p>Note that this code breaks lots of things as it is now. We&#8217;ll fix it soon. Let&#8217;s first look at the output from this code:</p><pre><code>Calling __getattribute__ with argument name=&#8217;Mark&#8217;
None
Calling __getattribute__ with argument name=&#8217;_data&#8217;
None</code></pre><p>As you can see, Python calls <code>.__getattribute__()</code> for both <code>table.Mark</code> and <code>table._data</code>. However, the current <code>.__getattribute__()</code> method does nothing else. Therefore, it returns <code>None</code>. You&#8217;ll see soon that this is a bigger problem than you might think.</p><p>Let&#8217;s try using the dot notation to access an attribute that doesn&#8217;t exist:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ORHL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!ORHL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!ORHL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!ORHL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ORHL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19171,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.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_!ORHL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!ORHL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!ORHL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!ORHL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58038f2d-a8f0-4b1c-81ac-1fc5067d4b35_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#13</figcaption></figure></div><p>Every time you use the dot, <code>.</code>, Python calls <code>.__getattribute__()</code>, which, for now, does nothing except print out the self-serving statement to show it was called:</p><pre><code>Calling __getattribute__ with argument name=&#8217;Mark&#8217;
None
Calling __getattribute__ with argument name=&#8217;_data&#8217;
None
Calling __getattribute__ with argument name=&#8217;Janine&#8217;
None</code></pre><p>Therefore, you can&#8217;t access any attribute at the moment. All data attributes and methods are out of reach. You should be careful when overriding <code>.__getattribute__()</code>. In fact, you&#8217;ll rarely need to write your own <code>.__getattribute__()</code>.</p><p>Let&#8217;s fix this code by calling <code>object.__getattribute__()</code> from within <code>PointsTable.__getattribute__()</code>. Recall that all Python classes inherit from <code>object</code>. And <code>object.__getattribute__()</code> is where the important logic that Python uses to decide what to do when you use the <code>.</code> lives. You can access <code>object</code> using <code>super()</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_!-ER0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-ER0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png 424w, https://substackcdn.com/image/fetch/$s_!-ER0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png 848w, https://substackcdn.com/image/fetch/$s_!-ER0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png 1272w, https://substackcdn.com/image/fetch/$s_!-ER0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!-ER0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png" width="1236" height="924" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:924,&quot;width&quot;:1236,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:77908,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.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_!-ER0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png 424w, https://substackcdn.com/image/fetch/$s_!-ER0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png 848w, https://substackcdn.com/image/fetch/$s_!-ER0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png 1272w, https://substackcdn.com/image/fetch/$s_!-ER0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d686747-479b-4efa-8c4c-3b77b22bad98_1236x924.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#14</figcaption></figure></div><p>Note that in this class, <code>.__getattribute__()</code> is not doing anything different to the default version except for printing out a statement. I&#8217;m using this for demonstration purposes only.</p><p>Let&#8217;s deal with one <code>print()</code> call at a time. The code above includes <code>print(table._data)</code>. You&#8217;re fetching the value of a data attribute:</p><pre><code>Calling __getattribute__ with argument name=&#8217;_data&#8217;
{&#8217;Stephen&#8217;: 20, &#8216;Mark&#8217;: 17, &#8216;Kate&#8217;: 19, &#8216;Sarah&#8217;: 22}</code></pre><p>Python calls <code>PointsTable.__getattribute__()</code>, which in turn calls the base class&#8217;s <code>object.__getattribute__()</code>. This special method recognises that <code>._data</code> is an instance variable and fetches its value from the object&#8217;s <code>.__dict__</code>.</p><p>But let&#8217;s see what happens with the <code>.Mark</code> attribute access. Recall that <code>.Mark</code> is not a data attribute or method:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YSbV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!YSbV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!YSbV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!YSbV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!YSbV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8794,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.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_!YSbV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!YSbV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!YSbV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!YSbV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7369d87f-c3ac-4252-85b8-665a45655cf0_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#15</figcaption></figure></div><p>Here&#8217;s the output now. Look at the various printouts, too:</p><pre><code>Calling __getattribute__ with argument name=&#8217;Mark&#8217;
Calling __getattr__ with argument name=&#8217;Mark&#8217;
Calling __getattribute__ with argument name=&#8217;_data&#8217;
17</code></pre><p>When Python sees <code>table.Mark</code>, it calls <code>PointsTable.__getattribute__(table, "Mark")</code>. This call gives rise to the first line printed out above. The base class&#8217;s <code>.__getattribute__()</code> doesn&#8217;t recognise <code>"Mark"</code> as a data attribute, a method name, or anything else it&#8217;s expecting (such as descriptors, which we will discuss soon). So, <code>object.__getattribute__()</code> actually raises an <code>AttributeError</code> in this case, which you can&#8217;t see in the output above.</p><p>That&#8217;s because when <code>.__getattribute__()</code> raises an <code>AttributeError</code> during normal attribute access using the dot, Python checks whether there&#8217;s a <code>.__getattr__()</code> defined. If there is, it uses it as a fallback. That&#8217;s what happens in this case. You can see that <code>.__getattr__()</code> is called next &#8211; that&#8217;s the second line printed out above.</p><p>But <code>.__getattr__()</code> contains this line: <code>return self._data[name]</code>. There&#8217;s a dot in that line, too. So Python needs to access <code>.__getattribute__()</code> again, this time using <code>"_data"</code> as the argument. Since <code>._data</code> is a data attribute, <code>object.__getattribute__()</code> doesn&#8217;t need to use <code>.__getattr__()</code> as a fallback since it knows how to deal with data attributes.</p><p>Confused? You&#8217;re not alone. This is confusing, I know. And there&#8217;s a bit more. But we&#8217;ll make sure things are clear by the end of this article.</p><p>But first, let&#8217;s focus on <code>table.Mark</code> again and let&#8217;s comment out, just for now, the definition of <code>.__getattr__()</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_!MknK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!MknK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png 424w, https://substackcdn.com/image/fetch/$s_!MknK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png 848w, https://substackcdn.com/image/fetch/$s_!MknK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png 1272w, https://substackcdn.com/image/fetch/$s_!MknK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!MknK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png" width="1236" height="1218" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1218,&quot;width&quot;:1236,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:120637,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.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_!MknK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png 424w, https://substackcdn.com/image/fetch/$s_!MknK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png 848w, https://substackcdn.com/image/fetch/$s_!MknK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png 1272w, https://substackcdn.com/image/fetch/$s_!MknK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbedfef1d-4c6b-43a6-b630-400bd8b8c16b_1236x1218.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#16</figcaption></figure></div><p>The base class&#8217;s <code>.__getattribute__()</code> method works hard to determine whether <code>"Mark"</code> is an attribute it expects. It doesn&#8217;t find it, and now, there&#8217;s no fallback <code>.__getattr__()</code>, so Python raises an error:</p><pre><code>Calling __getattribute__ with argument name=&#8217;Mark&#8217;
Calling __getattribute__ with argument name=&#8217;__dict__&#8217;
Calling __getattribute__ with argument name=&#8217;__class__&#8217;
Traceback (most recent call last):
  ...
AttributeError: &#8216;PointsTable&#8217; object has no attribute &#8216;Mark&#8217;</code></pre><p>You can see a couple of extra printouts, too. These are side effects of Python preparing the error message since we get the printout each time Python uses the dot notation, even when it does so behind the scenes. Let&#8217;s not go too far down the rabbit hole in this article. We may never come out again if we go too deep!</p><p>You&#8217;ve seen that when you use the dot notation, Python calls <code>object.__getattribute__()</code> eventually. That&#8217;s why you should include <code>super().__getattribute__()</code> when you override this special method, unless you have a clear (niche) reason why you don&#8217;t want to do this. This special method looks in a number of places for the attribute. I&#8217;m going to skip a few steps in the hierarchy for now. But we&#8217;ll revisit these in the next section (remember, we&#8217;re not done yet since there&#8217;s still <code>.__get__()</code> to deal with).</p><p>The <code>.__getattribute__()</code> special method looks for instance attributes. Let&#8217;s temporarily turn <code>.Mark</code> into an instance attribute:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!coz6!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!coz6!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png 424w, https://substackcdn.com/image/fetch/$s_!coz6!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png 848w, https://substackcdn.com/image/fetch/$s_!coz6!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png 1272w, https://substackcdn.com/image/fetch/$s_!coz6!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!coz6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png" width="1236" height="966" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:966,&quot;width&quot;:1236,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:86426,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.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_!coz6!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png 424w, https://substackcdn.com/image/fetch/$s_!coz6!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png 848w, https://substackcdn.com/image/fetch/$s_!coz6!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png 1272w, https://substackcdn.com/image/fetch/$s_!coz6!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06fa5c82-d0cd-4a53-8d76-cc9c486429ed_1236x966.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#17</figcaption></figure></div><p>Now, <code>.Mark</code> is a data attribute, so <code>.__getattribute__()</code> finds it:</p><pre><code>Calling __getattribute__ with argument name=&#8217;Mark&#8217;
This is Mark as a data attribute</code></pre><p>If it&#8217;s not an instance variable, <code>object.__getattribute__()</code> also checks whether it&#8217;s a class attribute. Let&#8217;s test 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_!lD3k!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lD3k!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png 424w, https://substackcdn.com/image/fetch/$s_!lD3k!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png 848w, https://substackcdn.com/image/fetch/$s_!lD3k!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png 1272w, https://substackcdn.com/image/fetch/$s_!lD3k!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!lD3k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png" width="1236" height="1050" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1050,&quot;width&quot;:1236,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:92656,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.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_!lD3k!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png 424w, https://substackcdn.com/image/fetch/$s_!lD3k!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png 848w, https://substackcdn.com/image/fetch/$s_!lD3k!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png 1272w, https://substackcdn.com/image/fetch/$s_!lD3k!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F92086ec8-a13c-470b-92aa-a9c986526ea9_1236x1050.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#18</figcaption></figure></div><p>Here&#8217;s the output:</p><pre><code>Calling __getattribute__ with argument name=&#8217;Mark&#8217;
This is Mark as a class attribute</code></pre><p>Note that the line in <code>.__init__()</code> that defines <code>.Mark</code> as a data attribute is commented out now because instance attributes take precedence over class attributes. Only when all else fails (including the steps I skipped for now), does Python check whether the fallback special method <code>.__getattr__()</code> is there.</p><p>So, when you use the dot notation for attribute access (the simplified version, for now):</p><ol><li><p>Python calls <code>.__getattribute__()</code></p></li><li><p>It checks for known attributes, such as instance attributes and class attributes (and a bit more &#8211; coming soon)</p></li><li><p>If it doesn&#8217;t find anything, then <code>.__getattribute__()</code> raises an <code>AttributeError</code>. However, Python does one final check before letting this error through to the user: is there a <code>.__getattr__()</code>? If there is, Python calls it to see whether it contains instructions for handling this unknown attribute.</p></li></ol><p>I&#8217;m simplifying slightly here. Descriptors complicate the order, and we&#8217;ll return to them in the next section.</p><p>Note that in real code, you rarely need to define <code>.__getattribute__()</code>. You can rely on the default provided in the <code>object</code> base class in most cases. Most custom attribute behaviour should use <code>.__getattr__()</code> rather than <code>.__getattribute__()</code>. Use <code>.__getattribute__()</code> only when you need to intercept every attribute access. There is rarely a need for this, though.</p><p>Common uses for <code>.__getattr__()</code> include delegating missing attributes to another object, implementing lazy loading, or exposing dynamic attributes from structured data.</p><p>Here&#8217;s the tidied-up code in full so far:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-J5g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-J5g!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png 424w, https://substackcdn.com/image/fetch/$s_!-J5g!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png 848w, https://substackcdn.com/image/fetch/$s_!-J5g!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png 1272w, https://substackcdn.com/image/fetch/$s_!-J5g!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!-J5g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png" width="1236" height="1596" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1596,&quot;width&quot;:1236,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:192027,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.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_!-J5g!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png 424w, https://substackcdn.com/image/fetch/$s_!-J5g!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png 848w, https://substackcdn.com/image/fetch/$s_!-J5g!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png 1272w, https://substackcdn.com/image/fetch/$s_!-J5g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbb191478-cb58-48dc-a1cd-9755b1dba0de_1236x1596.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#19</figcaption></figure></div><h3><strong>The Asymmetry Between </strong><code>.__getattr__()</code><strong> and </strong><code>.__setattr__()</code></h3><p>A short note: There&#8217;s an asymmetry between <code>.__getattr__()</code> and <code>.__setattr__()</code> despite their names following the same pattern. As you&#8217;ve seen above, <code>.__getattr__()</code> is only used as a fallback when <code>.__getattribute__()</code> doesn&#8217;t find the attribute through &#8220;normal routes&#8221;.</p><p>However, <code>.__setattr__()</code> doesn&#8217;t have a counterpart analogous to <code>.__getattribute__()</code>. Therefore, <code>.__setattr__()</code> is always used when setting the value of an attribute. Life is simpler in the &#8220;setting&#8221; world!</p><p>In this article, I&#8217;m focusing on the &#8220;getting&#8221; part of things, but some of the same logic applies to &#8220;setting&#8221;, too.</p><div class="pullquote"><p><em>All <a href="https://thepythoncodingplace.com?utm_source=the-python-coding-stack">The Python Coding Place</a> video courses are included into a single, cost-effective bundle. The courses cover beginner and intermediate level courses, and you also get access to a members-only forum.</em></p><p><a href="https://thepythoncodingplace.thinkific.com/enroll/2731141">Get All The Python Coding Place Courses in One Bundle</a></p></div><h2><strong>The Fourth Horseman: </strong><code>.__get__()</code></h2><p>I&#8217;ve had this article in my pipeline here on <em>The Python Coding Stack</em> for a very long time. But I never wrote it because I knew that dealing with <code>.__get__()</code> would be a pain and would need a lot of time and space. However, in March, I published <a href="https://www.thepythoncodingstack.com/p/python-descriptors-the-price-is-right">The Weird and Wonderful World of Descriptors in Python</a>. If you haven&#8217;t read that article yet, well, now is the time!</p><p>And therefore I can cheat in this article. I can avoid talking about <code>.__get__()</code> in detail. What follows in this section is a summary of the world of descriptors. See the full article for more details.</p><p>If a class has <code>.__get__()</code>, it&#8217;s a descriptor class. If it only has <code>.__get__()</code> and it does not define <code>.__set__()</code> or <code>.__delete__()</code>, which are the other methods that make up the descriptor protocol, then the class creates <em>non-data descriptors</em>. Classes that include <code>.__set__()</code> or <code>.__delete__()</code> create <em>data descriptors</em>. This distinction matters when we get back to <code>.__getattribute__()</code> and the order it uses to look for known attributes.</p><p>Let&#8217;s explore this with a dummy example. This code defines two descriptor classes and another class to test the priority order that <code>object.__getattribute__()</code> uses for different attribute types:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UR6A!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UR6A!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.png 424w, https://substackcdn.com/image/fetch/$s_!UR6A!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.png 848w, https://substackcdn.com/image/fetch/$s_!UR6A!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.png 1272w, https://substackcdn.com/image/fetch/$s_!UR6A!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!UR6A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.png" width="1362" height="1890" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/597a1293-508e-4371-9740-e538e926372f_1362x1890.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1890,&quot;width&quot;:1362,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:273781,&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://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.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_!UR6A!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.png 424w, https://substackcdn.com/image/fetch/$s_!UR6A!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.png 848w, https://substackcdn.com/image/fetch/$s_!UR6A!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.png 1272w, https://substackcdn.com/image/fetch/$s_!UR6A!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F597a1293-508e-4371-9740-e538e926372f_1362x1890.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#20</figcaption></figure></div><p><code>DataDescriptor</code> defines <code>.__get__()</code> and <code>.__set__()</code> methods, which is why it creates data descriptors. However, <code>NonDataDescriptor</code> creates non-data descriptors since the class only defines <code>.__get__()</code>.</p><p>All the special methods in all classes (except <code>.__init__()</code>) have <code>print()</code> calls so you can see when Python calls them. Before we look at the output from this code, let&#8217;s review the five attributes you use in the <code>print()</code> calls and where they appear in the class definitions:</p><ol><li><p><code>.first</code> is defined as a data descriptor at the top of the <code>TestingAttributeAccess</code> class. Recall from the article on descriptors that you initially define descriptors as class attributes within a class. You also assign a value to <code>.first</code> within the class&#8217;s <code>.__init__()</code>. More on this soon.</p></li><li><p><code>.second</code> is also defined as a descriptor at the top of the <code>TestingAttributeAccess</code> class, but it&#8217;s a non-data descriptor since the <code>NonDataDescriptor</code> class only defines <code>.__get__()</code>. You also assign a value to <code>self.second</code> within <code>.__init__()</code>. We&#8217;ll see how the class actually deals with <code>.second</code> soon, since it treats it differently from <code>.first</code>.</p></li><li><p><code>.third</code> is also defined as a non-data descriptor. However, there is no other assignment to <code>third</code> within <code>.__init__()</code>. This is the key difference between <code>.second</code> and <code>.third</code> in this code.</p></li><li><p><code>.fourth</code> is a class attribute. It&#8217;s not a descriptor and it&#8217;s not an instance attribute.</p></li><li><p><code>.fifth</code> is not defined anywhere in the class, but you still call <code>print(test.fifth)</code>.</p></li></ol><p>Let&#8217;s look at the whole output from this code and then break it down into steps later:</p><pre><code>Calling DataDescriptor.__set__ with value=&#8221;&#8217;first&#8217;: a data attribute defined in .__init__&#8221;

Printing `test.first`
Calling __getattribute__ with argument name=&#8217;first&#8217;
Calling DataDescriptor.__get__
This is the Data Descriptor

Printing `test.second`
Calling __getattribute__ with argument name=&#8217;second&#8217;
&#8216;second&#8217;: a data attribute defined in .__init__

Printing `test.third`
Calling __getattribute__ with argument name=&#8217;third&#8217;
Calling NonDataDescriptor.__get__
This is the Non-Data Descriptor

Printing `test.fourth`
Calling __getattribute__ with argument name=&#8217;fourth&#8217;
I&#8217;m just a normal class attribute!

Printing `test.fifth`
Calling __getattribute__ with argument name=&#8217;fifth&#8217;
Calling __getattr__ with argument name=&#8217;fifth&#8217;
This is the fallback value from __getattr__</code></pre><p>There&#8217;s plenty to digest there. So, let&#8217;s break it down in stages.</p><h3><strong>0. Creating an instance of </strong><code>TestingAttributeAccess</code></h3><p>I want to focus on the &#8220;getting&#8221; bit from the various <code>print()</code> calls. However, there&#8217;s this line output first, so let&#8217;s deal with it, too:</p><pre><code>Calling DataDescriptor.__set__ with value=&#8221;&#8217;first&#8217;: a data attribute defined in .__init__&#8221;</code></pre><p>This happens when you create the instance of <code>TestingAttributeAccess</code> and assign it to the variable name <code>test</code>. Why? Because <code>first</code> has already been defined as a data descriptor at the time of the class definition. Therefore, when you assign a value to <code>.first</code> during initialisation, the descriptor protocol kicks in.</p><p>When you call <code>TestingAttributeAccess()</code>, Python calls the class&#8217;s <code>.__init__()</code> and soon finds this expression: <code>self.first = ...</code></p><p>Therefore, Python calls <code>DataDescriptor.__set__()</code> to set the value of this attribute. Note that <code>DataDescriptor.__set__()</code> doesn&#8217;t really set anything in this case. Normally, something more meaningful would happen in <code>.__set__()</code>. See <a href="https://www.thepythoncodingstack.com/p/python-descriptors-the-price-is-right">The Weird and Wonderful World of Descriptors in Python</a> for more on this.</p><h3><strong>1. </strong><code>test.first</code></h3><p>The next section in the code&#8217;s output is the following:</p><pre><code>Printing `test.first`
Calling __getattribute__ with argument name=&#8217;first&#8217;
Calling DataDescriptor.__get__
This is the Data Descriptor</code></pre><p>This output is created when you write <code>print(test.first)</code>. The dot notation triggers Python to call <code>.__getattribute__()</code>. So, let&#8217;s start exploring the hierarchy of checks in <code>.__getattribute__()</code>. What does this special method look for first?</p><p><strong>The </strong><em><strong>first</strong></em><strong> thing </strong><code>.__getattribute__()</code><strong> checks is whether the attribute is a data descriptor.</strong></p><p>Since <code>.first</code> is a data descriptor, the search stops there. Python calls <code>DataDescriptor.__get__()</code> and returns whatever the <code>.__get__()</code> method returns. This is the string <code>"This is the Data Descriptor"</code> in this demo example.</p><h3><strong>2. </strong><code>test.second</code></h3><p>Let&#8217;s look at the next segment in the code&#8217;s output. This is generated when you call <code>print(test.second)</code>:</p><pre><code>Printing `test.second`
Calling __getattribute__ with argument name=&#8217;second&#8217;
&#8216;second&#8217;: a data attribute defined in .__init__</code></pre><p>You know the drill by now. The dot notation is the trigger that makes Python call <code>.__getattribute__()</code>. It checks whether the attribute is a data descriptor. But <code>.second</code> is not a data descriptor. You initially define it as a <em>non-data</em> descriptor. Since it&#8217;s definitely not a data descriptor, it&#8217;s time to move on to the second check in the hierarchy.</p><p><strong>The </strong><em><strong>second</strong></em><strong> thing </strong><code>.__getattribute__()</code><strong> checks is whether the attribute is an instance attribute.</strong></p><p>Is this attribute name in the object&#8217;s <code>.__dict__</code> dictionary? Instance attributes come second in the hierarchy. Now, you&#8217;ve seen that <code>.second</code> is not a data descriptor, which is why we moved to the second check. But is <code>test.second</code> an instance attribute or a non-data descriptor?</p><p>You can see from the printout that Python never called <code>NonDataDescriptor.__get__()</code> even though you originally defined <code>.second</code> as a <code>NonDataDescriptor</code> object. The swap occurred when you created the <code>TestingAttributeAccess</code> instance. Python calls the class&#8217;s <code>.__init__()</code>, which contains this assignment line: <code>self.second = ...</code>.</p><p>Since <code>.second</code> is not a data descriptor (it&#8217;s a non-data descriptor) and doesn&#8217;t have a <code>.__set__()</code>, the descriptor protocol doesn&#8217;t kick in here to set the value of this attribute. This is different from <code>.first</code>, which was a data descriptor and, therefore, its <code>.__set__()</code> was responsible for setting the value.</p><p>Since the <code>.second</code> non-data descriptor doesn&#8217;t have a <code>.__set__()</code>, Python does what it always does in these cases: it assigns the new object, the string <code>"'second': a data attribute defined in .__init__"</code>, to <code>test.second</code>. Therefore, <code>test.second</code> is now an instance attribute containing the string rather than the original non-data descriptor.</p><p>Although <code>test.second</code> would originally access the non-data descriptor, you created an instance attribute when you initialised the object. It&#8217;s now a data attribute, which is an instance attribute.</p><p>Note that <code>TestingAttributeAccess.second</code> is still there as a class attribute, and that&#8217;s still the non-data descriptor. But <code>test.second</code> now points to another object, the string.</p><p>Therefore, when later in the code you call <code>print(test.second)</code>, Python calls <code>.__getattribute__()</code> and starts looking through its hierarchy. It&#8217;s not a data descriptor. It is an instance attribute. Therefore, it returns its value.</p><h3><strong>3. </strong><code>test.third</code></h3><p>The next block of output is the one generated when you call <code>print(test.third)</code>. Recall that <code>.third</code> is a <code>NonDataDescriptor</code> object. So was <code>.second</code> initially. However, unlike <code>.second</code>, Python never creates an instance attribute that&#8217;s assigned to <code>test.third</code> since you don&#8217;t assign to <code>self.third</code> in <code>.__init__()</code>. Here&#8217;s the output:</p><pre><code>Printing `test.third`
Calling __getattribute__ with argument name=&#8217;third&#8217;
Calling NonDataDescriptor.__get__
This is the Non-Data Descriptor</code></pre><p>In <code>print(test.third)</code>, there&#8217;s a dot again, so Python calls <code>.__getattribute__()</code>. This method first checks whether <code>.third</code> is a data descriptor. It is not. Then it checks whether <code>.third</code> is an instance attribute. It is not. So...</p><p><strong>The </strong><em><strong>third</strong></em><strong> thing </strong><code>.__getattribute__()</code><strong> checks is whether the attribute is a non-data descriptor.</strong></p><p>Non-data descriptors come next in the hierarchy. That&#8217;s why you can see the printout saying that Python calls <code>NonDataDescriptor.__get__</code> and then prints the attribute&#8217;s value, which is the value it gets from the non-data descriptor&#8217;s <code>.__get__()</code>.</p><p>Incidentally, ordinary instance methods are functions that also implement the <code>.__get__()</code> special method. They are non-data descriptors. So, methods are found in this third check in the hierarchy of checks when you use the dot notation.</p><h3><strong>4. </strong><code>test.fourth</code></h3><p>It&#8217;s <code>test.fourth</code>&#8216;s turn. Here&#8217;s the output you get from <code>print(test.fourth)</code>:</p><pre><code>Printing `test.fourth`
Calling __getattribute__ with argument name=&#8217;fourth&#8217;
I&#8217;m just a normal class attribute!</code></pre><p>There&#8217;s a dot, so there&#8217;s a call to <code>.__getattribute__()</code> which checks whether <code>.fourth</code> is a data descriptor, an instance attribute, or a non-data descriptor, in that order. It&#8217;s none of these. Time for the fourth check.</p><p><strong>The </strong><em><strong>fourth</strong></em><strong> thing </strong><code>.__getattribute__()</code><strong> checks is whether the attribute is a class attribute.</strong></p><p>And look at that! The <code>.fourth</code> attribute is indeed a class attribute.</p><h3><strong>5. </strong><code>test.fifth</code></h3><p>And finally, it&#8217;s <code>.fifth</code>&#8216;s turn. You call <code>print(test.fifth)</code> and you get the following:</p><pre><code>Printing `test.fifth`
Calling __getattribute__ with argument name=&#8217;fifth&#8217;
Calling __getattr__ with argument name=&#8217;fifth&#8217;
This is the fallback value from __getattr__</code></pre><p>Yes, yes, there&#8217;s a dot again, so Python calls <code>.__getattribute__()</code>. No, it&#8217;s not a data descriptor. No, it&#8217;s not an instance attribute. No, it&#8217;s not a non-data descriptor. No, it&#8217;s not a class attribute. It&#8217;s nothing. The attribute <code>.fifth</code> doesn&#8217;t exist.</p><p><strong>When </strong><code>.__getattribute__()</code><strong> fails to find the attribute, Python calls </strong><code>.__getattr__()</code><strong> if this special method exists.</strong></p><p>And that&#8217;s it. Simple, eh?!?!</p><p>Let&#8217;s finish off by summarising the order in which Python deals with looking for attributes when you use the dot notation:</p><ol><li><p>The <em>first</em> thing <code>.__getattribute__()</code> checks is whether the attribute is a data descriptor.</p></li><li><p>The <em>second</em> thing <code>.__getattribute__()</code> checks is whether the attribute is an instance attribute.</p></li><li><p>The <em>third</em> thing <code>.__getattribute__()</code> checks is whether the attribute is a non-data descriptor.</p></li><li><p>The <em>fourth</em> thing <code>.__getattribute__()</code> checks is whether the attribute is a class attribute.</p></li><li><p>Finally, when <code>.__getattribute__()</code> fails to find the attribute, Python calls <code>.__getattr__()</code> if this special method exists.</p></li></ol><p>The fifth step occurs when you access attributes using the dot notation. If you call <code>.__getattribute__() </code>explicitly, which you rarely need to do, Python doesn&#8217;t automatically look for <code>.__getattr__()</code>.</p><p>Note that Python looks for descriptors, instance and class attributes in the class and its base classes, too, following the method resolution order.</p><h2><strong>Final Words</strong></h2><p>Wait for this. I&#8217;ve been waiting all article to write this:</p><blockquote><p>Now, you won&#8217;t <em>forget</em> the <em>four &#8220;get</em>*&#8221; special methods.</p></blockquote><p>Got it! (My son just walked out disapprovingly when he read this.)</p><p>You may never need to use all of these methods. Maybe you&#8217;ll never need to use any of them. But if you ever wondered why there are these four special methods with similar names, now you know what they do. And you dug a bit more underneath the Python surface along the way. And that&#8217;s always fun.</p><div class="pullquote"><p><em>Your call&#8230;</em></p><p><em>The Python Coding Place offers something for everyone:</em></p><p><em>&#8226; a super-personalised one-to-one 6-month mentoring option</em><br><em>$ 4,750</em></p><p><em>&#8226; individual one-to-one sessions</em><br><em>$ 125</em></p><p><em>&#8226; a self-led route with access to 60+ hrs of exceptional video courses and a support forum</em><br><em>$ 400</em></p><p><em><a href="https://thepythoncodingplace.com?utm_source=the-python-coding-stack">Which The Python Coding Place student are you?</a></em></p></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FUK2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FUK2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg 424w, https://substackcdn.com/image/fetch/$s_!FUK2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg 848w, https://substackcdn.com/image/fetch/$s_!FUK2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!FUK2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!FUK2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg" width="628" height="418.3791208791209" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:970,&quot;width&quot;:1456,&quot;resizeWidth&quot;:628,&quot;bytes&quot;:1156165,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.thepythoncodingstack.com/i/196397351?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.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_!FUK2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg 424w, https://substackcdn.com/image/fetch/$s_!FUK2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg 848w, https://substackcdn.com/image/fetch/$s_!FUK2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!FUK2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F708dc396-00c0-4ca1-85f4-3a00f69ca4f5_4936x3290.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em><a href="https://www.pexels.com/photo/an-abstract-painting-with-orange-and-blue-waves-21243683/">Photo by Robert Clark</a></em></p><div><hr></div><p><em>Code in this article uses Python 3.14</em></p><p><em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify</a>.</em> <em>[Affiliate link]</em></p><p><em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts</a>, videos, a members&#8217; forum, and more.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><p><em>You can also support this publication by making a <a href="https://buy.stripe.com/00g3de2iGdgg4gg7su">one-off contribution of any amount you wish</a>.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://buy.stripe.com/00g3de2iGdgg4gg7su&quot;,&quot;text&quot;:&quot;Support The Python Coding Stack&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://buy.stripe.com/00g3de2iGdgg4gg7su"><span>Support The Python Coding Stack</span></a></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p><p>Further reading related to this article&#8217;s topic:</p><ul><li><p><a href="https://www.thepythoncodingstack.com/p/python-getitem-special-method-library-manorhouse">The Manor House, the Oak-Panelled Library, the Vending Machine, and Python&#8217;s </a><strong>`</strong><code>_getitem__()`</code></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/python-descriptors-the-price-is-right">The Weird and Wonderful World of Descriptors in Python &#8226; The Price is Right</a></p></li></ul><div><hr></div><h2>Appendix: Code Blocks</h2><h5>Code Block #1</h5><pre><code><code>class PointsTable:
    def __init__(self, data):
        self._data = dict(data)

table = PointsTable(
    {
        "Stephen": 20,
        "Mark": 17,
        "Kate": 19,
        "Sarah": 22,
    }
)
</code></code></pre><h5>Code Block #2</h5><pre><code><code># ...
print(table["Mark"])
</code></code></pre><h5>Code Block #3</h5><pre><code><code>class PointsTable:
    def __init__(self, data):
        self._data = dict(data)

    def __getitem__(self, item):
        return self._data[item]

table = PointsTable(
    {
        "Stephen": 20,
        "Mark": 17,
        "Kate": 19,
        "Sarah": 22,
    }
)

print(table["Mark"])
</code></code></pre><h5>Code Block #4</h5><pre><code><code># ...
print(table["Mark", "Stephen"])
</code></code></pre><h5>Code Block #5</h5><pre><code><code>class PointsTable:
    def __init__(self, data):
        self._data = dict(data)

    def __getitem__(self, item):
        print(f"{item=}")
        print(f"{type(item)=}")
        return self._data[item]

table = PointsTable(
    # ...
)

print(table["Mark", "Stephen"])
</code></code></pre><h5>Code Block #6</h5><pre><code><code>class PointsTable:
    def __init__(self, data):
        self._data = dict(data)

    def __getitem__(self, item):
        if isinstance(item, tuple):
            return tuple(self._data[key] for key in item)
        return self._data[item]

table = PointsTable(
    # ...
)

print(table["Mark", "Stephen"])
print(table["Sarah", "Stephen", "Kate"])
print(table["Mark"])
</code></code></pre><h5>Code Block #7</h5><pre><code><code># ...
print(table.Mark)
</code></code></pre><h5>Code Block #8</h5><pre><code><code>class PointsTable:
    # ...

    def __getitem__(self, item):
        print(f"Calling __getitem__ with argument {item=}")
        if isinstance(item, tuple):
            return tuple(self._data[key] for key in item)
        return self._data[item]

    def __getattr__(self, name):
        print(f"Calling __getattr__ with argument {name=}")
        try:
            return self._data[name]
        except KeyError:
            raise AttributeError(
                f"'{type(self).__name__}' object has "
                f"no attribute '{name}'"
            ) from None

table = PointsTable(
    # ...
)

print(table["Mark"])
print(table.Mark)
</code></code></pre><h5>Code Block #9</h5><pre><code><code># ...
print(table.Matilda)
</code></code></pre><h5>Code Block #10</h5><pre><code><code># ...
print(table._data)
</code></code></pre><h5>Code Block #11</h5><pre><code><code># ...
print(table.Mark)
print(table._data)
</code></code></pre><h5>Code Block #12</h5><pre><code><code>class PointsTable:
    def __init__(self, data):
        self._data = dict(data)

    def __getitem__(self, item):
        # ...

    def __getattr__(self, name):
        # ...

    def __getattribute__(self, name):
        print(f"Calling __getattribute__ with argument {name=}")

table = PointsTable(
    # ...
)

print(table.Mark)
print(table._data)
</code></code></pre><h5>Code Block #13</h5><pre><code><code># ...
print(table.Mark)
print(table._data)
print(table.Janine)
</code></code></pre><h5>Code Block #14</h5><pre><code><code>class PointsTable:
    def __init__(self, data):
        self._data = dict(data)

    def __getitem__(self, item):
        # ...

    def __getattr__(self, name):
        # ...

    def __getattribute__(self, name):
        print(f"Calling __getattribute__ with argument {name=}")
        return super().__getattribute__(name)

table = PointsTable(
    # ...
)

print(table._data)
</code></code></pre><h5>Code Block #15</h5><pre><code><code># ...
print(table.Mark)
</code></code></pre><h5>Code Block #16</h5><pre><code><code>class PointsTable:
    def __init__(self, data):
        self._data = dict(data)

    def __getitem__(self, item):
        # ...

    # def __getattr__(self, name):
    #     print(f"Calling __getattr__ with argument {name=}")
    #     try:
    #         return self._data[name]
    #     except KeyError:
    #         raise AttributeError(
    #             f"'{type(self).__name__}' object has "
    #             f"no attribute '{name}'"
    #         ) from None

    def __getattribute__(self, name):
        print(f"Calling __getattribute__ with argument {name=}")
        return super().__getattribute__(name)

table = PointsTable(
    # ...
)

print(table.Mark)
</code></code></pre><h5>Code Block #17</h5><pre><code><code>class PointsTable:
    def __init__(self, data):
        self._data = dict(data)
        self.Mark = "This is Mark as a data attribute"

    def __getitem__(self, item):
        # ...

    # def __getattr__(self, name):
    # ...

    def __getattribute__(self, name):
        print(f"Calling __getattribute__ with argument {name=}")
        return super().__getattribute__(name)

table = PointsTable(
    # ...
)

print(table.Mark)
</code></code></pre><h5>Code Block #18</h5><pre><code><code>class PointsTable:
    Mark = "This is Mark as a class attribute"

    def __init__(self, data):
        self._data = dict(data)
        # self.Mark = "This is Mark as a data attribute"

    def __getitem__(self, item):
        # ...

    # def __getattr__(self, name):
    # ...

    def __getattribute__(self, name):
        print(f"Calling __getattribute__ with argument {name=}")
        return super().__getattribute__(name)

table = PointsTable(
    # ...
)

print(table.Mark)
</code></code></pre><h5>Code Block #19</h5><pre><code><code>class PointsTable:
    def __init__(self, data):
        self._data = dict(data)

    def __getitem__(self, item):
        print(f"Calling __getitem__ with argument {item=}")
        if isinstance(item, tuple):
            return tuple(self._data[key] for key in item)
        return self._data[item]

    def __getattr__(self, name):
        print(f"Calling __getattr__ with argument {name=}")
        try:
            return self._data[name]
        except KeyError:
            raise AttributeError(
                f"'{type(self).__name__}' object has "
                f"no attribute '{name}'"
            ) from None

    def __getattribute__(self, name):
        print(f"Calling __getattribute__ with argument {name=}")
        return super().__getattribute__(name)

table = PointsTable(
    {
        "Stephen": 20,
        "Mark": 17,
        "Kate": 19,
        "Sarah": 22,
    }
)

print(table._data)  # Only .__getattribute__() used
print(table.Mark)  # Fallback .__getattr__() needed here
</code></code></pre><h5>Code Block #20</h5><pre><code><code>class DataDescriptor:
    def __get__(self, instance, owner):
        print("Calling DataDescriptor.__get__")
        return "This is the Data Descriptor"

    def __set__(self, instance, value):
        print(f"Calling DataDescriptor.__set__ with {value=}")

class NonDataDescriptor:
    def __get__(self, instance, owner):
        print("Calling NonDataDescriptor.__get__")
        return "This is the Non-Data Descriptor"

class TestingAttributeAccess:
    first = DataDescriptor()
    second = NonDataDescriptor()
    third = NonDataDescriptor()
    fourth = "I'm just a normal class attribute!"

    def __init__(self):
        self.first = "'first': a data attribute defined in .__init__"
        self.second = "'second': a data attribute defined in .__init__"

    def __getattribute__(self, name):
        print(f"Calling __getattribute__ with argument {name=}")
        return super().__getattribute__(name)

    def __getattr__(self, name):
        print(f"Calling __getattr__ with argument {name=}")
        return "This is the fallback value from __getattr__"

test = TestingAttributeAccess()
print("\nPrinting `test.first`")
print(test.first)
print("\nPrinting `test.second`")
print(test.second)
print("\nPrinting `test.third`")
print(test.third)
print("\nPrinting `test.fourth`")
print(test.fourth)
print("\nPrinting `test.fifth`")
print(test.fifth)</code></code></pre><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p>]]></content:encoded></item><item><title><![CDATA[Doubling Down on Python in The Age of AI]]></title><description><![CDATA[&#8230;and why you haven&#8217;t seen AI posts on here (yet)]]></description><link>https://www.thepythoncodingstack.com/p/doubling-down-on-python-in-the-age</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/doubling-down-on-python-in-the-age</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Fri, 24 Apr 2026 08:53:41 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!19bs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you&#8217;ve been wondering where I&#8217;ve been, yes, it&#8217;s been quieter than usual around here. No dramatic reason. Just life, work, the usual stuff.</p><p>But one thing kept catching my attention: all the noise outside. Everyone&#8217;s talking about AI writing code, agents shipping products, the death of programming. And every so often, someone asks me &#8212; usually with that slightly guilty look of someone who thinks they&#8217;re about to insult my livelihood &#8212; &#8220;but do you really still need to <em>learn</em> Python? In this age?&#8221;</p><p>So I&#8217;ve been thinking about it. Properly. And I wanted to share where I&#8217;ve landed, because I think the answer matters and it&#8217;s different from what some hot takes suggest.</p><h2><strong>Do I still need to learn to code?</strong></h2><p>The way we write computer programs is changing. I don&#8217;t have a crystal ball for what programming looks like in five or ten years.</p><p>But here&#8217;s the thing: <em>neither does anyone else.</em></p><p>Here&#8217;s what I know from watching others and experimenting with AI tools in my own work: right now, the people getting the most out of AI are the ones who already know how to code.</p><p>Here&#8217;s the hierarchy as I see it today:</p><ul><li><p>No coding knowledge = Little benefit from AI</p></li><li><p>Little coding knowledge = Intermediate benefit from AI</p></li><li><p>Intermediate coding knowledge = Great benefit from AI</p></li><li><p>Great coding knowledge = Superpower-like benefit from AI</p></li></ul><p>We&#8217;re in an era where some coding knowledge takes you much further than it could have a few years ago. That&#8217;s not an argument against learning to code. It&#8217;s an argument for it.</p><p>&#8220;But what about those vibe coding people? They seem to be shipping things.&#8221; Some are. I&#8217;ll be honest about that.</p><p>The projects I&#8217;ve seen from pure vibe coders tend to be smaller, tend to follow well-trodden patterns, and often hit a ceiling when something goes slightly wrong or slightly off-piste. Which is fine for a side project. I just created a useful dashboard to help me organise my day the way I want to using this approach.</p><p>But it tells you something: the AI does the heavy lifting on the known stuff. The moment something needs genuine thinking, you need the human who knows what&#8217;s going on beneath the surface.</p><h2><strong>AI-Assisted Human Coding and Human-Assisted AI Coding</strong></h2><p>Most serious work right now is a partnership.</p><p>Sometimes it&#8217;s <em>AI-assisted human coding</em>. The human drives, AI assists.</p><p>Sometimes it&#8217;s <em>human-assisted AI programming</em>. The AI writes most of the code, but the human knows what to ask for, how to steer it toward good design, how to evaluate whether the output actually makes sense.</p><p>Even when the coding looks like it&#8217;s done by AI, the person prompting and reviewing it is generally an experienced programmer. They&#8217;ve learned enough Python to know what&#8217;s reasonable, what&#8217;s a red flag, and when the AI is confidently wrong.</p><p>I&#8217;ve been experimenting with agentic AI over the past few weeks. I&#8217;ve tackled side projects I&#8217;d never have had the time for before. I didn&#8217;t have the time to start then, let alone finish them. Some of that output will show up in other places &#8212; stay tuned! But not here. <em>The Python Coding Stack</em> is the place for <em>my</em> writing.</p><h2><strong>The Programming Mindset When Talking to AI Agents</strong></h2><p>Here&#8217;s one thing I noticed. Talking to AI agents isn&#8217;t like talking to humans. But it isn&#8217;t like talking to computers (a.k.a. programming) either.</p><p>You need both qualities at the same time.</p><p>You need the clarity and communication skills you&#8217;d use with a person &#8212; explaining context, setting direction, knowing what matters, using clear language.</p><p>And you need the precision you&#8217;d use when programming &#8212; no ambiguity, clear intent, structure.</p><p><strong>A good programmer who&#8217;s also a good communicator is the best human to work with AI agents.</strong></p><p>That&#8217;s not coincidental. The same thought habits that make you an effective programmer also make you an effective prompter and reviewer when AI is involved.</p><p>I&#8217;ll share some of the prompts I&#8217;m using in a future post and analyse them to discuss why I wrote what I wrote. Learning to code well gives you an unfair advantage in this new world.</p><h2><strong>There&#8217;s Never Been a Better Time to Learn Python</strong></h2><p>Here&#8217;s what I&#8217;ve convinced myself of after all this. <em>There&#8217;s never been a better time to learn Python.</em></p><p>A few years ago, you needed to reach an intermediate-to-advanced level before you could do something genuinely useful with Python. The bar was high. Now, with AI assistance, the bar is lower. Less Python knowledge takes you further than ever.</p><p>What used to need expertise can now be explored with curiosity and a bit of intermediate-ish-level Python.</p><p>That&#8217;s not replacing deeper learning. It&#8217;s making the entry point more accessible. And once you&#8217;re in, you can go as deep as you want.</p><p>So yes, I&#8217;ll keep coding in Python. Sometimes with a bit of help from AI. Sometimes with a lot of help from AI.</p><p>And yes, I&#8217;ll keep writing about Python here, as I&#8217;ve always done.</p><h2><strong>The Fun Factor</strong></h2><p>Here&#8217;s the thing we don&#8217;t talk about enough when discussing programming. It&#8217;s fun. It&#8217;s challenging. It&#8217;s rewarding. It&#8217;s fulfilling. It&#8217;s stimulating. It keeps my brain active.</p><p>I code because I enjoy it. I&#8217;ll keep writing about Python because I enojoy that, too,, and because I find value in sharing here &#8212; for myself and, hopefully, for you too.</p><p>Normal service resumes here. More Python posts coming. And maybe, just maybe, some of the AI things I&#8217;m learning will make their way in, too.</p><p><em>Psst&#8211;did you know you can become a premium member to be a part of The Club? It would mean so much to me!</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><p>Quick question:</p><div class="poll-embed" data-attrs="{&quot;id&quot;:501089}" data-component-name="PollToDOM"></div><p></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!19bs!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!19bs!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg 424w, https://substackcdn.com/image/fetch/$s_!19bs!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg 848w, https://substackcdn.com/image/fetch/$s_!19bs!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!19bs!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!19bs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg" width="599" height="490.9141672762741" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3361,&quot;width&quot;:4101,&quot;resizeWidth&quot;:599,&quot;bytes&quot;:3028108,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.thepythoncodingstack.com/i/195326850?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26c84d66-33d1-4bbc-9fa5-2e5e0f6ab8e0_4101x6151.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_!19bs!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg 424w, https://substackcdn.com/image/fetch/$s_!19bs!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg 848w, https://substackcdn.com/image/fetch/$s_!19bs!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!19bs!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa037bf24-5372-476e-9e60-b5516e5e1f7d_4101x3361.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em>Photo by <a href="https://www.pexels.com/photo/a-person-holding-a-pair-of-black-framed-eyeglasses-9929033/">Maksim Goncharenok</a></em></p><div><hr></div><p><em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts</a>, videos, a members&#8217; forum, and more.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><p><em>You can also support this publication by making a <a href="https://buy.stripe.com/00g3de2iGdgg4gg7su">one-off contribution of any amount you wish</a>.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://buy.stripe.com/00g3de2iGdgg4gg7su&quot;,&quot;text&quot;:&quot;Support The Python Coding Stack&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://buy.stripe.com/00g3de2iGdgg4gg7su"><span>Support The Python Coding Stack</span></a></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p>]]></content:encoded></item><item><title><![CDATA[The Weird and Wonderful World of Descriptors in Python • The Price is Right]]></title><description><![CDATA[The Weird and Wonderful World of Descriptors in Python &#8226; Let&#8217;s demystify one of the trickiest topics around]]></description><link>https://www.thepythoncodingstack.com/p/python-descriptors-the-price-is-right</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/python-descriptors-the-price-is-right</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Sun, 15 Mar 2026 21:27:03 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!Ohw0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You have a class called <code>Product</code> that has an attribute called <code>.selling_price</code>. You also have an instance of <code>Product</code> assigned to the variable name <code>coffee</code>.</p><p>What happens when you write <code>coffee.selling_price</code>?</p><p>Sure, I know you know. The code returns the value of the <code>.selling_price</code> attribute. But what <em>really</em> happens behind the scenes?</p><p>Python operations rely on special methods. The dot you use to access attributes is no exception. But strange and weird things can happen when you use the dot.</p><p>Normally, the <code>Product</code> class determines what happens when you write <code>coffee.selling_price</code>. It checks whether the instance has a <code>.selling_price</code> attribute, typically by looking in its <code>.__dict__</code> dictionary of attributes. If the instance doesn&#8217;t have this attribute, Python checks whether it&#8217;s a class attribute.</p><p>But sometimes the class doesn&#8217;t get to decide what happens when you write <code>coffee.selling_price</code>. The object in <code>.selling_price</code> could take control of the attribute lookup.</p><p>Let&#8217;s explore the weird and wonderful world of <strong>descriptors</strong> in Python. For such a long time, I struggled to understand descriptors. But, as with many topics, at some stage, everything clicks. The story makes sense. Hopefully, this article can help you make sense of descriptors.</p><p>But first, we&#8217;ll start with properties.</p><h2><strong>The </strong><code>Product</code><strong> Class</strong></h2><p>Let&#8217;s create a <code>Product</code> class to deal with products for sale in a shop:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BfEe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BfEe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.png 424w, https://substackcdn.com/image/fetch/$s_!BfEe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.png 848w, https://substackcdn.com/image/fetch/$s_!BfEe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.png 1272w, https://substackcdn.com/image/fetch/$s_!BfEe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!BfEe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.png" width="1254" height="378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d0e1dde7-b944-4d59-a580-18261074e809_1254x378.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:378,&quot;width&quot;:1254,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:38992,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.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_!BfEe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.png 424w, https://substackcdn.com/image/fetch/$s_!BfEe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.png 848w, https://substackcdn.com/image/fetch/$s_!BfEe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.png 1272w, https://substackcdn.com/image/fetch/$s_!BfEe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0e1dde7-b944-4d59-a580-18261074e809_1254x378.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">All code blocks are available in text format at the end of this article &#8226; #1</figcaption></figure></div><p>You create a <code>Product</code> instance by providing a name, a cost price, and a selling price. There&#8217;s a data attribute for each of these values. There&#8217;s also a <code>.profit_margin</code> data attribute.</p><p>However, there&#8217;s a serious flaw in this code. Have you spotted it?</p><p>Let&#8217;s try it out:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eLIA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc827430c-0b82-4f79-9be6-4761d4295b18_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!eLIA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc827430c-0b82-4f79-9be6-4761d4295b18_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!eLIA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc827430c-0b82-4f79-9be6-4761d4295b18_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!eLIA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc827430c-0b82-4f79-9be6-4761d4295b18_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!eLIA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc827430c-0b82-4f79-9be6-4761d4295b18_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c827430c-0b82-4f79-9be6-4761d4295b18_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:21022,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc827430c-0b82-4f79-9be6-4761d4295b18_1200x252.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_!eLIA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc827430c-0b82-4f79-9be6-4761d4295b18_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!eLIA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc827430c-0b82-4f79-9be6-4761d4295b18_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!eLIA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc827430c-0b82-4f79-9be6-4761d4295b18_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!eLIA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc827430c-0b82-4f79-9be6-4761d4295b18_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#2</figcaption></figure></div><p>This code outputs the following:</p><pre><code>coffee.profit_margin=2.0</code></pre><p>So far, so good. But now try the following update:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!35yN!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!35yN!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!35yN!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!35yN!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!35yN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:26865,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.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_!35yN!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!35yN!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!35yN!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!35yN!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe8c46b05-c06b-44f4-bee9-66a43c5caacc_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#3</figcaption></figure></div><p>Here&#8217;s the output from this version:</p><pre><code>coffee.profit_margin=2.0</code></pre><p>The profit margin still shows as &#163;2. This is incorrect since you modified the selling price to &#163;5.50 soon after creating the <code>Product</code> instance. The cost price is still &#163;2.50. Therefore, the profit margin should be &#163;3.</p><p>The <code>.profit_margin</code> data attribute is only calculated once in the <code>.__init__()</code> method, which is called when you create and initialise the object. The code doesn&#8217;t update the <code>.profit_margin</code> data attribute when you update the selling price.</p><p>You can choose to use a method instead of a data attribute, say <code>.calculate_profit_margin()</code>. However, you think the class&#8217;s interface would be neater and easier to use if <code>.profit_margin</code> were still a data attribute like <code>.cost_price</code> and <code>.selling_price</code>.</p><p>The solution is to create a <em>property</em>. I promise that this is related to this week&#8217;s topic &#8211; properties are a great stepping stone towards descriptors:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GaoC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GaoC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png 424w, https://substackcdn.com/image/fetch/$s_!GaoC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png 848w, https://substackcdn.com/image/fetch/$s_!GaoC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png 1272w, https://substackcdn.com/image/fetch/$s_!GaoC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!GaoC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png" width="1200" height="672" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:672,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:73998,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.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_!GaoC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png 424w, https://substackcdn.com/image/fetch/$s_!GaoC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png 848w, https://substackcdn.com/image/fetch/$s_!GaoC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png 1272w, https://substackcdn.com/image/fetch/$s_!GaoC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F37ae6495-b11e-4560-b937-cb01275a7887_1200x672.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#4</figcaption></figure></div><p>You start by creating a method called <code>.profit_margin()</code>. Note how you name this in the style of a data attribute rather than a method &#8211; it describes data rather than an action. However, you use the decorator <code>@property</code> to create a <code>property</code> object.</p><p>Whenever you access the <code>.profit_margin</code> attribute, without the parentheses, Python calls the <code>.profit_margin()</code> method behind the scenes. Therefore, each time you access the attribute <code>.profit_margin</code>, which is now a property, Python calculates and returns the current value:</p><pre><code>coffee.profit_margin=3.0</code></pre><p>The <code>.profit_margin</code> attribute looks and feels like a data attribute but behaves like a method.</p><p>There&#8217;s another benefit in this case. This attribute is read-only:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5ekJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!5ekJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!5ekJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!5ekJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!5ekJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8828,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.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_!5ekJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!5ekJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!5ekJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!5ekJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5f6e17b-5386-4bec-8d50-f9c8d8eba187_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#5</figcaption></figure></div><p>You try to assign a new value to the <code>.profit_margin</code> attribute, but Python raises an error:</p><pre><code>Traceback (most recent call last):
  ...
    coffee.profit_margin = 4
    ^^^^^^^^^^^^^^^^^^^^
AttributeError: property &#8216;profit_margin&#8217; of 
    &#8216;Product&#8217; object has no setter</code></pre><p>In this case, this is the desired behaviour since a user shouldn&#8217;t be able to set the profit margin directly. It should be calculated from the cost price and the selling price.</p><h3><strong>Validating Prices</strong></h3><p>But let&#8217;s move to the central theme of this article. You want to add validation to the prices. For example, you want to ensure they can&#8217;t be below zero.</p><p>Let&#8217;s work on the cost price only for now. The following version won&#8217;t work for the same reason you saw earlier:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ctat!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ctat!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.png 424w, https://substackcdn.com/image/fetch/$s_!ctat!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.png 848w, https://substackcdn.com/image/fetch/$s_!ctat!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.png 1272w, https://substackcdn.com/image/fetch/$s_!ctat!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ctat!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.png" width="1200" height="672" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/94061c25-f165-432e-a68a-e5a90140e452_1200x672.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:672,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69143,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.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_!ctat!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.png 424w, https://substackcdn.com/image/fetch/$s_!ctat!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.png 848w, https://substackcdn.com/image/fetch/$s_!ctat!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.png 1272w, https://substackcdn.com/image/fetch/$s_!ctat!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94061c25-f165-432e-a68a-e5a90140e452_1200x672.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#6</figcaption></figure></div><p>You add the validation in the <code>.__init__()</code> method. This will apply only to the initialisation process, not to any later changes to the cost price.</p><p>So, the validation works fine in this case:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IqGl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!IqGl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!IqGl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!IqGl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!IqGl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12126,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.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_!IqGl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!IqGl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!IqGl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!IqGl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb40667df-71a7-44e0-a9b2-8a5cb514484f_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#7</figcaption></figure></div><p>This raises the exception:</p><pre><code>Traceback (most recent call last):
  ...
ValueError: Cost price cannot be negative</code></pre><p>However, the code won&#8217;t stop you from changing the cost price to a negative value later:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CWwp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a38925-192b-4880-bbcd-acdc578b574e_1308x294.png 424w, https://substackcdn.com/image/fetch/$s_!CWwp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a38925-192b-4880-bbcd-acdc578b574e_1308x294.png 848w, https://substackcdn.com/image/fetch/$s_!CWwp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a38925-192b-4880-bbcd-acdc578b574e_1308x294.png 1272w, https://substackcdn.com/image/fetch/$s_!CWwp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a38925-192b-4880-bbcd-acdc578b574e_1308x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!CWwp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a38925-192b-4880-bbcd-acdc578b574e_1308x294.png" width="1308" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b0a38925-192b-4880-bbcd-acdc578b574e_1308x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1308,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:29677,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a38925-192b-4880-bbcd-acdc578b574e_1308x294.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_!CWwp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a38925-192b-4880-bbcd-acdc578b574e_1308x294.png 424w, https://substackcdn.com/image/fetch/$s_!CWwp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a38925-192b-4880-bbcd-acdc578b574e_1308x294.png 848w, https://substackcdn.com/image/fetch/$s_!CWwp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a38925-192b-4880-bbcd-acdc578b574e_1308x294.png 1272w, https://substackcdn.com/image/fetch/$s_!CWwp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb0a38925-192b-4880-bbcd-acdc578b574e_1308x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#8</figcaption></figure></div><p>Here&#8217;s the output:</p><pre><code>coffee.cost_price=-1</code></pre><p>Solution? Create a property:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8tzj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8tzj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!8tzj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!8tzj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!8tzj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!8tzj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png" width="1200" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:59455,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.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_!8tzj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!8tzj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!8tzj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!8tzj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F44ca994d-8612-4f6f-8ce0-261f8b4979f6_1200x756.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#9</figcaption></figure></div><p>Note that I removed the validation code from the <code>.__init__()</code> method. The definition of the <code>.cost_price</code> data attribute in <code>.__init__()</code> has also gone.</p><p>But what do you include in the <code>cost_price()</code> method? Unlike the <code>.profit_margin</code> property, which can be calculated from existing attributes, you still need somewhere to store the current value for the cost price. You still need a data attribute that you create in the <code>.__init__()</code> method.</p><p>You can create a <em>non-public</em> data attribute:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YjSH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YjSH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!YjSH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!YjSH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!YjSH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!YjSH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png" width="1200" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:69170,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.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_!YjSH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!YjSH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!YjSH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!YjSH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8a060f66-3fda-4a4e-bd9c-3d9465d1f03c_1200x756.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#10</figcaption></figure></div><p>The data attribute <code>._cost_price</code> has a leading underscore, which is a Python convention indicating that the user shouldn&#8217;t access this attribute directly. Python doesn&#8217;t prevent the user from accessing this non-public attribute, but the leading underscore shows the programmer&#8217;s intent that this attribute should be left alone when using the class.</p><p>Whenever you access the <code>.cost_price</code> property, Python executes the code you define in the method that you decorate with the <code>@property</code> decorator. In this case, Python returns the value of the <code>._cost_price</code> data attribute.</p><p>Therefore, you still have a data attribute &#8211; the one with the leading underscore. However, the user doesn&#8217;t access it directly. Instead, they access it through the property <code>.cost_price</code>:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YkMa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!YkMa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!YkMa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!YkMa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!YkMa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19691,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.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_!YkMa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!YkMa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!YkMa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!YkMa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1fd11392-2574-4e88-8cec-fbc12fcd2a69_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#11</figcaption></figure></div><p>Here&#8217;s the output from this code:</p><pre><code>coffee.cost_price=2.5</code></pre><p>However, this makes the cost price read-only. That&#8217;s not what you&#8217;re trying to achieve:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!n8r3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!n8r3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!n8r3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!n8r3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!n8r3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:24537,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.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_!n8r3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!n8r3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!n8r3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!n8r3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9d078d4f-b440-43be-8273-263cbf93b0e4_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#12</figcaption></figure></div><p>This raises an error since you can&#8217;t assign values to the <code>.cost_price</code> property:</p><pre><code>Traceback (most recent call last):
  ...
    coffee.cost_price = 3
    ^^^^^^^^^^^^^^^^^
AttributeError: property &#8216;cost_price&#8217; of 
    &#8216;Product&#8217; object has no setter</code></pre><p>Note what the error message says: <code>'Product' object has no setter</code>. The setter is the method that allows you to set the value of a property. But you can add this setter to your 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_!FsQ2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FsQ2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png 424w, https://substackcdn.com/image/fetch/$s_!FsQ2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png 848w, https://substackcdn.com/image/fetch/$s_!FsQ2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!FsQ2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!FsQ2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png" width="1200" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:125707,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.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_!FsQ2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png 424w, https://substackcdn.com/image/fetch/$s_!FsQ2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png 848w, https://substackcdn.com/image/fetch/$s_!FsQ2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!FsQ2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63aaf448-0f80-4c74-8878-f3886e8cf715_1200x1092.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#13</figcaption></figure></div><p>There are no issues with setting the value for <code>coffee.cost_price</code> now that you have a setter, too. And the validation works when you try to set the cost price value to a negative value:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!82VK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff394673b-ab91-40e1-958a-00f274c6cc32_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!82VK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff394673b-ab91-40e1-958a-00f274c6cc32_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!82VK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff394673b-ab91-40e1-958a-00f274c6cc32_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!82VK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff394673b-ab91-40e1-958a-00f274c6cc32_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!82VK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff394673b-ab91-40e1-958a-00f274c6cc32_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f394673b-ab91-40e1-958a-00f274c6cc32_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:24571,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff394673b-ab91-40e1-958a-00f274c6cc32_1200x294.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_!82VK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff394673b-ab91-40e1-958a-00f274c6cc32_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!82VK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff394673b-ab91-40e1-958a-00f274c6cc32_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!82VK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff394673b-ab91-40e1-958a-00f274c6cc32_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!82VK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff394673b-ab91-40e1-958a-00f274c6cc32_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#14</figcaption></figure></div><p>This raises an error:</p><pre><code>Traceback (most recent call last):
  ...
    coffee.cost_price = -3
    ^^^^^^^^^^^^^^^^^
ValueError: Cost price cannot be negative</code></pre><p>However, there&#8217;s still a flaw in this code. The negative cost price validation still fails in some circumstances. Can you figure out when it fails?</p><p>Try this code:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hKTL!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9dd867-58b4-4995-a531-85a528c89085_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!hKTL!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9dd867-58b4-4995-a531-85a528c89085_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!hKTL!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9dd867-58b4-4995-a531-85a528c89085_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!hKTL!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9dd867-58b4-4995-a531-85a528c89085_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!hKTL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9dd867-58b4-4995-a531-85a528c89085_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7a9dd867-58b4-4995-a531-85a528c89085_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19708,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9dd867-58b4-4995-a531-85a528c89085_1200x252.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_!hKTL!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9dd867-58b4-4995-a531-85a528c89085_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!hKTL!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9dd867-58b4-4995-a531-85a528c89085_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!hKTL!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9dd867-58b4-4995-a531-85a528c89085_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!hKTL!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7a9dd867-58b4-4995-a531-85a528c89085_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#15</figcaption></figure></div><p>Here&#8217;s the output:</p><pre><code>coffee.cost_price=-2.5</code></pre><p>Validation occurs only when you set the <code>cost_price</code> attribute. However, look carefully at the code in your <code>.__init__()</code> method. It still sets the actual data attribute <code>._cost_price</code> directly. This bypasses the verification.</p><p>Luckily, there&#8217;s an easy fix:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!gSws!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gSws!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png 424w, https://substackcdn.com/image/fetch/$s_!gSws!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png 848w, https://substackcdn.com/image/fetch/$s_!gSws!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png 1272w, https://substackcdn.com/image/fetch/$s_!gSws!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!gSws!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png" width="1200" height="1008" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1008,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:105722,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.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_!gSws!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png 424w, https://substackcdn.com/image/fetch/$s_!gSws!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png 848w, https://substackcdn.com/image/fetch/$s_!gSws!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png 1272w, https://substackcdn.com/image/fetch/$s_!gSws!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd6b3fb4c-e3e2-4614-bde3-92903788a708_1200x1008.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#16</figcaption></figure></div><p>You can use the property in the <code>.__init__()</code> method, too. This triggers the property&#8217;s setter, which creates the <code>._cost_price</code> data attribute and stores the value in it.</p><h3><strong>Avoiding </strong><code>float</code><strong> for prices</strong></h3><p>Let&#8217;s add a bit more to the validation code. It&#8217;s best not to use <code>float</code> when dealing with prices since floats suffer from rounding errors, which may lead to issues when dealing with money (especially if the rounding goes against you!)</p><p>Here&#8217;s the classic example showing the floating-point rounding errors:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!OYTG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce41330d-0f74-4906-aab8-379362886a70_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!OYTG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce41330d-0f74-4906-aab8-379362886a70_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!OYTG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce41330d-0f74-4906-aab8-379362886a70_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!OYTG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce41330d-0f74-4906-aab8-379362886a70_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!OYTG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce41330d-0f74-4906-aab8-379362886a70_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ce41330d-0f74-4906-aab8-379362886a70_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:6548,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce41330d-0f74-4906-aab8-379362886a70_1200x210.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_!OYTG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce41330d-0f74-4906-aab8-379362886a70_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!OYTG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce41330d-0f74-4906-aab8-379362886a70_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!OYTG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce41330d-0f74-4906-aab8-379362886a70_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!OYTG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce41330d-0f74-4906-aab8-379362886a70_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#17</figcaption></figure></div><p>Some floats cannot be represented precisely in binary, leading to rounding errors.</p><p>One option is to work in cents or pence or whatever the smaller unit of the currency you&#8217;re using. This means you&#8217;re working with integers. However, an alternative is to use <code>decimal.Decimal</code> instead:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lrj0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!lrj0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!lrj0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!lrj0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!lrj0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19745,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.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_!lrj0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!lrj0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!lrj0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!lrj0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8838be9d-2dae-498a-a9bd-949e0b60d913_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#18</figcaption></figure></div><p>Note that you should pass the floats as strings to <code>Decimal</code> and let the <code>Decimal</code> class deal with that. If you use <code>float</code> objects, you&#8217;ve already included the rounding errors in your starting value!</p><p>Let&#8217;s make sure the cost price uses <code>Decimal</code> internally without forcing the user to use this data type:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!vrqm!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vrqm!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png 424w, https://substackcdn.com/image/fetch/$s_!vrqm!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png 848w, https://substackcdn.com/image/fetch/$s_!vrqm!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png 1272w, https://substackcdn.com/image/fetch/$s_!vrqm!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!vrqm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png" width="1200" height="1260" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1260,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:140665,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.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_!vrqm!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png 424w, https://substackcdn.com/image/fetch/$s_!vrqm!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png 848w, https://substackcdn.com/image/fetch/$s_!vrqm!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png 1272w, https://substackcdn.com/image/fetch/$s_!vrqm!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff85ca0f2-18c1-4576-9c41-b33b72d36b29_1200x1260.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#19</figcaption></figure></div><p>In true duck typing fashion, rather than choosing which data types you&#8217;re willing to accept when setting the cost price, you try to convert the input value to <code>Decimal</code>. Any data type that can be converted to <code>Decimal</code> is acceptable. The <code>Decimal</code> type raises an <code>InvalidOperation</code> exception, defined within <code>decimal</code>, when you pass an unacceptable type. So, you use <code>InvalidOperation</code> in the <code>except</code> block.</p><p>You probably want to perform the same validation for the selling price, too:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NKMn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NKMn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png 424w, https://substackcdn.com/image/fetch/$s_!NKMn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png 848w, https://substackcdn.com/image/fetch/$s_!NKMn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png 1272w, https://substackcdn.com/image/fetch/$s_!NKMn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!NKMn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png" width="1236" height="1764" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1764,&quot;width&quot;:1236,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:223241,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.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_!NKMn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png 424w, https://substackcdn.com/image/fetch/$s_!NKMn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png 848w, https://substackcdn.com/image/fetch/$s_!NKMn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png 1272w, https://substackcdn.com/image/fetch/$s_!NKMn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F341594c2-3baa-4e2f-87e4-1b09f9fc4cb8_1236x1764.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#20</figcaption></figure></div><p>This works. However, there&#8217;s a lot of boilerplate code. And the validation is repeated in two setter methods. Sure, you can create a helper function to avoid the repetition. But what if you had more types of prices to include in your class? Perhaps there&#8217;s a <code>wholesale_price</code> and a <code>discounted_price</code>, say. You&#8217;d have to create properties for each one.</p><p>Before I move on from properties, here&#8217;s a link to another article I wrote about properties: <a href="https://www.thepythoncodingstack.com/p/the-properties-of-python-property">The Properties of Python&#8217;s property </a>.</p><p>Now let&#8217;s explore a different option.</p><h2><strong>Descriptors</strong></h2><p>Spoiler alert: you&#8217;ve already been using descriptors. Python&#8217;s <code>property</code> uses the descriptor protocol behind the scenes. Indeed, you use descriptors each time you access a method, or when you use the <code>@classmethod</code> and <code>@staticmethod</code> decorators.</p><p>But let&#8217;s get back to what happens when you use the dot after an object name, such as <code>coffee.cost_price</code>. The quick answer often states that Python looks at the instance&#8217;s <code>.__dict__</code> attribute, which is a dictionary containing the instance&#8217;s data attributes. If the attribute is not there, Python looks in the class&#8217;s <code>.__dict__</code> to check whether the attribute is a class attribute.</p><p>However, there&#8217;s a bit more happening.</p><p>The <code>.</code> notation calls the <code>.__getattribute__()</code> special method, which looks for the attribute using a broader set of rules and priorities.</p><p>The first thing it looks for is whether the attribute is a descriptor &#8211; technically, a data descriptor.</p><p>But what&#8217;s a descriptor?</p><h3><strong>Creating a descriptor class</strong></h3><p>Let&#8217;s create one. Create a <code>Price</code> class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!VH7I!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VH7I!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png 424w, https://substackcdn.com/image/fetch/$s_!VH7I!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png 848w, https://substackcdn.com/image/fetch/$s_!VH7I!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png 1272w, https://substackcdn.com/image/fetch/$s_!VH7I!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!VH7I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png" width="1362" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1362,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:35129,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.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_!VH7I!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png 424w, https://substackcdn.com/image/fetch/$s_!VH7I!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png 848w, https://substackcdn.com/image/fetch/$s_!VH7I!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png 1272w, https://substackcdn.com/image/fetch/$s_!VH7I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46965f12-ab9f-4377-99bb-5506288cd524_1362x630.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#21</figcaption></figure></div><p>An object that has either of these special methods is a <em>descriptor</em>. (Note that there&#8217;s another special method that&#8217;s part of the descriptor protocol, <code>.__delete__()</code>, which is also sufficient to create a descriptor. I won&#8217;t be discussing <code>.__delete__()</code> in this article.)</p><p>So what? This is where descriptors start getting weird &#8211; yes, right at the start! Let&#8217;s pause with this class and get back to the <code>Product</code> class. Define <code>.cost_price</code> and  <code>.selling_price</code> as <em>class attributes</em> and assign instances of the new <code>Price</code> class to them:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NMUv!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NMUv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png 424w, https://substackcdn.com/image/fetch/$s_!NMUv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png 848w, https://substackcdn.com/image/fetch/$s_!NMUv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png 1272w, https://substackcdn.com/image/fetch/$s_!NMUv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!NMUv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png" width="1200" height="798" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:798,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:64256,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.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_!NMUv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png 424w, https://substackcdn.com/image/fetch/$s_!NMUv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png 848w, https://substackcdn.com/image/fetch/$s_!NMUv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png 1272w, https://substackcdn.com/image/fetch/$s_!NMUv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff448a06b-1552-4082-92f0-e7aefd86dc15_1200x798.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#22</figcaption></figure></div><p>The rest of the code remains the same except that four methods are gone. These are the getter and setter methods you had defined previously to ensure that <code>.cost_price</code> and <code>.selling_price</code> are properties. You no longer need them. You&#8217;ll see why soon.</p><p>Why define class attributes? Class attributes are created when you define the class, unlike instance attributes, which are created when you create instances. Therefore, the attributes <code>.cost_price</code> and <code>.selling_price</code> exist and are equal to instances of a descriptor class at the time of class definition. This matters, as you&#8217;ll also see shortly.</p><p>So, what&#8217;s special about descriptors? Remember when we discussed how the <code>.</code> triggers the <code>.__getattribute__()</code> special method, which is responsible for looking for the attribute and returning its value? Well, as it happens, Python doesn&#8217;t look in the instance&#8217;s <code>.__dict__</code> attribute first, after all.</p><p>The first thing it checks is whether the attribute is a descriptor. More specifically, it checks whether the attribute is a data descriptor, which is a descriptor that has <code>.__set__()</code> or <code>.__delete__()</code>. But our descriptor class, <code>Price</code>, has a <code>.__set__()</code>, so this priority applies to a <code>Price</code> object.</p><p>Here&#8217;s the key to understanding descriptors:</p><blockquote><p>Since <code>.cost_price</code> and <code>.selling_price</code> are descriptors, the <code>Product</code> class defers to the <code>Price</code> class to decide how to get or set a value for this attribute.</p></blockquote><p>Let me repeat that.</p><p>Normally, the class that defines an instance determines its behaviour. The special methods in <code>Product</code> determine how a <code>Product</code> instance behaves, such as what its string representations are, whether it&#8217;s iterable, whether it has a length, and so on. We haven&#8217;t defined any of these special methods in <code>Product</code>, but if we did, they would determine the object&#8217;s behaviour in those contexts.</p><p>However, when you use the dot on an instance of a <code>Product</code> class, if the attribute you&#8217;re accessing is a descriptor, such as <code>.cost_price</code> and <code>.selling_price</code>, it&#8217;s <code>Price.__get__()</code> and <code>Price.__set__()</code> that determine what to do when you get or set the values of <code>.cost_price</code> and <code>.selling_price</code>.</p><p>Code in the <code>Price</code> class determines what happens when you access an attribute in a <code>Product</code> instance.</p><p>And since you define <code>.cost_price</code> and <code>.selling_price</code> as class attributes that contain descriptors &#8211; instances of <code>Price</code> &#8211; then the descriptor special methods kick in even in <code>Product.__init__()</code> when you write <code>self.cost_price = cost_price</code> and <code>self.selling_price = selling_price</code>.</p><div class="pullquote"><p><em>Do you want to master Python one article at a time? Then don&#8217;t miss out on the articles in The Club, which are exclusive to premium subscribers here on The Python Coding Stack</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p></div><h3><strong>Understanding how descriptors work</strong></h3><p>Let&#8217;s prove this by adding some code to the <code>Price</code> class. This code is here to let us track what&#8217;s happening. You&#8217;ll write &#8220;proper&#8221; code later:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zP4l!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zP4l!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png 424w, https://substackcdn.com/image/fetch/$s_!zP4l!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png 848w, https://substackcdn.com/image/fetch/$s_!zP4l!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png 1272w, https://substackcdn.com/image/fetch/$s_!zP4l!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!zP4l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png" width="1200" height="588" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:588,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:48714,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.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_!zP4l!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png 424w, https://substackcdn.com/image/fetch/$s_!zP4l!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png 848w, https://substackcdn.com/image/fetch/$s_!zP4l!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png 1272w, https://substackcdn.com/image/fetch/$s_!zP4l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F04cd6565-b6a1-4f99-9037-ab864104f0d7_1200x588.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#23</figcaption></figure></div><p>The <code>.__get__()</code> and <code>.__set__()</code> methods print out phrases to allow you to see when these methods are called. The <code>.__get__()</code> special method also returns a string. A reminder that these special methods are defined in the <code>Price</code> class.</p><p>Here&#8217;s the code so far, which includes a statement in the main scope that creates an instance of the <code>Product</code> class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!8ksU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8ksU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png 424w, https://substackcdn.com/image/fetch/$s_!8ksU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png 848w, https://substackcdn.com/image/fetch/$s_!8ksU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!8ksU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!8ksU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png" width="1200" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:115622,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.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_!8ksU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png 424w, https://substackcdn.com/image/fetch/$s_!8ksU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png 848w, https://substackcdn.com/image/fetch/$s_!8ksU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!8ksU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3b33929-c533-47c1-a7f8-c57f626a01f6_1200x1092.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#24</figcaption></figure></div><p>Here&#8217;s what you see when you run this code:</p><pre><code>Calling Price.__set__()
Calling Price.__set__()</code></pre><p>The code calls the <code>Price.__set__()</code> method twice: once when creating <code>self.cost_price</code> and another time when creating <code>self.selling_price</code> in <code>Product.__init__()</code>.</p><p>Let&#8217;s also fetch one of the attributes:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dwkx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!dwkx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!dwkx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!dwkx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!dwkx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19150,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.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_!dwkx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!dwkx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!dwkx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!dwkx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa2bc936e-6411-42ee-a06c-9553d10272c8_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#25</figcaption></figure></div><p>Here&#8217;s the output from this code:</p><pre><code>Calling Price.__set__()
Calling Price.__set__()
Calling Price.__get__()
Price coming soon...</code></pre><p>You still get the two &#8220;breadcrumbs&#8221; that show that the code called <code>Price.__set__()</code> twice. But now you can also see that the code calls <code>Price.__get__()</code> since you wrote <code>print(coffee.selling_price)</code>. And when you access the <code>.selling_price</code> attribute, Python returns the value returned by <code>Price.__get__()</code>, which is the string saying <code>"Price coming soon..."</code>.</p><p>Therefore, attribute access for <code>.selling_price</code> and <code>.cost_price</code>, which are attributes in <code>Product</code>, is now controlled by the <code>Price</code> class, which is the descriptor class.</p><p>Yes, the <code>Price</code> class has taken over control of attribute access in the <code>Product</code> class (but only for the attributes that are descriptors of the <code>Price</code> class, <code>.cost_price</code> and <code>.selling_price</code>.)</p><div><hr></div><p>Let&#8217;s look at the signatures of the <code>.__get__()</code> and <code>.__set__()</code> special methods to figure out how they work. Let&#8217;s focus on <code>.__get__()</code> first. Here&#8217;s the method&#8217;s signature and a few more printouts to help us figure out what&#8217;s what:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!oMth!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!oMth!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!oMth!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!oMth!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!oMth!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!oMth!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png" width="1200" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:48439,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.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_!oMth!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!oMth!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!oMth!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!oMth!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3cca53ba-8111-4d87-b915-9128dcaa068b_1200x504.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#26</figcaption></figure></div><p>There are three parameters defined in the signature for <code>.__get__()</code>. You won&#8217;t be surprised to see <code>self</code> as the first parameter, which is the case for all instance methods in classes. There are also two other parameters named <code>instance</code> and <code>owner</code>. Let&#8217;s figure out what they are.</p><p>You&#8217;ve seen earlier that the current code calls <code>.__get__()</code> once when the code evaluates <code>coffee.selling_price</code>, which you use as an argument for <code>print()</code>. Here&#8217;s the output of the code now:</p><pre><code>Calling Price.__set__()
Calling Price.__set__()
Calling Price.__get__()
self=&lt;__main__.Price object at 0x100bc8f50&gt;
instance=&lt;__main__.Product object at 0x100bd9160&gt;
owner=&lt;class &#8216;__main__.Product&#8217;&gt;
Price coming soon...</code></pre><p>The new additions are the printouts on the fourth, fifth, and sixth lines showing the values assigned to the parameters <code>self</code>, <code>instance</code>, and <code>owner</code> in <code>Price.__get__()</code>. First, a reminder that this method is triggered when you run the following expression:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!K0Ia!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!K0Ia!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!K0Ia!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!K0Ia!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!K0Ia!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:7086,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.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_!K0Ia!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!K0Ia!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!K0Ia!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!K0Ia!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5f58be39-97c5-4384-8a64-e7ff56d089a7_1200x168.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#27</figcaption></figure></div><p>Here&#8217;s what the outputs for the three parameters show:</p><ul><li><p><code>self=&lt;__main__.Price object ...&gt;</code>:  Therefore, <code>self</code> refers to the instance of the <code>Price</code> class itself, as <code>self</code> always does in classes. This is the descriptor instance. It&#8217;s the same descriptor object the attribute <code>coffee.selling_price</code> invokes (but not the object that <code>coffee.selling_price</code> returns, as you&#8217;ll see soon.)</p></li><li><p><code>instance=&lt;__main__.Product object ...&gt;</code>: This output shows that <code>instance</code> is an object of type <code>Product</code>. It&#8217;s the object that has the descriptor as one of its attributes. In this example, this is the <code>coffee</code> object.</p></li><li><p><code>owner=&lt;__main__.Product&gt;</code>: This is the <code>Product</code> class itself (not an instance of the class).</p></li></ul><p>Therefore, in the expression <code>coffee.selling_price</code>, <code>coffee</code> is the <code>Product</code> instance and <code>.selling_price</code> is the <code>Price</code> instance, which is the descriptor.</p><p>And when Python evaluates the expression <code>coffee.selling_price</code>, it defers the decision of which value to display to the <code>Price</code> class. Python calls <code>Price.__get__()</code> with the following arguments:</p><ul><li><p>The <code>selling_price</code> descriptor is passed to <code>self</code></p></li><li><p>The <code>coffee</code> object, an instance of <code>Product</code>, is passed to <code>instance</code></p></li><li><p>The <code>Product</code> class is passed to <code>owner</code></p></li></ul><p>I&#8217;ve repeated myself in the previous few paragraphs, but that&#8217;s deliberate. I get confused following the flow from the <code>Product</code> class to calling a method in the descriptor class, <code>Price</code>.  I need this repetition. Maybe it helps you, too.</p><p>As a side note, which I&#8217;ll mostly ignore in this article: It&#8217;s possible to call the descriptor using the class rather than an instance, such as the following:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ohYG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!ohYG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!ohYG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!ohYG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ohYG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:11181,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.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_!ohYG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!ohYG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!ohYG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!ohYG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa7b108f9-5e52-44dc-979c-cedd6774f0bf_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#28</figcaption></figure></div><p>Here&#8217;s the output from this code:</p><pre><code>Calling Price.__get__()
self=&lt;__main__.Price object at 0x102a79090&gt;
instance=None
owner=&lt;class &#8216;__main__.Product&#8217;&gt;
Price coming soon...</code></pre><p>In this case, <code>None</code> is assigned to <code>instance</code> since there&#8217;s no <code>Product</code> instance involved.</p><div><hr></div><p>Let&#8217;s look at the <code>.__set__()</code> special method now:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_rcE!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_rcE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!_rcE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!_rcE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!_rcE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!_rcE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png" width="1200" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:42879,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.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_!_rcE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!_rcE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!_rcE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!_rcE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1152dbac-f8c2-4013-8e68-dd56883a7c73_1200x504.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#29</figcaption></figure></div><p>The signature still includes <code>self</code> and <code>instance</code>, and these refer to the same objects as they did in <code>.__get__()</code>. The third parameter is <code>value</code>, which stores the object you want to use when setting the attribute&#8217;s value. Let&#8217;s focus on creating an instance of <code>Product</code> as you did earlier:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Nyih!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!Nyih!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!Nyih!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!Nyih!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Nyih!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12153,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.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_!Nyih!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!Nyih!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!Nyih!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!Nyih!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06d22059-8484-4c5b-8a83-310e7d264c56_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#30</figcaption></figure></div><p>This code accesses descriptors using the dot notation twice within <code>Product.__init__()</code> since it sets the values of <code>.cost_price</code> and <code>.selling_price</code>, which contain <code>Price</code> objects. Here&#8217;s the output from this code:</p><pre><code>Calling Price.__set__()
self=&lt;__main__.Price object at 0x104cf5010&gt;
instance=&lt;__main__.Product object at 0x104cf5160&gt;
value=3.2

Calling Price.__set__()
self=&lt;__main__.Price object at 0x104ce4f50&gt;
instance=&lt;__main__.Product object at 0x104cf5160&gt;
value=5</code></pre><p>The two calls are triggered by two different descriptors, <code>.cost_price</code> and <code>.selling_price</code>. Therefore, <code>self</code> refers to different objects in these calls, as you can see from the different identity values displayed.</p><p>However, the descriptors belong to the same instance, the <code>Product</code> object you named <code>coffee</code>. You can see that the printout references the same <code>Product</code> object on both occasions.</p><p>The value is the number you&#8217;re trying to assign to the descriptors.</p><h3><strong>Writing the </strong><code>.__get__()</code><strong> and </strong><code>.__set__()</code><strong> methods</strong></h3><p>Now you know how and when Python calls the <code>.__get__()</code> and <code>.__set__()</code> methods, you can add code within them. You can use the same reasoning you used when creating properties earlier.</p><p>To keep track of what&#8217;s happening, let&#8217;s build the code you need in stages.</p><p>First, let&#8217;s focus exclusively on the <code>.cost_price</code> attribute. You&#8217;ll write the validation as if it&#8217;s just for cost price &#8212; and you&#8217;ll soon see why that breaks once selling price joins the party. You&#8217;ll deal with <code>.selling_price</code> later.</p><p>You can use the same validation code you used earlier when working with properties. This code should now go in the <code>.__set__()</code> method within the <code>Price</code> class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!UkS-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UkS-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.png 424w, https://substackcdn.com/image/fetch/$s_!UkS-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.png 848w, https://substackcdn.com/image/fetch/$s_!UkS-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.png 1272w, https://substackcdn.com/image/fetch/$s_!UkS-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!UkS-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.png" width="1380" height="966" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c15af7a0-2204-4585-8434-c7d1417945da_1380x966.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:966,&quot;width&quot;:1380,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:113195,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.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_!UkS-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.png 424w, https://substackcdn.com/image/fetch/$s_!UkS-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.png 848w, https://substackcdn.com/image/fetch/$s_!UkS-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.png 1272w, https://substackcdn.com/image/fetch/$s_!UkS-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc15af7a0-2204-4585-8434-c7d1417945da_1380x966.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#31</figcaption></figure></div><p>Let&#8217;s see what&#8217;s new in this version:</p><ol><li><p>I removed most of the <code>print()</code> calls, which were useful merely to explore what objects are passed to these special methods. I left the ones showing when the code calls these methods for now.</p></li><li><p>The <code>.__set__()</code> method includes the <code>try..except</code> block, which ensures the value is a <code>Decimal</code>, and the <code>if</code> statement, which checks that the value is not negative.</p></li><li><p>The final line in <code>.__set__()</code> sets the <code>._cost_price</code> attribute in the <code>instance</code> object, using the value in <code>value</code>. The function call <code>setattr(instance, "_cost_price", value)</code> is equivalent to <code>instance._cost_price = value</code>. In this case, <code>instance</code> is the <code>Product</code> object, such as <code>coffee</code>. There&#8217;s a good reason to use the <code>setattr()</code> built-in function rather than assigning the value directly using the dot notation. You&#8217;ll find out later when you also deal with the selling price.<br>Note that you use the leading underscore in <code>"_cost_price"</code> since you wish to create the non-public attribute <code>._cost_price</code> rather than assign the value to the <code>.cost_price</code> attribute (the one without the leading underscore).</p></li></ol><p>Let&#8217;s try this out. Note that this code is hard-coded to work only for the <code>.cost_price</code> attribute for now:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eoSj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!eoSj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!eoSj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!eoSj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!eoSj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:18666,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.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_!eoSj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!eoSj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!eoSj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!eoSj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcbb135a5-24f8-4788-8a84-3d0183befd93_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#32</figcaption></figure></div><p>Oops! This doesn&#8217;t work:</p><pre><code>Calling Price.__set__()
Calling Price.__set__()
Calling Price.__get__()
None</code></pre><p>The final line shows that the code outputs <code>None</code>. That&#8217;s because <code>coffee.cost_price</code> triggers the <code>Price.__get__()</code> method, which you haven&#8217;t completed yet! You can still check whether we&#8217;re on track by printing the actual data attribute <code>._cost_price</code>:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9b_I!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!9b_I!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!9b_I!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!9b_I!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!9b_I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:18671,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.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_!9b_I!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!9b_I!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!9b_I!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!9b_I!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff38e50ef-72e5-4274-8be7-e79b396653e5_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#33</figcaption></figure></div><p>You should avoid accessing non-public attributes outside of the class definition in general. But I give you permission to break the rule here since we&#8217;re merely exploring what&#8217;s happening behind the scenes!</p><pre><code>Calling Price.__set__()
Calling Price.__set__()
5</code></pre><p>Note how there&#8217;s no printout saying <code>"Calling Price.__get__()"</code> now since you&#8217;re accessing the data attribute <code>._cost_price</code>, not the descriptor <code>.cost_price</code>.</p><p>But did you notice that this still shows the wrong value? The cost price should be &#163;3.20. It&#8217;s the selling price that&#8217;s &#163;5.00. Remember how you&#8217;re hard-coding the string <code>"_cost_price"</code> in the call to <code>setattr()</code>? This means that when you try to set the selling price, the code currently overwrites the cost price. But don&#8217;t worry, we&#8217;ll fix this soon.</p><p>Time to focus on <code>.__get__()</code>. Since you created the non-public data attribute <code>._cost_price</code> when setting the value using <code>.__set__()</code>, you can now get the value of that attribute using <code>getattr()</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_!fnVT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fnVT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png 424w, https://substackcdn.com/image/fetch/$s_!fnVT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png 848w, https://substackcdn.com/image/fetch/$s_!fnVT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png 1272w, https://substackcdn.com/image/fetch/$s_!fnVT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!fnVT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png" width="1380" height="882" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:882,&quot;width&quot;:1380,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:118708,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.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_!fnVT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png 424w, https://substackcdn.com/image/fetch/$s_!fnVT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png 848w, https://substackcdn.com/image/fetch/$s_!fnVT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png 1272w, https://substackcdn.com/image/fetch/$s_!fnVT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5a0653f8-e2ed-4629-886d-4c60934fe3f2_1380x882.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#34</figcaption></figure></div><p>Recall that in <code>.__get__()</code>, the parameter <code>instance</code> refers to the <code>Product</code> instance, such as <code>coffee</code>. Therefore, <code>getattr(instance, "_cost_price")</code> is equivalent to <code>coffee._cost_price</code> in this example.</p><p>Let&#8217;s try this out, this time using the <code>.cost_price</code> descriptor directly when accessing the value of the cost price:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!VeML!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff30a435a-2254-4920-a03a-16564f619858_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!VeML!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff30a435a-2254-4920-a03a-16564f619858_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!VeML!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff30a435a-2254-4920-a03a-16564f619858_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!VeML!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff30a435a-2254-4920-a03a-16564f619858_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!VeML!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff30a435a-2254-4920-a03a-16564f619858_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f30a435a-2254-4920-a03a-16564f619858_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:18661,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff30a435a-2254-4920-a03a-16564f619858_1200x294.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_!VeML!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff30a435a-2254-4920-a03a-16564f619858_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!VeML!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff30a435a-2254-4920-a03a-16564f619858_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!VeML!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff30a435a-2254-4920-a03a-16564f619858_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!VeML!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff30a435a-2254-4920-a03a-16564f619858_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#35</figcaption></figure></div><p>Here&#8217;s the output showing all the breadcrumbs confirming that two attributes are set and that you fetch the value of one of them once. The output also shows the value of the attribute, which is still wrong since &#163;5 is the selling price:</p><pre><code>Calling Price.__set__()
Calling Price.__set__()
Calling Price.__get__()
5</code></pre><p>We&#8217;ll soon stop the selling price from overwriting the cost price.</p><p>But first, let&#8217;s check that the validation logic works:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ImmM!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!ImmM!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!ImmM!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!ImmM!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ImmM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12615,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.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_!ImmM!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!ImmM!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!ImmM!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!ImmM!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0819a9d2-4caf-42f0-8f6d-07ea94eac59a_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#36</figcaption></figure></div><p>This raises an error:</p><pre><code>Traceback (most recent call last):
  ... in &lt;module&gt;
    coffee = Product(&#8221;Espresso&#8221;, -3.2, 5)
  ... in Product.__init__
    self.cost_price = cost_price
    ^^^^^^^^^^^^^^^
  ... in Price.__set__
    raise ValueError(f&#8221;&#8217;cost_price&#8217; can&#8217;t be less than zero&#8221;)
    
ValueError: &#8216;cost_price&#8217; can&#8217;t be less than zero</code></pre><p>And so does this:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KJ1F!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd3b93e-85a6-4507-a760-15edfb649574_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!KJ1F!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd3b93e-85a6-4507-a760-15edfb649574_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!KJ1F!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd3b93e-85a6-4507-a760-15edfb649574_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!KJ1F!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd3b93e-85a6-4507-a760-15edfb649574_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!KJ1F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd3b93e-85a6-4507-a760-15edfb649574_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/efd3b93e-85a6-4507-a760-15edfb649574_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12876,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd3b93e-85a6-4507-a760-15edfb649574_1200x210.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_!KJ1F!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd3b93e-85a6-4507-a760-15edfb649574_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!KJ1F!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd3b93e-85a6-4507-a760-15edfb649574_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!KJ1F!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd3b93e-85a6-4507-a760-15edfb649574_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!KJ1F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fefd3b93e-85a6-4507-a760-15edfb649574_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#37</figcaption></figure></div><p>This time, the error message is different:</p><pre><code>...
TypeError: Invalid format for &#8216;cost_price&#8217;: three point two</code></pre><p>Another minor note for completeness&#8217;s sake. We mentioned that you can call the descriptor through the class, such as <code>Product.cost_price</code>. Since <code>instance</code> is <code>None</code> in this case, the code in <code>.__get__()</code> raises an error since <code>None</code> doesn&#8217;t have a <code>._cost_price</code> attribute (or any attribute, for that matter!) To account for this, you can add the following code in <code>.__get__()</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_!Ti0g!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ti0g!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!Ti0g!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!Ti0g!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!Ti0g!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ti0g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png" width="1200" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:52650,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.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_!Ti0g!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!Ti0g!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!Ti0g!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!Ti0g!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9807d897-33e8-4e66-b365-0205723e2cc6_1200x504.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#38</figcaption></figure></div><p>If you call the descriptor from a class, you just get the descriptor back. There&#8217;s no instance, so there&#8217;s no value to fetch in this case! But let&#8217;s move on&#8230;</p><div><hr></div><p><em>Your call&#8230;</em></p><p><em>The Python Coding Place offers something for everyone:</em></p><p><em>&#8226; a super-personalised one-to-one 6-month mentoring option</em><br><em>$ 4,750</em></p><p><em>&#8226; individual one-to-one sessions</em><br><em>$ 125</em></p><p><em>&#8226; a self-led route with access to 60+ hrs of exceptional video courses and a support forum</em><br><em>$ 400</em></p><p><em><a href="https://thepythoncodingplace.com?utm_source=the-python-coding-stack">Which The Python Coding Place student are you?</a></em></p><div><hr></div><h3><strong>Making a general descriptor class</strong></h3><p>This works. But it only works for the <code>.cost_price</code> attribute since there are a few references to this attribute hard-coded in the <code>.__get__()</code> and <code>.__set__()</code> methods:</p><ol><li><p>You use the string <code>"_cost_price"</code> when calling <code>getattr()</code> and <code>setattr()</code>.</p></li><li><p>You also refer to the attribute name <code>'cost_price'</code> in the error messages.</p></li></ol><p>Hard-coding the cost price attribute names also has the undesirable effect of overwriting the cost price with the selling price!</p><p>Ideally, you&#8217;d like to access the public attribute name <code>"cost_price"</code> (the name of the descriptor) and the non-public data attribute name <code>"_cost_price"</code> dynamically. Recall that these are attributes in the <code>Product</code> class. Python passes the descriptor object <code>self</code> to the <code>.__get__</code> and <code>.__set__()</code> methods, but not its attribute name within <code>Product</code>.</p><p>But descriptors can also deal with this problem. A descriptor allows you to pass the attribute name from the <code>Product</code> class to the <code>Price</code> class using <code>.__set_name__()</code> in the descriptor class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1bWl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1bWl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png 424w, https://substackcdn.com/image/fetch/$s_!1bWl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png 848w, https://substackcdn.com/image/fetch/$s_!1bWl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png 1272w, https://substackcdn.com/image/fetch/$s_!1bWl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!1bWl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png" width="1200" height="546" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:546,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:51078,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.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_!1bWl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png 424w, https://substackcdn.com/image/fetch/$s_!1bWl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png 848w, https://substackcdn.com/image/fetch/$s_!1bWl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png 1272w, https://substackcdn.com/image/fetch/$s_!1bWl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1e2a241a-00c7-4146-aece-28890f77304c_1200x546.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#39</figcaption></figure></div><p>I&#8217;ve put similar <code>print()</code> calls to the ones you used earlier to help us identify what&#8217;s what. Remove the code that creates the instance <code>coffee</code>, so that your module only defines the two classes, <code>Price</code> and <code>Product</code>, and nothing else. Run your script, and you&#8217;ll see this output:</p><pre><code>Calling Price.__set_name__()
self=&lt;__main__.Price object at 0x101bbcec0&gt;
owner=&lt;class &#8216;__main__.Product&#8217;&gt;
name=&#8217;cost_price&#8217;

Calling Price.__set_name__()
self=&lt;__main__.Price object at 0x101bacf50&gt;
owner=&lt;class &#8216;__main__.Product&#8217;&gt;
name=&#8217;selling_price&#8217;</code></pre><p>Python calls <code>Price.__set_name__</code> when you create the descriptors within <code>Product</code>. Recall that you create the descriptors when you assign them to the class attributes. These attributes, and therefore the descriptors, are created when you define the <code>Product</code> class and not when you create <code>Product</code> instances.</p><p>As before, <code>self</code> refers to the descriptor object itself. The <code>owner</code> parameter still refers to the class in which the descriptors are defined, <code>Product</code> in this example.</p><p>Finally, <code>name</code> is a string containing the attribute name you use within the <code>Product</code> class. Therefore, <code>name</code> is either <code>"cost_price"</code> or <code>"selling_price"</code>.</p><p>You can now use this name within code in the <code>Price</code> class. First, let&#8217;s tidy up the <code>.__set_name__()</code> method:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!d5gl!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!d5gl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!d5gl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!d5gl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!d5gl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!d5gl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png" width="1200" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:46602,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.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_!d5gl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!d5gl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!d5gl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!d5gl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa5597bae-6a07-4739-8dbb-b2f404507e4d_1200x504.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#40</figcaption></figure></div><p>You create two instance attributes in the <code>Price</code> object to refer to the private and public names. You may recall that I mentioned Python prefers the term &#8220;non-public&#8221; over &#8220;private&#8221;. However, the Python documentation also occasionally uses the term &#8220;private&#8221;, including when discussing descriptors. It&#8217;s common to see <code>.private_name</code> used as the instance attribute within a descriptor. I&#8217;ll acquiesce.</p><p>Now, you can update the rest of the 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_!XBTo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!XBTo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png 424w, https://substackcdn.com/image/fetch/$s_!XBTo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png 848w, https://substackcdn.com/image/fetch/$s_!XBTo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png 1272w, https://substackcdn.com/image/fetch/$s_!XBTo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!XBTo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png" width="1290" height="1302" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1302,&quot;width&quot;:1290,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:137424,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.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_!XBTo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png 424w, https://substackcdn.com/image/fetch/$s_!XBTo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png 848w, https://substackcdn.com/image/fetch/$s_!XBTo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png 1272w, https://substackcdn.com/image/fetch/$s_!XBTo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F440fb805-c9c2-49f2-8a46-b584108a4952_1290x1302.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#41</figcaption></figure></div><p>You use <code>self.private_name</code> as an argument in <code>getattr()</code> and <code>setattr()</code> instead of the hard-coded string you had before. And you use <code>self.public_name</code> in the error messages. Note that I&#8217;ve also removed the breadcrumb calls to <code>print()</code> since we no longer need to show when Python calls each of these methods.</p><p>Let&#8217;s test:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ijMQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ijMQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!ijMQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!ijMQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!ijMQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ijMQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png" width="1200" height="336" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:336,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:32952,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.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_!ijMQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!ijMQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!ijMQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!ijMQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd5e22f46-7cdb-4fb3-9922-1a909fdbebf4_1200x336.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#42</figcaption></figure></div><p>You can set and get values, including within the <code>.profit_margin</code> property:</p><pre><code>3.2
5
1.8</code></pre><p>But you can&#8217;t set invalid values. Try <code>coffee.cost_price = -2</code> and <code>coffee.cost_price = "three point two"</code> to confirm the validation code works.</p><p>Here&#8217;s the full code containing both classes:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mabD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mabD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png 424w, https://substackcdn.com/image/fetch/$s_!mabD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png 848w, https://substackcdn.com/image/fetch/$s_!mabD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png 1272w, https://substackcdn.com/image/fetch/$s_!mabD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mabD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png" width="1290" height="1764" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1764,&quot;width&quot;:1290,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:197505,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.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_!mabD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png 424w, https://substackcdn.com/image/fetch/$s_!mabD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png 848w, https://substackcdn.com/image/fetch/$s_!mabD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png 1272w, https://substackcdn.com/image/fetch/$s_!mabD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F52442f70-58c8-4951-a3f5-e913d607c812_1290x1764.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#43</figcaption></figure></div><h2><strong>How About Properties, Then?</strong></h2><p>You use a property for the <code>.profit_margin</code> attribute in <code>Product</code>. This is a simple read-only attribute you use to calculate the value each time you need the attribute. You could use properties for <code>.selling_price</code> and <code>.cost_price</code>, but there&#8217;s plenty of boilerplate code needed for each attribute. Annoying, especially if you need many price-related attributes in your class, not just cost and selling prices.</p><p>Descriptors allow you to put the validation logic into a separate class. And descriptors aren&#8217;t restricted to data validation. You can use descriptors whenever you need to execute any logic each time you get or set the value of an attribute. And you can use the <code>Price</code> descriptor elsewhere, too. It&#8217;s not restricted to the <code>Product</code> class.</p><p>But remember the <code>property</code> object? This is itself a descriptor. Here&#8217;s evidence of this:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!u0kr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e938d33-156a-40be-b6b2-964b1b991242_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!u0kr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e938d33-156a-40be-b6b2-964b1b991242_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!u0kr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e938d33-156a-40be-b6b2-964b1b991242_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!u0kr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e938d33-156a-40be-b6b2-964b1b991242_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!u0kr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e938d33-156a-40be-b6b2-964b1b991242_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7e938d33-156a-40be-b6b2-964b1b991242_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:14458,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e938d33-156a-40be-b6b2-964b1b991242_1200x210.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_!u0kr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e938d33-156a-40be-b6b2-964b1b991242_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!u0kr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e938d33-156a-40be-b6b2-964b1b991242_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!u0kr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e938d33-156a-40be-b6b2-964b1b991242_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!u0kr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e938d33-156a-40be-b6b2-964b1b991242_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#44</figcaption></figure></div><p>This code returns <code>True</code>. The <code>.profit_margin</code> attribute is a property. It has the <code>.__get__()</code> special method, which is sufficient to make it a descriptor. A property is a descriptor.</p><p>Note that you&#8217;re accessing this property through the class name within <code>hasattr()</code>. Remember the code checking whether <code>instance</code> is <code>None</code> in <code>.__get__()</code>? You used the <code>if instance is None:</code> check to return the descriptor itself when you call the descriptor from a class. That&#8217;s why you can introspect the descriptor through <code>Product.profit_margin</code>. But don&#8217;t worry too much about this detail!</p><h2><strong>Final Words</strong></h2><p>How often have you used a method, such as in this case?</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!LbA3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!LbA3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!LbA3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!LbA3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!LbA3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:20242,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.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_!LbA3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!LbA3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!LbA3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!LbA3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fae907ea5-2f57-4220-9fbb-c08605c2741a_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#45</figcaption></figure></div><p>Millions of times, you say? You may already be aware that this call to the <code>.append()</code> method is similar to this more verbose version:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!eXXC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!eXXC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!eXXC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!eXXC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!eXXC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:21512,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.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_!eXXC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!eXXC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!eXXC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!eXXC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0a3ecf56-857f-4bf9-a23b-225ce9e27d0c_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#46</figcaption></figure></div><p>In this version, you use <code>append()</code> as a function. It&#8217;s a function that&#8217;s an attribute of the <code>list</code> class. Therefore, you pass the object as its first argument &#8211; this is the object that is assigned to the first parameter <code>self</code> in the <code>append()</code> signature.</p><p>Well, as it happens, Python uses the descriptor protocol to automatically equate <code>numbers.append(30)</code> to the function call <code>list.append(numbers, 30)</code>.</p><p>Functions are objects. And function objects are descriptors in Python. When you access them through an instance of a class, such as in <code>numbers.append(30)</code>, Python goes through the function&#8217;s <code>.__get__()</code> method and calls <code>list.append(numbers, 30)</code> so that you don&#8217;t have to worry about it:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!J-iy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!J-iy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png 424w, https://substackcdn.com/image/fetch/$s_!J-iy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png 848w, https://substackcdn.com/image/fetch/$s_!J-iy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png 1272w, https://substackcdn.com/image/fetch/$s_!J-iy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!J-iy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png" width="1200" height="378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:378,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:30787,&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://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.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_!J-iy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png 424w, https://substackcdn.com/image/fetch/$s_!J-iy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png 848w, https://substackcdn.com/image/fetch/$s_!J-iy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png 1272w, https://substackcdn.com/image/fetch/$s_!J-iy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e8c0159-a96d-4d22-9ab4-9eb4d5402dc2_1200x378.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#47</figcaption></figure></div><p>Functions have a <code>.__get__()</code> method, which makes them descriptors. Since you can&#8217;t set the value for a function object, they don&#8217;t have a <code>.__set__()</code> method. Descriptors that only have a <code>.__get__()</code> special method, such as functions, are non-data descriptors. Non-data descriptors don&#8217;t get the same precedence as data descriptors when Python is figuring out what to do when you use the dot notation. But that&#8217;s a topic for another day&#8230;</p><p>As with many topics, learning about descriptors helps you learn about descriptors (duh!), but it also helps you understand Python better.</p><p>So, descriptors are a useful tool whenever you want to perform additional tasks, such as validation, whenever you get or set the value of an attribute. What makes them a bit weird until you get used to them is that the logic is defined in the descriptor class itself. The benefit of this is that you can use descriptors across many classes and rely on the same logic, without having to define that logic in each class.</p><p>For example, you can use <code>Price()</code> objects, which are descriptors, in any class where you need to use prices and apply the same validation you defined in this article. And you can add functions to <em>any</em> class safe in the knowledge that the descriptor protocol will ensure they&#8217;re treated as instance methods when they&#8217;re accessed (unless you use the <code>@classmethod</code> or <code>@staticmethod</code> decorators, which &#8211; you guessed it &#8211; also use the descriptor protocol to perform their magic.)</p><p>In summary, a descriptor is an object that hijacks the attribute access process triggered by the dot notation. Normally, when you access an attribute of an object, the object&#8217;s class deals with finding the value. However, when the attribute is a descriptor, the descriptor class takes over.</p><div><hr></div><p>Did you enjoy this article? Did you understand how descriptors work? That&#8217;s not an easy feat!</p><p>Do you want to become a premium subscriber and join <em>The Club</em> to help support this publication and ensure there are more articles like this one?</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ohw0!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ohw0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ohw0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ohw0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ohw0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ohw0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg" width="622" height="413.10027472527474" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:967,&quot;width&quot;:1456,&quot;resizeWidth&quot;:622,&quot;bytes&quot;:796911,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.thepythoncodingstack.com/i/191055116?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.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_!Ohw0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Ohw0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Ohw0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Ohw0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F715dbc5d-d1fa-4ff2-91f0-d41aa7d85dc3_4288x2848.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em><a href="https://www.pexels.com/photo/round-clock-mechanism-4760575/">Photo by Ej Agumbay</a></em></p><div><hr></div><p><em>Code in this article uses Python 3.14</em></p><p><em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify</a>.</em> <em>[Affiliate link]</em></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p><div><hr></div><p>Further reading related to this article&#8217;s topic:</p><ul><li><p><a href="https://www.thepythoncodingstack.com/p/the-properties-of-python-property">The Properties of Python&#8217;s </a><code>property</code></p></li></ul><div><hr></div><h2>Appendix: Code Blocks</h2><h5>Code Block #1</h5><pre><code><code>class Product:
    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self.cost_price = cost_price
        self.selling_price = selling_price
        self.profit_margin = self.selling_price - self.cost_price
</code></code></pre><h5>Code Block #2</h5><pre><code><code># ...
coffee = Product("Espresso", 2.5, 4.5)
print(f"{coffee.profit_margin=}")
</code></code></pre><h5>Code Block #3</h5><pre><code><code># ...
coffee = Product("Espresso", 2.5, 4.5)
coffee.selling_price = 5.5
print(f"{coffee.profit_margin=}")
</code></code></pre><h5>Code Block #4</h5><pre><code><code>class Product:
    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self.cost_price = cost_price
        self.selling_price = selling_price

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price

coffee = Product("Espresso", 2.5, 4.5)
coffee.selling_price = 5.5
print(f"{coffee.profit_margin=}")
</code></code></pre><h5>Code Block #5</h5><pre><code><code># ...
coffee.profit_margin = 4
</code></code></pre><h5>Code Block #6</h5><pre><code><code>class Product:
    def __init__(self, name, cost_price, selling_price):
        self.name = name
        if cost_price &lt; 0:
            raise ValueError("Cost price cannot be negative")
        self.cost_price = cost_price
        self.selling_price = selling_price

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price
      
# ...
</code></code></pre><h5>Code Block #7</h5><pre><code><code># ...
coffee = Product("Espresso", -2.5, 4.5)
</code></code></pre><h5>Code Block #8</h5><pre><code><code># ...
coffee = Product("Espresso", 2.5, 4.5)  # Back to correct cost price
coffee.cost_price = -1
print(f"{coffee.cost_price=}")
</code></code></pre><h5>Code Block #9</h5><pre><code><code>class Product:
    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self.selling_price = selling_price
        
    @property
    def cost_price(self):
        # ???
        ...

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price
      
# ...
</code></code></pre><h5>Code Block #10</h5><pre><code><code>class Product:
    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self._cost_price = cost_price
        self.selling_price = selling_price

    @property
    def cost_price(self):
        return self._cost_price

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price
      
# ...
</code></code></pre><h5>Code Block #11</h5><pre><code><code># ...
coffee = Product("Espresso", 2.5, 4.5)
print(f"{coffee.cost_price=}")
</code></code></pre><h5>Code Block #12</h5><pre><code><code># ...
coffee = Product("Espresso", 2.5, 4.5)
coffee.cost_price = 3
print(f"{coffee.cost_price=}")
</code></code></pre><h5>Code Block #13</h5><pre><code><code>class Product:
    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self._cost_price = cost_price
        self.selling_price = selling_price

    @property
    def cost_price(self):
        return self._cost_price

    @cost_price.setter
    def cost_price(self, value):
        if value &lt; 0:
            raise ValueError("Cost price cannot be negative")
        self._cost_price = value

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price

coffee = Product("Espresso", 2.5, 4.5)
coffee.cost_price = 3
print(f"{coffee.cost_price=}")
</code></code></pre><h5>Code Block #14</h5><pre><code><code># ...
coffee = Product("Espresso", 2.5, 4.5)
coffee.cost_price = -3
print(f"{coffee.cost_price=}")
</code></code></pre><h5>Code Block #15</h5><pre><code><code># ...
coffee = Product("Espresso", -2.5, 4.5)
print(f"{coffee.cost_price=}")
</code></code></pre><h5>Code Block #16</h5><pre><code><code>class Product:
    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self.cost_price = cost_price
        self.selling_price = selling_price

    @property
    def cost_price(self):
        return self._cost_price

    @cost_price.setter
    def cost_price(self, value):
        if value &lt; 0:
            raise ValueError("Cost price cannot be negative")
        self._cost_price = value

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price
      
# ...
</code></code></pre><h5>Code Block #17</h5><pre><code><code>0.1 + 0.2
# 0.30000000000000004
</code></code></pre><h5>Code Block #18</h5><pre><code><code>from decimal import Decimal
Decimal("0.1") + Decimal("0.2")
# Decimal('0.3')
</code></code></pre><h5>Code Block #19</h5><pre><code><code>from decimal import Decimal, InvalidOperation

class Product:
    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self.cost_price = cost_price
        self.selling_price = selling_price

    @property
    def cost_price(self):
        return self._cost_price

    @cost_price.setter
    def cost_price(self, value):
        try:
            value = Decimal(str(value))
        except InvalidOperation:
            raise TypeError("Invalid format for cost price")
        if value &lt; 0:
            raise ValueError("Cost price cannot be negative")
        self._cost_price = value

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price
      
# ...
</code></code></pre><h5>Code Block #20</h5><pre><code><code>from decimal import Decimal, InvalidOperation

class Product:
    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self.cost_price = cost_price
        self.selling_price = selling_price

    @property
    def cost_price(self):
        return self._cost_price

    @cost_price.setter
    def cost_price(self, value):
        try:
            value = Decimal(str(value))
        except InvalidOperation:
            raise TypeError("Invalid format for cost price")
        if value &lt; 0:
            raise ValueError("Cost price cannot be negative")
        self._cost_price = value

    @property
    def selling_price(self):
        return self._selling_price

    @selling_price.setter
    def selling_price(self, value):
        try:
            value = Decimal(str(value))
        except InvalidOperation:
            raise TypeError("Invalid format for selling price")
        if value &lt; 0:
            raise ValueError("Selling price cannot be negative")
        self._selling_price = value

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price
</code></code></pre><h5>Code Block #21</h5><pre><code><code># ...

class Price:
    """Descriptor to handle price validation and Decimal conversion."""
    
    def __get__(self, instance, owner):
        ...

    def __set__(self, instance, value):
        ...
        
# ...
</code></code></pre><h5>Code Block #22</h5><pre><code><code># ...

class Product:
    cost_price = Price()
    selling_price = Price()

    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self.cost_price = cost_price
        self.selling_price = selling_price

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price

# ...
</code></code></pre><h5>Code Block #23</h5><pre><code><code># ...

class Price:
    def __get__(self, instance, owner):
        print("Calling Price.__get__()")
        return "Price coming soon..."

    def __set__(self, instance, value):
        print("Calling Price.__set__()")

# ...
</code></code></pre><h5>Code Block #24</h5><pre><code><code>class Price:
    def __get__(self, instance, owner):
        print("Calling Price.__get__()")
        return "Price coming soon..."

    def __set__(self, instance, value):
        print("Calling Price.__set__()")

class Product:
    cost_price = Price()
    selling_price = Price()

    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self.cost_price = cost_price
        self.selling_price = selling_price

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price


coffee = Product("Espresso", 3.2, 5)
</code></code></pre><h5>Code Block #25</h5><pre><code><code># ...
coffee = Product("Espresso", 3.2, 5)
print(coffee.selling_price)
</code></code></pre><h5>Code Block #26</h5><pre><code><code>class Price:
    def __get__(self, instance, owner):
        print("Calling Price.__get__()")
        print(f"{self=}")
        print(f"{instance=}")
        print(f"{owner=}")
        return "Price coming soon..."
      
      # ...
</code></code></pre><h5>Code Block #27</h5><pre><code><code>coffee.selling_price
</code></code></pre><h5>Code Block #28</h5><pre><code><code># ...
print(Product.selling_price)
</code></code></pre><h5>Code Block #29</h5><pre><code><code>class Price:
    # ...

    def __set__(self, instance, value):
        print("Calling Price.__set__()")
        print(f"{self=}")
        print(f"{instance=}")
        print(f"{value=}")
# ...
</code></code></pre><h5>Code Block #30</h5><pre><code><code># ...
coffee = Product("Espresso", 3.2, 5)
</code></code></pre><h5>Code Block #31</h5><pre><code><code>from decimal import Decimal, InvalidOperation

class Price:
    def __get__(self, instance, owner):
        print("Calling Price.__get__()")
        # more code coming soon here

    def __set__(self, instance, value):
        print("Calling Price.__set__()")
        try:
            value = Decimal(str(value))
        except InvalidOperation:
            raise TypeError(f"Invalid format for 'cost_price': {value}")

        if value &lt; 0:
            raise ValueError(f"'cost_price' can't be less than zero")

        setattr(instance, "_cost_price", value)

# ...
</code></code></pre><h5>Code Block #32</h5><pre><code><code># ...

coffee = Product("Espresso", 3.2, 5)
print(coffee.cost_price)
</code></code></pre><h5>Code Block #33</h5><pre><code><code># ...

coffee = Product("Espresso", 3.2, 5)
print(coffee._cost_price)
</code></code></pre><h5>Code Block #34</h5><pre><code><code>from decimal import Decimal, InvalidOperation

class Price:
    def __get__(self, instance, owner):
        print("Calling Price.__get__()")
        return getattr(instance, "_cost_price")

    def __set__(self, instance, value):
        print("Calling Price.__set__()")
        try:
            value = Decimal(str(value))
        except InvalidOperation:
            raise TypeError(f"Invalid format for 'cost_price': {value}")

        if value &lt; 0:
            raise ValueError(f"'cost_price' can't be less than zero")

        setattr(instance, "_cost_price", value)
</code></code></pre><h5>Code Block #35</h5><pre><code><code># ...

coffee = Product("Espresso", 3.2, 5)
print(coffee.cost_price)
</code></code></pre><h5>Code Block #36</h5><pre><code><code># ...

coffee = Product("Espresso", -3.2, 5)
</code></code></pre><h5>Code Block #37</h5><pre><code><code># ...
coffee = Product("Espresso", "three point two", 5)
</code></code></pre><h5>Code Block #38</h5><pre><code><code>from decimal import Decimal, InvalidOperation

class Price:
    def __get__(self, instance, owner):
        print("Calling Price.__get__()")
        if instance is None:
            return self
        return getattr(instance, "_cost_price")
    # ...
</code></code></pre><h5>Code Block #39</h5><pre><code><code>from decimal import Decimal, InvalidOperation

class Price:
    def __set_name__(self, owner, name):
        print("Calling Price.__set_name__()")
        print(f"{self=}")
        print(f"{owner=}")
        print(f"{name=}")
        
&#9;&#9;# ...
</code></code></pre><h5>Code Block #40</h5><pre><code><code>from decimal import Decimal, InvalidOperation

class Price:
    def __set_name__(self, owner, name):
        print("Calling Price.__set_name__()")
        self.public_name = name
        self.private_name = f"_{name}"

# ...
</code></code></pre><h5>Code Block #41</h5><pre><code><code>from decimal import Decimal, InvalidOperation

class Price:
    def __set_name__(self, owner, name):
        self.public_name = name
        self.private_name = f"_{name}"

    def __get__(self, instance, owner):
        if instance is None:
            return self
        return getattr(instance, self.private_name)

    def __set__(self, instance, value):
        try:
            value = Decimal(str(value))
        except InvalidOperation:
            raise TypeError(
                f"Invalid format for '{self.public_name}': {value}"
            )

        if value &lt; 0:
            raise ValueError(
                f"'{self.public_name}' can't be less than zero"
            )

        setattr(instance, self.private_name, value)

# ...
</code></code></pre><h5>Code Block #42</h5><pre><code><code># ...
coffee = Product("Espresso", 3.2, 5)
print(coffee.cost_price)
print(coffee.selling_price)
print(coffee.profit_margin)
</code></code></pre><h5>Code Block #43</h5><pre><code><code>from decimal import Decimal, InvalidOperation

class Price:
    def __set_name__(self, owner, name):
        self.public_name = name
        self.private_name = f"_{name}"

    def __get__(self, instance, owner):
        if instance is None:
            return self
        return getattr(instance, self.private_name)

    def __set__(self, instance, value):
        try:
            value = Decimal(str(value))
        except InvalidOperation:
            raise TypeError(
                f"Invalid format for '{self.public_name}': {value}"
            )

        if value &lt; 0:
            raise ValueError(
                f"'{self.public_name}' can't be less than zero"
            )

        setattr(instance, self.private_name, value)

class Product:
    cost_price = Price()
    selling_price = Price()

    def __init__(self, name, cost_price, selling_price):
        self.name = name
        self.cost_price = cost_price
        self.selling_price = selling_price

    @property
    def profit_margin(self):
        return self.selling_price - self.cost_price
</code></code></pre><h5>Code Block #44</h5><pre><code><code># ...
print(hasattr(Product.profit_margin, "__get__"))
</code></code></pre><h5>Code Block #45</h5><pre><code><code>numbers = [10, 20]
numbers.append(30)
numbers
# [10, 20, 30]
</code></code></pre><h5>Code Block #46</h5><pre><code><code>numbers = [10, 20]
list.append(numbers, 30)
numbers
# [10, 20, 30]
</code></code></pre><h5>Code Block #47</h5><pre><code><code>def some_function():
    ...
hasattr(some_function, "__get__")
# True
hasattr(some_function, "__set__")
# False
</code></code></pre><div><hr></div><p><em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts</a>, videos, a members&#8217; forum, and more.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><p><em>You can also support this publication by making a <a href="https://buy.stripe.com/00g3de2iGdgg4gg7su">one-off contribution of any amount you wish</a>.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://buy.stripe.com/00g3de2iGdgg4gg7su&quot;,&quot;text&quot;:&quot;Support The Python Coding Stack&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://buy.stripe.com/00g3de2iGdgg4gg7su"><span>Support The Python Coding Stack</span></a></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p>]]></content:encoded></item><item><title><![CDATA[Field Notes: First, Second, and Five Hundred and Twenty-Third]]></title><description><![CDATA[Have you ever needed to convert numbers like 22 into the string &#8220;twenty-two&#8221; or 523 into &#8220;five hundred and twenty-third&#8221;?]]></description><link>https://www.thepythoncodingstack.com/p/field-notes-first-second-and-five</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/field-notes-first-second-and-five</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Mon, 09 Mar 2026 15:25:48 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/4b146607-5d93-4c07-aed6-8b65fce4e239_840x600.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Most of my posts on</em> The Python Coding Stack<em>, whether in the main publication or here in</em> The Club<em>, typically focus on some aspect of core Python and explore it through a step-by-step approach, a mini-project, or sometimes through an essay-type article.</em></p><p><em>But today, I&#8217;ll write a short post about some tools I came across that may be interesting. I&#8217;ll keep the post short since, if you&#8217;re interested, you can easily explore the packages independently &#8211; you won&#8217;t need my explanatory efforts.</em></p><div><hr></div><p>Remember some of the earliest code you ever wrote? It may have looked like this:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;59aefe4d-d092-4ca5-8e83-abda31f26c1a&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">first = input(&#8221;Enter the first number: &#8220;)
second = input(&#8221;Enter the second number: &#8220;)
print(
    f&#8221;The sum of the two numbers is {float(first) + float(second)}&#8221;
)</code></pre></div><p>Those days are long gone. But what if you wanted this code to work for any number of inputs, not just two?</p><p>I&#8217;m not talking about the code to work out the sum itself. You&#8217;d probably use a list to collect all the numbers and the <code>sum()</code> built-in function, or just use a running total. Whatever.</p><p>The annoying part is making user-friendly strings when asking for the input &#8211; it&#8217;s fine to write <code>"first"</code> and <code>"second"</code> when there are only two prompts &#8211; and then when showing the result, which currently says <code>"two numbers"</code>. But what if you have more?</p><p>I came across this need several times, but my solution has always been to change the string so that it&#8217;s general enough to work in all cases. I&#8217;m lazy, I know.</p><p>In any case, recently I decided to look for solutions. And of course, they exist! Everything seems to exist in the Python ecosystem. Several solutions&#8230;</p><h2><code>num2words</code></h2><p>The first solution is probably the simplest: the <code>num2words</code> package doesn&#8217;t do much beyond converting numbers to words, as its name suggests. You&#8217;ll need to install <code>num2words</code> using <code>pip</code>, <code>uv</code>, or whatever you use to install packages.</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;5dc57e66-4a9b-46c9-bc1d-f2bac6e8a001&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">&gt;&gt;&gt; import num2words
&gt;&gt;&gt; num2words.num2words(34)
&#8216;thirty-four&#8217;</code></pre></div><p>The main function in the <code>num2words</code> module is also called <code>num2words()</code>, as often happens with such modules!</p><p>How far can it go?</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;6e551eb0-1a02-451d-852b-9cdcc1cb5ab6&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">&gt;&gt;&gt; num2words.num2words(5468.23)
&#8216;five thousand, four hundred and sixty-eight point two three&#8217;</code></pre></div><p>Working in Spanish?</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;a36e2039-283d-4493-9031-fd0575d6a10a&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">&gt;&gt;&gt; num2words.num2words(5468.23, lang=&#8221;es&#8221;)
&#8216;cinco mil cuatrocientos sesenta y ocho punto dos tres&#8217;</code></pre></div><p>Or Japanese?</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;python&quot;,&quot;nodeId&quot;:&quot;f65faf64-470e-44cd-b50d-f536948c1b85&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-python">&gt;&gt;&gt; num2words.num2words(5468.23, lang=&#8221;ja&#8221;)
&#8216;&#20116;&#21315;&#22235;&#30334;&#20845;&#21313;&#20843;&#28857;&#20108;&#19977;&#8217;</code></pre></div>
      <p>
          <a href="https://www.thepythoncodingstack.com/p/field-notes-first-second-and-five">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[You Store Data and You Do Stuff With Data • The OOP Mindset]]></title><description><![CDATA[Why use classes and objects?]]></description><link>https://www.thepythoncodingstack.com/p/python-oop-mindset-you-store-data-and-you-do-stuff-with-data</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/python-oop-mindset-you-store-data-and-you-do-stuff-with-data</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Thu, 05 Mar 2026 22:58:15 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!X8ae!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Learning <em>how</em> to use a tool can be challenging. But learning <em>why</em> you should use that tool&#8211;and <em>when</em>&#8211;is sometimes even more challenging.</p><p>In this post, I&#8217;ll discuss the OOP mindset&#8211;or, let&#8217;s say, one way of viewing the object-oriented paradigm. I debated with myself whether to write this article here on <em>The Python Coding Stack</em>. Most articles here are aimed at the &#8220;intermediate-ish&#8221; Python programmer, whatever &#8220;intermediate&#8221; means. Most readers may feel they already <em>understand</em> the ethos and philosophy of OOP. I know I keep discovering new perspectives from time to time. So here&#8217;s a perspective I&#8217;ve been exploring in courses I ran recently.</p><p>As you can see, I decided to write this post. At worst, it serves as revision for some readers, perhaps a different route towards understanding why we (sometimes) define classes and (always) use objects in Python. And beginners read these articles, too!</p><p>If you feel you&#8217;re an OOP Pro, go ahead and skip this post. Or just read it anyway. It&#8217;s up to you. You can always catch up with anything you may have missed from <a href="https://www.thepythoncodingstack.com/archive">The Python Coding Stack&#8217;s Archive</a> instead &#8211; around 120 full-length articles and counting!</p><p><em>This post is inspired by the introduction to OOP in Chapter 7 in <a href="https://thepythoncodingplace.com/the-python-coding-book/">The Python Coding Book &#8211; The Relaxed and Friendly Programming Book for Beginners</a></em></p><div><hr></div><p>Meet Mark, a market seller. He sets up a stall in his local market and sells tea, coffee, and home-made biscuits (aka cookies for those in North America).</p><p>I&#8217;ll write two and a half versions of the code Mark could use to keep track of his stock and sales. The first one&#8211;that&#8217;s the half&#8211;is not very pretty. Don&#8217;t write code like this. But it will serve as a starting point for the main theme of this post. The second version is a stepping stone towards the third.</p><h2><strong>First (Half) Version &#8226; Not Pretty</strong></h2><p>Mark is also learning Python in his free time. He starts writing some code:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!E89x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5eac796e-cd41-4866-b921-657d182f9e06_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!E89x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5eac796e-cd41-4866-b921-657d182f9e06_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!E89x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5eac796e-cd41-4866-b921-657d182f9e06_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!E89x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5eac796e-cd41-4866-b921-657d182f9e06_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!E89x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5eac796e-cd41-4866-b921-657d182f9e06_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5eac796e-cd41-4866-b921-657d182f9e06_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:30093,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5eac796e-cd41-4866-b921-657d182f9e06_1200x294.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_!E89x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5eac796e-cd41-4866-b921-657d182f9e06_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!E89x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5eac796e-cd41-4866-b921-657d182f9e06_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!E89x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5eac796e-cd41-4866-b921-657d182f9e06_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!E89x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5eac796e-cd41-4866-b921-657d182f9e06_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">All code blocks are available in text format at the end of this article &#8226; #1</figcaption></figure></div><p>He was planning to write some functions to update the stock, change the cost price and selling price, and deal with a sale from his market stall.</p><p>But he stopped.</p><p>We&#8217;ll also stop here with this version.</p><p>Mark is a Python beginner, but even he knew this was not the best way to store the relevant data for each product he sells.</p><p>Four separate objects? Not ideal. Mark knows that the data in these four lists are linked to each other. The first items in each list belong together, and so on. But he&#8217;ll need to manually ensure he maintains these links in the code he writes. Not impossible, but it&#8217;s asking for trouble. So many things can go wrong. And he&#8217;ll have a tough time writing the code, making all those links in every line he writes.</p><p>Mark knows what the link is between the various values. But the computer program doesn&#8217;t. The computer program sees four separate data structures, unrelated to each other. You can try writing an <code>update_stock()</code> function with this version to see the challenges, the manual work needed to connect data across separate structures.</p><p>Let&#8217;s move on.</p><h2><strong>Second Version &#8226; Dictionary and Functions</strong></h2><p>Mark learnt about dictionaries. They&#8217;re a great way to group data together:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!X257!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!X257!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png 424w, https://substackcdn.com/image/fetch/$s_!X257!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png 848w, https://substackcdn.com/image/fetch/$s_!X257!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png 1272w, https://substackcdn.com/image/fetch/$s_!X257!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!X257!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png" width="1200" height="840" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:840,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:63994,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.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_!X257!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png 424w, https://substackcdn.com/image/fetch/$s_!X257!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png 848w, https://substackcdn.com/image/fetch/$s_!X257!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png 1272w, https://substackcdn.com/image/fetch/$s_!X257!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F831a258f-5694-4ba3-b70d-be8b2306f0e2_1200x840.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#2</figcaption></figure></div><p>Now there&#8217;s one data structure that contains the three products he sells. This structure contains three other data structures, each containing all the relevant data for each product.</p><p>The data are structured into these dictionaries to show what belongs where. In this version, the Python program &#8220;knows&#8221; which data items belong together. Each dictionary contains related values.</p><p>Well done, Mark! He understood the need to organise the data into a sensible structure. This is not the only combination of nested data structures Mark could use, but this is a valid option. Certainly better than the first version!</p><p>He can write some functions now. First up is <code>update_stock()</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_!rNJj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rNJj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png 424w, https://substackcdn.com/image/fetch/$s_!rNJj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png 848w, https://substackcdn.com/image/fetch/$s_!rNJj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png 1272w, https://substackcdn.com/image/fetch/$s_!rNJj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!rNJj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png" width="1200" height="462" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:462,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:66559,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.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_!rNJj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png 424w, https://substackcdn.com/image/fetch/$s_!rNJj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png 848w, https://substackcdn.com/image/fetch/$s_!rNJj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png 1272w, https://substackcdn.com/image/fetch/$s_!rNJj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58ba20a8-f2c9-47ab-b913-8ec95bb402b3_1200x462.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#3</figcaption></figure></div><p>Let&#8217;s ignore the fact that Mark is accessing the global variable <code>products</code> within the function. We&#8217;ll have a chat with Mark about this.</p><p>Still, there&#8217;s now a function called <code>update_stock()</code>. It needs the product name as an argument. It also needs the stock amount to increase (or decrease if the value is negative).</p><p>Let&#8217;s look at another function Mark wrote:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!hZ4n!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hZ4n!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png 424w, https://substackcdn.com/image/fetch/$s_!hZ4n!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png 848w, https://substackcdn.com/image/fetch/$s_!hZ4n!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png 1272w, https://substackcdn.com/image/fetch/$s_!hZ4n!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!hZ4n!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png" width="1200" height="840" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:840,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:123883,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.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_!hZ4n!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png 424w, https://substackcdn.com/image/fetch/$s_!hZ4n!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png 848w, https://substackcdn.com/image/fetch/$s_!hZ4n!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png 1272w, https://substackcdn.com/image/fetch/$s_!hZ4n!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F03fe16a7-0577-453a-b56e-017ecda88be0_1200x840.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#4</figcaption></figure></div><p>This function also needs the product name as one of its arguments. It also needs a second argument: the quantity sold.</p><p>Mark wrote other functions, but I&#8217;ll keep this section brief so I won&#8217;t show them. However, many of Mark&#8217;s functions have a few things in common:</p><ul><li><p>They require the product name as one of the arguments. This makes sense since the operations Mark needs to carry out depend on which product he&#8217;s dealing with.</p></li><li><p>They make changes to the data in one of the inner dictionaries defined within <code>products</code>.</p></li><li><p>Some of them return data. Others don&#8217;t.</p></li></ul><p>Great. Mark is happy with his effort.</p><p>He structured the data sensibly so it&#8217;s well organised. Separately, he wrote functions that use data from those data structures&#8211;the inner dictionaries in <code>products</code> and sometimes make changes to the data in those data structures.</p><div><hr></div><p><em>Your call&#8230;</em></p><p><em>The Python Coding Place offers something for everyone:</em></p><p><em>&#8226; a super-personalised one-to-one 6-month mentoring option</em><br><em>$ 4,750</em></p><p><em>&#8226; individual one-to-one sessions</em><br><em>$ 125</em></p><p><em>&#8226; a self-led route with access to 60+ hrs of exceptional video courses and a support forum</em><br><em>$ 400</em></p><p><em><strong><a href="https://thepythoncodingplace.com?utm_source=the-python-coding-stack">Which The Python Coding Place student are you?</a></strong></em></p><div><hr></div><h2><strong>Third Version &#8226; Class and Objects</strong></h2><p>Mark&#8217;s code stores data. The nested dictionaries in <code>products</code> deal with the storage part. His code also does stuff* with the data through the functions he wrote.</p><p><em>*stuff is not quite a Python technical term, in case you&#8217;re wondering. But it&#8217;s quite suitable here, I think!</em></p><p>Lots of programs store data and do stuff with data.</p><p>Object-oriented programming takes these two separate tasks&#8211;storing data and doing stuff with data&#8211;and combines them into a single &#8220;unit&#8221;. In OOP, this &#8220;unit&#8221; is the <em>object</em>. Objects are at the centre of the OOP paradigm, which is why OOP is called OOP, after all!</p><ol><li><p>Mark&#8217;s progression from the first version to the second relied on structuring the data into units&#8211;the nested dictionary structure.</p></li><li><p>The progression from the second version to the third takes this a step further and structures the data <em>and</em> the functions that act on those data into a single unit: the object.</p></li></ol><p>This structure means that the data for each object is contained within the object, and the actions performed are also contained within that object. Everything is self-contained within the object.</p><p>Let&#8217;s build a <code>Product</code> class for Mark. But let&#8217;s do this step by step, using the code from the second version and gradually morphing it into object-oriented code. This will help us follow the transition.</p><p>First, let&#8217;s create the class:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!z1i5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!z1i5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!z1i5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!z1i5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!z1i5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:7003,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.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_!z1i5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!z1i5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!z1i5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!z1i5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5143cf31-32cd-4d87-b117-a0ff79ed70f6_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#5</figcaption></figure></div><p>Nothing much to see so far. But this is the shell that will contain all the instructions for creating this &#8220;unit,&#8221; including all the relevant data and functionality.</p><p>You can already create an <em>instance</em> of this class &#8211; that&#8217;s another way of saying <em>an object created from this class</em>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-uje!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-uje!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!-uje!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!-uje!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!-uje!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!-uje!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png" width="1200" height="336" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:336,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12896,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.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_!-uje!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!-uje!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!-uje!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!-uje!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F25d3e1e5-a426-4591-ba68-a3eb22390703_1200x336.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#6</figcaption></figure></div><p>Whereas <code>Product</code> represents the class, <code>Product()</code> is an instance of the class. Note the parentheses. There&#8217;s only one <code>Product</code>, but you can create many instances using <code>Product()</code> .</p><h3><strong>Bundling In the Functionality &#8226; Methods</strong></h3><p>Now, let me take a route I recently explored for the first time while teaching OOP in a beginners&#8217; course. It&#8217;s only subtly different from my &#8220;usual&#8221; teaching route, but I think it helped me appreciate the topic from a distinct perspective. So, here we go.</p><p>Let&#8217;s copy and paste the functions from version two directly into this class. Warning: This won&#8217;t work. We&#8217;ll need to make some changes. But let&#8217;s use this as a starting point:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-Iap!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-Iap!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png 424w, https://substackcdn.com/image/fetch/$s_!-Iap!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png 848w, https://substackcdn.com/image/fetch/$s_!-Iap!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png 1272w, https://substackcdn.com/image/fetch/$s_!-Iap!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!-Iap!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png" width="1272" height="1260" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1260,&quot;width&quot;:1272,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:208295,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.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_!-Iap!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png 424w, https://substackcdn.com/image/fetch/$s_!-Iap!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png 848w, https://substackcdn.com/image/fetch/$s_!-Iap!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png 1272w, https://substackcdn.com/image/fetch/$s_!-Iap!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F67de610b-ab76-4c8f-9467-13f3cb72a693_1272x1260.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#7</figcaption></figure></div><p>To keep you on your toes, we change the terminology here. These are functions. However, when they&#8217;re defined within a class definition, we call them <em>methods</em>. But they&#8217;re still functions. Everything you know about functions applies equally to methods.</p><p>You&#8217;ve seen that each function in version two needed to know which product it was dealing with. That&#8217;s why the first parameter is <code>product_name</code>. You used <code>product_name</code> to fetch the correct values when you needed the selling price, the cost price, or the number of items in stock.</p><p>However, now that we&#8217;re in the OOP domain, the object will contain all the data it needs&#8211;you&#8217;ll add the data-related code soon. You don&#8217;t need to fetch the data from anywhere else, just from the object <em>itself</em>.</p><p>Therefore, the functions defined within the class &#8211; the methods &#8211; no longer need the product name as the first argument. Instead, they need the entire object <em>itself</em> since this object contains all the data the method needs about the object.</p><p>We just need a parameter name to describe the object <em>itself</em>. How about <code>self</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_!F7-U!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!F7-U!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png 424w, https://substackcdn.com/image/fetch/$s_!F7-U!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png 848w, https://substackcdn.com/image/fetch/$s_!F7-U!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png 1272w, https://substackcdn.com/image/fetch/$s_!F7-U!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!F7-U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png" width="1200" height="378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:378,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:42027,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.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_!F7-U!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png 424w, https://substackcdn.com/image/fetch/$s_!F7-U!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png 848w, https://substackcdn.com/image/fetch/$s_!F7-U!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png 1272w, https://substackcdn.com/image/fetch/$s_!F7-U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F19d503ca-5374-4ea9-a497-ccf98f0a4fad_1200x378.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#8</figcaption></figure></div><p>The method signatures now include <code>self</code> as the first parameter and whatever else the methods need as the remaining parameters.</p><p>Incidentally, although you can technically name this first parameter anything you want, there&#8217;s a strong convention to always use <code>self</code>. So it&#8217;s best to stick with <code>self</code>!</p><p>The methods are the tools you use to bundle functionality into the object. Let&#8217;s pause on working on the methods for now and shift our attention to how to store the data, which also needs to be bundled into the object.</p><h3><strong>Bundling In the Data &#8226; Data Attributes</strong></h3><p>Let&#8217;s get back to the code that creates an instance of the <code>Product</code> class:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ELDx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb77c2438-d948-4408-abd0-cd2eef82a455_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!ELDx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb77c2438-d948-4408-abd0-cd2eef82a455_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!ELDx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb77c2438-d948-4408-abd0-cd2eef82a455_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!ELDx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb77c2438-d948-4408-abd0-cd2eef82a455_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ELDx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb77c2438-d948-4408-abd0-cd2eef82a455_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b77c2438-d948-4408-abd0-cd2eef82a455_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8291,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb77c2438-d948-4408-abd0-cd2eef82a455_1200x252.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_!ELDx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb77c2438-d948-4408-abd0-cd2eef82a455_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!ELDx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb77c2438-d948-4408-abd0-cd2eef82a455_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!ELDx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb77c2438-d948-4408-abd0-cd2eef82a455_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!ELDx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb77c2438-d948-4408-abd0-cd2eef82a455_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#9</figcaption></figure></div><p>The expression <code>Product()</code> does a few things behind the scenes. First, it creates a new blank object. Then it initialises this object. To initialise the object, Python needs to &#8220;do stuff&#8221;. Therefore, it needs a method. But not just any method. A special method:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Tw81!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Tw81!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png 424w, https://substackcdn.com/image/fetch/$s_!Tw81!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png 848w, https://substackcdn.com/image/fetch/$s_!Tw81!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png 1272w, https://substackcdn.com/image/fetch/$s_!Tw81!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Tw81!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png" width="1200" height="420" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:420,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:39562,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.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_!Tw81!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png 424w, https://substackcdn.com/image/fetch/$s_!Tw81!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png 848w, https://substackcdn.com/image/fetch/$s_!Tw81!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png 1272w, https://substackcdn.com/image/fetch/$s_!Tw81!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F50668299-736e-48a0-aaad-eb07baaf231f_1200x420.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#10</figcaption></figure></div><p>You can&#8217;t choose the name of this method. It must be <code>.__init__()</code>. But it&#8217;s still a method. It still takes <code>self</code> as the first parameter since it still needs access to the object itself. This method creates variables that are attached to the object. You can think of the dot as attaching <code>name</code> to <code>self</code> and so on for the others. We tend not to call these variables &#8211; more new terminology just for the OOP paradigm &#8211; they&#8217;re <em>data attributes</em>. They&#8217;re object attributes that store data.</p><p>For now, these data attributes contain default values: the empty string for the <code>.name</code> data attribute and <code>0</code> for the others. However, when you create an object, you often want to supply some or all of the data that the object needs. Often, you want to pass this information when you create the object:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1OUE!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!1OUE!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!1OUE!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!1OUE!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!1OUE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:14142,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.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_!1OUE!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!1OUE!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!1OUE!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!1OUE!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8fb4f53a-64a7-4719-a7e6-9b4e658372a6_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#11</figcaption></figure></div><p>However, when you run the code, you get an error:</p><pre><code>Traceback (most recent call last):
  ...
    a_product = Product(&#8221;Coffee&#8221;, 1.98, 3.2, 100)
TypeError: Product.__init__() takes 1 positional 
    argument but 5 were given</code></pre><p>The error message mentions <code>Product.__init__()</code>. Note how you don&#8217;t explicitly use <code>.__init__()</code> in the expression to create a <code>Product</code> object. However, Python calls this special method behind the scenes. And when it does, it complains about the arguments you passed:</p><ul><li><p><code>"Product.__init__() takes 1 positional argument..."</code> is the first part of the error message. Makes sense, since you have <code>self</code> as the one and only parameter within the definition of the <code>.__init__()</code> special method.</p></li><li><p><code>"...but 5 [arguments] were given"</code>, the error message goes on to say. Wait, why 5? You pass four objects when you create <code>Product()</code>: the string <code>"Coffee"</code>, the floats <code>1.98</code> and <code>3.2</code>, and the integer <code>100</code>. Python can&#8217;t count, it seems?</p></li></ul><p>Not quite. When Python calls a method, it automatically passes the object as the first argument. You don&#8217;t see this. You don&#8217;t need to do anything about it. It happens behind the scenes. So, soon after <code>Product()</code> creates a blank new instance, it calls <code>.__init__()</code> and passes the object as the first argument to <code>.__init__()</code>, the one that&#8217;s assigned to the parameter <code>self</code>.</p><p>Recall that methods are functions. So, Python automatically passes the object as the first argument so that these functions (methods) have access to the object.</p><p>That&#8217;s why the error message says that five arguments were passed: the object itself and the four remaining arguments.</p><p>This tells you that <code>.__init__()</code> needs five parameters. The first is <code>self</code>, which is the first parameter in these methods. Let&#8217;s add the remaining four:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KdEU!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KdEU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.png 424w, https://substackcdn.com/image/fetch/$s_!KdEU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.png 848w, https://substackcdn.com/image/fetch/$s_!KdEU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.png 1272w, https://substackcdn.com/image/fetch/$s_!KdEU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!KdEU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.png" width="1218" height="378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/606da463-e4b2-4120-b097-0974a5d66597_1218x378.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:378,&quot;width&quot;:1218,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:37034,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.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_!KdEU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.png 424w, https://substackcdn.com/image/fetch/$s_!KdEU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.png 848w, https://substackcdn.com/image/fetch/$s_!KdEU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.png 1272w, https://substackcdn.com/image/fetch/$s_!KdEU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F606da463-e4b2-4120-b097-0974a5d66597_1218x378.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#12</figcaption></figure></div><p>The code no longer raises an error since the number of arguments passed to <code>Product()</code> when you create the object &#8211; including the object itself, which is implied &#8211; matches the number of parameters in <code>.__init__()</code>. However, you want to shift the data into the data attributes you created earlier. These data attributes are the storage devices attached to the object. You want the data to be stored there:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ee1j!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ee1j!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png 424w, https://substackcdn.com/image/fetch/$s_!Ee1j!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png 848w, https://substackcdn.com/image/fetch/$s_!Ee1j!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png 1272w, https://substackcdn.com/image/fetch/$s_!Ee1j!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ee1j!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png" width="1218" height="378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:378,&quot;width&quot;:1218,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:35205,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.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_!Ee1j!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png 424w, https://substackcdn.com/image/fetch/$s_!Ee1j!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png 848w, https://substackcdn.com/image/fetch/$s_!Ee1j!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png 1272w, https://substackcdn.com/image/fetch/$s_!Ee1j!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2650aea2-eed0-4cb0-a601-db93fd0c7b5f_1218x378.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#13</figcaption></figure></div><p>The parameters are used only to transfer the data from the method call to the data attributes. From now on, the data are stored in the data attributes, which are attached to the object.</p><p>Note that the data attribute names don&#8217;t have to match the parameter names. But why bother coming up with different names? Might as well use the same ones!</p><p>Now, you can create any object you wish, each having its own data:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!02LF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!02LF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png 424w, https://substackcdn.com/image/fetch/$s_!02LF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png 848w, https://substackcdn.com/image/fetch/$s_!02LF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png 1272w, https://substackcdn.com/image/fetch/$s_!02LF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!02LF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png" width="1200" height="546" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:546,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:55983,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.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_!02LF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png 424w, https://substackcdn.com/image/fetch/$s_!02LF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png 848w, https://substackcdn.com/image/fetch/$s_!02LF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png 1272w, https://substackcdn.com/image/fetch/$s_!02LF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F21b7ea38-19c2-44ef-bf4e-a0d2dc968ecb_1200x546.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#14</figcaption></figure></div><p>Here&#8217;s the output:</p><pre><code>Coffee
Tea
3.2
2.25</code></pre><p>Every instance of the <code>Product</code> class will have a <code>.name</code>, <code>.cost_price</code>, <code>.selling_price</code>, and <code>.stock</code>. But each instance will have its own values for those data attributes. Each object is distinct from the others. The data is self-contained within the object.</p><h3><strong>Back to the Functionality &#8226; Methods</strong></h3><p>Let&#8217;s look at the class so far, which still has code pasted from version two earlier:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7mVZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7mVZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png 424w, https://substackcdn.com/image/fetch/$s_!7mVZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png 848w, https://substackcdn.com/image/fetch/$s_!7mVZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png 1272w, https://substackcdn.com/image/fetch/$s_!7mVZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!7mVZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png" width="1272" height="1512" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1512,&quot;width&quot;:1272,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:234542,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.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_!7mVZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png 424w, https://substackcdn.com/image/fetch/$s_!7mVZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png 848w, https://substackcdn.com/image/fetch/$s_!7mVZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png 1272w, https://substackcdn.com/image/fetch/$s_!7mVZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4c425b1e-6ff3-477c-aca7-9ade1211e4ae_1272x1512.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#15</figcaption></figure></div><p>Let&#8217;s focus on <code>.update_stock()</code> first. Note how in my writing style guide, I use a leading dot when writing method names, such as <code>.update_stock()</code>. That&#8217;s because they&#8217;re also attributes of the object. To call a method, you call it through the object, such as <code>a_product.update_stock(30)</code>.</p><p>Recall that Python will pass the object <em>itself</em> as the first argument to the method. That&#8217;s the argument assigned to <code>self</code>. You then pass <code>30</code> to the parameter <code>stock_increment</code>.</p><p>But this means that this method can only act on an object that already exists, that already has the data attributes it needs. You no longer need to check whether the product exists. If you&#8217;re calling this method, you&#8217;re calling it on a product. Checks on existence will happen elsewhere in your code.</p><p>So, all that&#8217;s left is to increment the stock for this object. The current stock is stored in the <code>.stock</code> data attribute &#8211; the data attribute that&#8217;s connected to the object. But you passed the object to <code>.update_stock()</code>, so you can access <code>self.stock</code> from within the method:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!N97H!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!N97H!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!N97H!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!N97H!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!N97H!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19884,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.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_!N97H!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!N97H!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!N97H!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!N97H!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2683369b-d547-42c0-b821-dfd60661d0e9_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#16</figcaption></figure></div><p>And that&#8217;s it. Everything is self-contained within the object. The method acts on the object and modifies one of the object&#8217;s data attributes.</p><p>How about the <code>.sell()</code> method?</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!qOzq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!qOzq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png 424w, https://substackcdn.com/image/fetch/$s_!qOzq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png 848w, https://substackcdn.com/image/fetch/$s_!qOzq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png 1272w, https://substackcdn.com/image/fetch/$s_!qOzq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!qOzq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png" width="1272" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1272,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:78361,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.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_!qOzq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png 424w, https://substackcdn.com/image/fetch/$s_!qOzq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png 848w, https://substackcdn.com/image/fetch/$s_!qOzq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png 1272w, https://substackcdn.com/image/fetch/$s_!qOzq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6213da54-d72a-46bf-a868-b6affd44dfeb_1272x630.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#17</figcaption></figure></div><p>Again, you can remove the validation to check that the product exists. A method is called on a <code>Product</code> object, so it exists. This method then uses three of the object&#8217;s data attributes to perform its task.</p><p>Note that you can add similar validation in <code>.update_stock()</code> to ensure the stock doesn&#8217;t dip below <code>0</code>. However, <code>stock_increment</code> can be negative to enable reducing the stock. You could even use <code>.update_stock()</code> within <code>.sell()</code> if you wish.</p><div><hr></div><p>Ah, what about the biscuits? You can still use a list of products, but this time the list contains <code>Product</code> objects:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!YJBc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!YJBc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png 424w, https://substackcdn.com/image/fetch/$s_!YJBc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png 848w, https://substackcdn.com/image/fetch/$s_!YJBc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png 1272w, https://substackcdn.com/image/fetch/$s_!YJBc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!YJBc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png" width="1200" height="378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:378,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:33140,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.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_!YJBc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png 424w, https://substackcdn.com/image/fetch/$s_!YJBc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png 848w, https://substackcdn.com/image/fetch/$s_!YJBc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png 1272w, https://substackcdn.com/image/fetch/$s_!YJBc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fecd689a1-d478-47f5-a966-cce06885dee5_1200x378.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#18</figcaption></figure></div><p>Or, if you prefer, you can use a dictionary:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jUm2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jUm2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!jUm2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!jUm2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!jUm2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!jUm2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png" width="1200" height="336" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:336,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:33414,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.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_!jUm2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!jUm2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!jUm2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!jUm2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcdf5c65c-133b-4286-859e-8bb9793df9cd_1200x336.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#19</figcaption></figure></div><p>Let&#8217;s trial out this dictionary and the <code>Product</code> class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!BaYC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BaYC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!BaYC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!BaYC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!BaYC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!BaYC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png" width="1200" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:89449,&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://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.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_!BaYC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!BaYC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!BaYC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!BaYC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbdafbc9b-c2d7-4d73-a0da-9bba48c2d376_1200x756.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#20</figcaption></figure></div><p>In this basic use case, you use the item input by the user to fetch the corresponding <code>Product</code> object from the <code>products</code> dictionary. You assign this object to the variable name <code>product</code>. Then you can call its methods, such as <code>.sell()</code>, and access its data attributes, such as <code>.name</code> and <code>.stock</code>.</p><p>Here&#8217;s the output from this code, including sample user inputs:</p><pre><code>Enter item: coffee
Enter quantity of Coffee sold: 3
The income from this sale is &#163;9.60
The profit from this sale is &#163;3.66
Remaining Coffee units: 97</code></pre><h2><strong>Final Words</strong></h2><p>The aim of this article is not to provide a comprehensive and exhaustive walkthrough of OOP. I wrote elsewhere about OOP. You can start from <em><a href="https://thepythoncodingplace.com/the-python-coding-book/">The Python Coding Book</a></em> and then read the seven-part series <em><a href="https://www.thepythoncodingstack.com/p/a-magical-tour-through-object-oriented">A Magical Tour Through Object-Oriented Programming in Python &#8226; Hogwarts School of Codecraft and Algorithmancy</a></em>.</p><p>You can learn about the syntax and the mechanics of defining and using classes. And that&#8217;s important if you want to write classes. But just as importantly, you need to adopt an OOP mindset. A central point is how OOP bundles data and functionality into a single unit, the object, and how everything stems from that structure.</p><p>In this post, you saw how data is bundled into the object through data attributes. And you bundled the high-level functionality that matters for your object through the methods <code>.update_stock()</code> and <code>.sell()</code>. Mark will need more of these methods, as you can imagine.</p><p>However, the object also includes low-level functionality. What should Python do when it needs to print the object? How about if it needs to add it to another object? Should that be possible? Should the object be considered <code>False</code> under any circumstance, say? These operations are defined by an object&#8217;s special methods, also known as dunder methods. I proposed thinking of these as &#8220;plumbing methods&#8221; recently: <a href="https://www.thepythoncodingstack.com/p/pythons-plumbing-is-not-as-flashy">&#8220;Python&#8217;s Plumbing&#8221; Is Not As Flashy as &#8220;Magic Methods&#8221; &#8226; But Is It Better?</a></p><p>Therefore, there&#8217;s plenty of high-level and low-level functionality bundled within the object. And the data, of course.</p><p>Here&#8217;s another relatively recent post you may enjoy in case you missed it when it was published: <a href="https://www.thepythoncodingstack.com/p/my-life-the-autobiography-of-a-python-object">My Life &#8226; The Autobiography of a Python Object</a>.</p><p>In summary, OOP structures data and functionality into a single unit &#8211; the object. Then, your code is oriented around this object.</p><div class="pullquote"><p><em>Do you want to master Python one article at a time? Then don&#8217;t miss out on the articles in The Club which are exclusive to premium subscribers here on The Python Coding Stack</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!X8ae!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!X8ae!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg 424w, https://substackcdn.com/image/fetch/$s_!X8ae!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg 848w, https://substackcdn.com/image/fetch/$s_!X8ae!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!X8ae!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!X8ae!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg" width="622" height="829.190934065934" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1941,&quot;width&quot;:1456,&quot;resizeWidth&quot;:622,&quot;bytes&quot;:1368065,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.thepythoncodingstack.com/i/190048208?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.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_!X8ae!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg 424w, https://substackcdn.com/image/fetch/$s_!X8ae!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg 848w, https://substackcdn.com/image/fetch/$s_!X8ae!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!X8ae!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F0c839d9c-76df-411e-982e-25c9d1762b66_3024x4032.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em>Photo by <a href="https://www.pexels.com/photo/bamboo-sticks-tied-together-in-bundles-5607157/">gomed fashion</a></em></p><div><hr></div><p><em>Code in this article uses Python 3.14</em></p><p><em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify</a>.</em> <em>[Affiliate link]</em></p><p><em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts</a>, videos, a members&#8217; forum, and more.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><p><em>You can also support this publication by making a <a href="https://buy.stripe.com/00g3de2iGdgg4gg7su">one-off contribution of any amount you wish</a>.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://buy.stripe.com/00g3de2iGdgg4gg7su&quot;,&quot;text&quot;:&quot;Support The Python Coding Stack&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://buy.stripe.com/00g3de2iGdgg4gg7su"><span>Support The Python Coding Stack</span></a></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p><p>Further reading related to this article&#8217;s topic:</p><ul><li><p><a href="https://thepythoncodingplace.com/the-python-coding-book/">The Python Coding Book</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/a-magical-tour-through-object-oriented">A Magical Tour Through Object-Oriented Programming in Python &#8226; Hogwarts School of Codecraft and Algorithmancy</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/my-life-the-autobiography-of-a-python-object">My Life &#8226; The Autobiography of a Python Object</a></p></li></ul><div><hr></div><h2>Appendix: Code Blocks</h2><h5>Code Block #1</h5><pre><code><code>products = ["Coffee", "Tea", "Biscuits"]
cost_price = [1.98, 0.85, 3.1]
selling_price = [3.2, 2.25, 5]
stock = [100, 200, 25]
</code></code></pre><h5>Code Block #2</h5><pre><code><code>products = {
    "Coffee": {
        "cost_price": 1.98,
        "selling_price": 3.2,
        "stock": 100,
    },
    "Tea": {
        "cost_price": 0.85,
        "selling_price": 2.25,
        "stock": 200,
    },
    "Biscuits": {
        "cost_price": 3.1,
        "selling_price": 5,
        "stock": 25,
    },
}
</code></code></pre><h5>Code Block #3</h5><pre><code><code># ...
def update_stock(product_name, stock_increment):
    if product_name not in products:
        raise KeyError(f"Product {product_name} not found")
    products[product_name]["stock"] += stock_increment
    # We'll need to have a chat with Mark about the issues
    # with accessing global variables from functions.
    # Let's let it pass here!
</code></code></pre><h5>Code Block #4</h5><pre><code><code># ...
def sell(product_name, quantity):
    if product_name not in products:
        raise KeyError(f"Product {product_name} not found")
    if quantity &lt;= 0:
        raise ValueError("Quantity must be greater than zero")
    if products[product_name]["stock"] &lt; quantity:
        raise ValueError("Not enough stock")
        
    products[product_name]["stock"] -= quantity
    selling_price = products[product_name]["selling_price"]
    cost_price = products[product_name]["cost_price"]

    income = selling_price * quantity
    profit = (selling_price - cost_price) * quantity

    return income, profit
</code></code></pre><h5>Code Block #5</h5><pre><code><code>class Product:
    ...
</code></code></pre><h5>Code Block #6</h5><pre><code><code>class Product:
    ...
    

a_product = Product()
</code></code></pre><h5>Code Block #7</h5><pre><code><code>class Product:
    # Just pasting the functions from Version 2 here for now.
    # This still doesn't work. It's a work-in-progress
    def update_stock(product_name, stock_increment):
        if product_name not in products:
            raise KeyError(f"Product {product_name} not found")
        products[product_name]["stock"] += stock_increment
        # We'll need to have a chat with Mark about the issues
        # with accessing global variables from functions.
        # Let's let it pass here!

    def sell(product_name, quantity):
        if product_name not in products:
            raise KeyError(f"Product {product_name} not found")
        if quantity &lt;= 0:
            raise ValueError("Quantity must be greater than zero")
        if products[product_name]["stock"] &lt; quantity:
            raise ValueError("Not enough stock")

        products[product_name]["stock"] -= quantity
        selling_price = products[product_name]["selling_price"]
        cost_price = products[product_name]["cost_price"]

        income = selling_price * quantity
        profit = (selling_price - cost_price) * quantity

        return income, profit
</code></code></pre><h5>Code Block #8</h5><pre><code><code>class Product:
    def update_stock(self, stock_increment):
        # rest of code pasted from version two (for now)

    def sell(self, quantity):
        # rest of code pasted from version two (for now)
</code></code></pre><h5>Code Block #9</h5><pre><code><code># ...

a_product = Product()
</code></code></pre><h5>Code Block #10</h5><pre><code><code>class Product:
    # We'll make improvements to this method soon
    def __init__(self):
        self.name = ""
        self.cost_price = 0
        self.selling_price = 0
        self.stock = 0
</code></code></pre><h5>Code Block #11</h5><pre><code><code># ...

a_product = Product("Coffee", 1.98, 3.2, 100)
</code></code></pre><h5>Code Block #12</h5><pre><code><code>class Product:
    def __init__(self, name, cost_price, selling_price, stock):
        self.name = ""
        self.cost_price = 0
        self.selling_price = 0
        self.stock = 0
</code></code></pre><h5>Code Block #13</h5><pre><code><code>class Product:
    def __init__(self, name, cost_price, selling_price, stock):
        self.name = name
        self.cost_price = cost_price
        self.selling_price = selling_price
        self.stock = stock
</code></code></pre><h5>Code Block #14</h5><pre><code><code># ...

a_product = Product("Coffee", 1.98, 3.2, 100)
another_product = Product("Tea", 0.85, 2.25, 200)

print(a_product.name)
print(another_product.name)

print(a_product.selling_price)
print(another_product.selling_price)
</code></code></pre><h5>Code Block #15</h5><pre><code><code>class Product:
    def __init__(self, name, cost_price, selling_price, stock):
        self.name = name
        self.cost_price = cost_price
        self.selling_price = selling_price
        self.stock = stock

    # Just pasting the functions from Version 2 here for now.
    # This still doesn't work. It's a work-in-progress
    def update_stock(self, stock_increment):
        if product_name not in products:
            raise KeyError(f"Product {product_name} not found")
        products[product_name]["stock"] += stock_increment
        # We'll need to have a chat with Mark about the issues
        # with accessing global variables from functions.
        # Let's let it pass here!

    def sell(self, quantity):
        if product_name not in products:
            raise KeyError(f"Product {product_name} not found")
        if quantity &lt;= 0:
            raise ValueError("Quantity must be greater than zero")
        if products[product_name]["stock"] &lt; quantity:
            raise ValueError("Not enough stock")

        products[product_name]["stock"] -= quantity
        selling_price = products[product_name]["selling_price"]
        cost_price = products[product_name]["cost_price"]

        income = selling_price * quantity
        profit = (selling_price - cost_price) * quantity

        return income, profit
</code></code></pre><h5>Code Block #16</h5><pre><code><code># ...
    def update_stock(self, stock_increment):
        self.stock += stock_increment
</code></code></pre><h5>Code Block #17</h5><pre><code><code># ...
    def sell(self, quantity):
        if quantity &lt;= 0:
            raise ValueError("Quantity must be greater than zero")
        if self.stock &lt; quantity:
            raise ValueError("Not enough stock")

        self.stock -= quantity
        income = self.selling_price * quantity
        profit = (self.selling_price - self.cost_price) * quantity

        return income, profit
</code></code></pre><h5>Code Block #18</h5><pre><code><code># ...
products = [
    Product("Coffee", 1.98, 3.2, 100),
    Product("Tea", 0.85, 2.25, 200),
    Product("Biscuits", 3.1, 5, 25),
]
</code></code></pre><h5>Code Block #19</h5><pre><code><code>products = {
    "Coffee": Product("Coffee", 1.98, 3.2, 100),
    "Tea": Product("Tea", 0.85, 2.25, 200),
    "Biscuits": Product("Biscuits", 3.1, 5, 25),
}
</code></code></pre><h5>Code Block #20</h5><pre><code><code># ...

# I've kept this demo code brief and simple, so it lacks
# verification and robustness. You can add this if you wish!

item = input("Enter item: ").title()
qty = int(input(f"Enter quantity of {item} sold: "))

product = products[item]
income, profit = product.sell(qty)

print(f"The income from this sale is &#163;{income:.2f}")
print(f"The profit from this sale is &#163;{profit:.2f}")

print(f"Remaining {product.name} units: {product.stock}")
</code></code></pre><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p>]]></content:encoded></item><item><title><![CDATA[“Python’s Plumbing” Is Not As Flashy as “Magic Methods” • But Is It Better?]]></title><description><![CDATA[Dunder methods are the pipes and valves that are out of sight, but that keep everything flowing in Python]]></description><link>https://www.thepythoncodingstack.com/p/pythons-plumbing-is-not-as-flashy</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/pythons-plumbing-is-not-as-flashy</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Tue, 24 Feb 2026 13:56:05 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/87ba71f7-042a-4178-adc7-e69de2f2f01e_1920x1380.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You&#8217;ve heard this phrase before: &#8220;Everything is an object in Python&#8221;. But here&#8217;s another phrase that&#8217;s related but rather less catchy:</p><blockquote><p>Everything goes through special methods (dunder methods) in Python</p></blockquote><p>Special methods are everywhere. However, you don&#8217;t see them. In fact, you&#8217;re not meant to use them directly unless you&#8217;re defining them within a class. They&#8217;re out of sight. But they keep everything moving smoothly in Python.</p><p>Here&#8217;s a short essay exploring where these special methods fit within Python.</p><h2><strong>Why Should I Care About Special Methods?</strong></h2><p>&#8220;Everything goes through special methods in Python.&#8221; I should probably preface the phrase with &#8220;almost&#8221;, but the phrase is already unwieldy as it is.</p><p>You want to display an object on the screen? Python looks for guidance in <code>.__str__()</code> or <code>.__repr__()</code>.</p><p>You want to use the object in a <code>for</code> loop? Is it even possible? Python looks for <code>.__iter__()</code> to check whether it can iterate over the object and how.</p><p>Do you want to fetch an individual item from the object? If this makes sense for this object, then it will have a <code>.__getitem__()</code> special method.</p><p>How should Python interpret an object&#8217;s truthiness? There&#8217;s <code>.__bool__()</code> for that. Or <code>.__len__()</code>!</p><p>Ah, you&#8217;d like to add an object to another object. Does your object have a <code>.__add__()</code> special method?</p><p>I could go on. I&#8217;ll post links to articles that cover some of these special methods in more detail below.</p><p>I&#8217;m also running a <a href="https://thepythoncodingstack.substack.com/p/when-it-works-is-not-good-enough">two-hour workshop this Thursday, 26 February, called </a><em><a href="https://thepythoncodingstack.substack.com/p/when-it-works-is-not-good-enough">Python&#8217;s Plumbing &#8226; Dunder Methods and Python&#8217;s Hidden Interface</a></em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thepythoncodingstack.substack.com/p/when-it-works-is-not-good-enough&quot;,&quot;text&quot;:&quot;Book Workshops&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thepythoncodingstack.substack.com/p/when-it-works-is-not-good-enough"><span>Book Workshops</span></a></p><p>Many operations you take for granted in your code are governed by special methods. Each class defines the special methods it needs, and Python knows how to handle instances of that class through those methods.</p><p>But let&#8217;s talk about different ways we refer to these special methods.</p><h2><strong>What&#8217;s In A Name?</strong></h2><p>These methods are called <em>special</em> methods. That&#8217;s their official name. These special methods have double underscores at the beginning and end of their names, such as <code>.__init__()</code>, <code>.__str__()</code>, and <code>.__iter__()</code>. This double-underscore notation led to the informal name &#8220;dunder methods&#8221;. And let&#8217;s face it, most people call them &#8220;dunder methods&#8221; instead of their actual name: &#8220;special methods.&#8221;</p><p>I often call them dunder methods, too. However, the term <em>dunder</em> merely describes the syntax, <em>d</em>ouble <em>under</em>score, so it doesn&#8217;t tell us much about what they do. The term <em>special</em> doesn&#8217;t tell us what they do, either, but it shows us they have a special role in Python.</p><h2><strong>There&#8217;s No Such Thing as Magic</strong></h2><p>Some people also call them <em>magic</em> methods. However, I avoid this term, and I discourage students from using it. It makes these methods look unnecessarily mysterious, perhaps difficult to understand because it&#8217;s all down to <em>magic</em>.</p><p>But there&#8217;s no such thing as magic (unless you&#8217;re Harry Potter). And the magic tricks we see from real-world &#8220;magicians&#8221; are just that &#8211; tricks. The magic dissolves away once you know how the trick works.</p><p>And if you&#8217;re learning Python, then you need to learn how to be a magician. You need to learn the &#8220;magic tricks.&#8221; Therefore, they&#8217;re no longer magic!</p><h2><strong>Python&#8217;s Plumbing (&#8221;Plumbing Methods&#8221;, Anyone?)</strong></h2><p>So, &#8220;special method&#8221; tells us that these methods are important, but it doesn&#8217;t tell us what they do. &#8220;Dunder method&#8221; describes the syntax. &#8220;Magic method&#8221; misleads us and doesn&#8217;t provide any useful insight.</p><p>How about &#8220;plumbing methods&#8221; then? Now, before anyone takes me too seriously, I&#8217;m saying this with my tongue firmly in my cheek. I&#8217;m not that foolish to suggest a new term for the whole Python community to adopt. And it&#8217;s not as flashy as &#8220;magic methods&#8221; or as cool as &#8220;dunder methods&#8221;. But bear with me&#8230;</p><p>Let&#8217;s explore the analogy, even if the term won&#8217;t catch on.</p><p><em>Disclaimer: I know very little about plumbing. But I think that&#8217;s OK for this essay!</em></p><p>There are pipes, valves, and other stuff carrying water (clean or otherwise) around your house. You know they&#8217;re there. You need them there. But you don&#8217;t see them.</p><p>You don&#8217;t think about these pipes unless you&#8217;re building the house &#8211; or unless the pipes are blocked or leaking.</p><p>The house&#8217;s plumbing keeps things running smoothly. Yet, it&#8217;s out of sight, and you don&#8217;t normally think about it. You take it for granted.</p><p>You see where I&#8217;m going, right?</p><p>Python&#8217;s special methods perform the same role. You don&#8217;t normally see them when coding since they&#8217;re called implicitly, behind the scenes. You do need to define the special methods you need when you&#8217;re defining the class, just like you&#8217;ll need to lay the pipes when building or modifying your house.</p><p>And if something goes wrong in your code, you may need to dive into how these dunder methods behave, just as when you have a leak and need to explore which pipe is responsible.</p><p>Good plumbing is reliable, predictable. Bad plumbing is asking for trouble. The same applies to the infrastructure you create through the special methods you define in classes.</p><p>So, there you go, they&#8217;re &#8220;plumbing methods&#8221;. This name tells us what they do!</p><div><hr></div><p>I&#8217;m running a <strong>two-hour live workshop this Thursday called </strong><em><strong><a href="https://thepythoncodingstack.substack.com/p/when-it-works-is-not-good-enough">Python&#8217;s Plumbing &#8226; Dunder Methods and Python&#8217;s Hidden Interface</a></strong></em><strong>.</strong> This is your last chance to join and I may not run this workshop again for a while.</p><p>This workshop is the first of three in the <em>Python Behind the Scenes</em> series. The other two workshops in the series are:</p><ul><li><p>#2 &#8226; <strong>Pythonic Iteration:</strong> Iterables, Iterators, <code>itertools</code></p></li><li><p>#3 &#8226; <strong>To Inherit or Not?</strong> Inheritance, Composition, Abstract Base Classes, and Protocols</p></li></ul><p>Join all three, or pick and choose:</p><div class="embedded-post-wrap" data-attrs="{&quot;id&quot;:188398348,&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/p/when-it-works-is-not-good-enough&quot;,&quot;publication_id&quot;:1563052,&quot;embedding_publication_id&quot;:null,&quot;publication_name&quot;:&quot;The Python Coding Stack&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!Dn3k!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab4a59e8-e362-456b-8427-934e87c31a0d_600x600.png&quot;,&quot;title&quot;:&quot;When \&quot;It Works\&quot; Is Not Good Enough &#8226; Live Workshops&quot;,&quot;truncated_body_text&quot;:&quot;You&#8217;ve been reading articles here on The Python Coding Stack. How about live workshops?&quot;,&quot;date&quot;:&quot;2026-02-18T17:13:03.909Z&quot;,&quot;like_count&quot;:1,&quot;comment_count&quot;:2,&quot;bylines&quot;:[{&quot;id&quot;:120170782,&quot;name&quot;:&quot;Stephen Gruppetta&quot;,&quot;handle&quot;:&quot;stephengruppetta&quot;,&quot;previous_name&quot;:null,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ca736a83-f5a1-4563-ac6c-c09a9e6fa351_800x800.png&quot;,&quot;bio&quot;:&quot;Constantly looking for simple ways to explain complex things in Python &#8226; You'll find Python and narrative technical writing stuff here&#8230; stephengruppetta.com&quot;,&quot;profile_set_up_at&quot;:&quot;2023-04-08T06:55:32.227Z&quot;,&quot;reader_installed_at&quot;:&quot;2023-04-08T20:05:07.058Z&quot;,&quot;publicationUsers&quot;:[{&quot;id&quot;:1532734,&quot;user_id&quot;:120170782,&quot;publication_id&quot;:1563052,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:true,&quot;publication&quot;:{&quot;id&quot;:1563052,&quot;name&quot;:&quot;The Python Coding Stack&quot;,&quot;subdomain&quot;:&quot;thepythoncodingstack&quot;,&quot;custom_domain&quot;:&quot;www.thepythoncodingstack.com&quot;,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;I write the articles I wish I had when I was learning Python programming\n\nI learn through narratives, stories. And I communicate in the same way, with a friendly and relaxed tone, clear and accessible&quot;,&quot;logo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ab4a59e8-e362-456b-8427-934e87c31a0d_600x600.png&quot;,&quot;author_id&quot;:120170782,&quot;primary_user_id&quot;:120170782,&quot;theme_var_background_pop&quot;:&quot;#D10000&quot;,&quot;created_at&quot;:&quot;2023-04-08T06:55:58.228Z&quot;,&quot;email_from_name&quot;:&quot;Stephen Gruppetta from The Python Coding Stack&quot;,&quot;copyright&quot;:&quot;Stephen Gruppetta&quot;,&quot;founding_plan_name&quot;:&quot;Supporting Member&quot;,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;enabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;magaziney&quot;,&quot;is_personal_mode&quot;:false}},{&quot;id&quot;:1721978,&quot;user_id&quot;:120170782,&quot;publication_id&quot;:1741371,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:false,&quot;publication&quot;:{&quot;id&quot;:1741371,&quot;name&quot;:&quot;Breaking the Rules&quot;,&quot;subdomain&quot;:&quot;breakingtherules&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;A story about telling stories in technical writing.\n\nThis substack is about my journey exploring Narrative Technical Writing.\n\nIt's about breaking the traditional rules and borrowing techniques from storytelling to make compelling technical articles&quot;,&quot;logo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/957ad311-5542-40a5-9501-ade43452a524_280x280.png&quot;,&quot;author_id&quot;:120170782,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF9900&quot;,&quot;created_at&quot;:&quot;2023-06-18T19:22:23.910Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Stephen Gruppetta&quot;,&quot;founding_plan_name&quot;:&quot;Founding Member&quot;,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;magaziney&quot;,&quot;is_personal_mode&quot;:false}},{&quot;id&quot;:5098065,&quot;user_id&quot;:120170782,&quot;publication_id&quot;:4997978,&quot;role&quot;:&quot;admin&quot;,&quot;public&quot;:true,&quot;is_primary&quot;:false,&quot;publication&quot;:{&quot;id&quot;:4997978,&quot;name&quot;:&quot;Back on the Track&quot;,&quot;subdomain&quot;:&quot;backonthetrack&quot;,&quot;custom_domain&quot;:null,&quot;custom_domain_optional&quot;:false,&quot;hero_text&quot;:&quot;My journey as I return back to track and field athletics after a 25-year gap&#8230; as a masters athlete (translation: old) and an aspiring coach&quot;,&quot;logo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9cd864f5-2da4-47ae-8d64-51aec2fa1f85_550x550.png&quot;,&quot;author_id&quot;:120170782,&quot;primary_user_id&quot;:null,&quot;theme_var_background_pop&quot;:&quot;#FF6719&quot;,&quot;created_at&quot;:&quot;2025-05-12T17:03:22.009Z&quot;,&quot;email_from_name&quot;:null,&quot;copyright&quot;:&quot;Stephen Gruppetta&quot;,&quot;founding_plan_name&quot;:null,&quot;community_enabled&quot;:true,&quot;invite_only&quot;:false,&quot;payments_state&quot;:&quot;disabled&quot;,&quot;language&quot;:null,&quot;explicit&quot;:false,&quot;homepage_type&quot;:&quot;magaziney&quot;,&quot;is_personal_mode&quot;:false}}],&quot;twitter_screen_name&quot;:&quot;s_gruppetta_ct&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null,&quot;status&quot;:{&quot;bestsellerTier&quot;:null,&quot;subscriberTier&quot;:1,&quot;leaderboard&quot;:null,&quot;vip&quot;:false,&quot;badge&quot;:{&quot;type&quot;:&quot;subscriber&quot;,&quot;tier&quot;:1,&quot;accent_colors&quot;:null},&quot;paidPublicationIds&quot;:[1717194],&quot;subscriber&quot;:null}}],&quot;utm_campaign&quot;:null,&quot;belowTheFold&quot;:true,&quot;type&quot;:&quot;newsletter&quot;,&quot;language&quot;:&quot;en&quot;,&quot;source&quot;:null}" data-component-name="EmbeddedPostToDOM"><a class="embedded-post" native="true" href="https://www.thepythoncodingstack.com/p/when-it-works-is-not-good-enough?utm_source=substack&amp;utm_campaign=post_embed&amp;utm_medium=web"><div class="embedded-post-header"><img class="embedded-post-publication-logo" src="https://substackcdn.com/image/fetch/$s_!Dn3k!,w_56,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fab4a59e8-e362-456b-8427-934e87c31a0d_600x600.png" loading="lazy"><span class="embedded-post-publication-name">The Python Coding Stack</span></div><div class="embedded-post-title-wrapper"><div class="embedded-post-title">When "It Works" Is Not Good Enough &#8226; Live Workshops</div></div><div class="embedded-post-body">You&#8217;ve been reading articles here on The Python Coding Stack. How about live workshops&#8230;</div><div class="embedded-post-cta-wrapper"><span class="embedded-post-cta">Read more</span></div><div class="embedded-post-meta">8 months ago &#183; 1 like &#183; 2 comments &#183; Stephen Gruppetta</div></a></div><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thepythoncodingstack.substack.com/p/when-it-works-is-not-good-enough&quot;,&quot;text&quot;:&quot;Book Workshops&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thepythoncodingstack.substack.com/p/when-it-works-is-not-good-enough"><span>Book Workshops</span></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_!gOVQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!gOVQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg 424w, https://substackcdn.com/image/fetch/$s_!gOVQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg 848w, https://substackcdn.com/image/fetch/$s_!gOVQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!gOVQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!gOVQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg" width="628" height="451.59065934065933" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1047,&quot;width&quot;:1456,&quot;resizeWidth&quot;:628,&quot;bytes&quot;:684833,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.thepythoncodingstack.com/i/189015669?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.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_!gOVQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg 424w, https://substackcdn.com/image/fetch/$s_!gOVQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg 848w, https://substackcdn.com/image/fetch/$s_!gOVQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!gOVQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc71567a3-256a-421f-9c79-eb68b4703ed7_1920x1380.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em>Image by <a href="https://pixabay.com/users/thedigitalartist-202249/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=8012885">Pete Linforth</a> from <a href="https://pixabay.com//?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=8012885">Pixabay</a></em></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com?utm_source=the-python-coding-stack">stephengruppetta.com</a></em></p><p>Further reading related to this article&#8217;s topic:</p><ul><li><p><em>This is part of a longer OOP series:</em> <a href="https://www.thepythoncodingstack.com/p/python-oop-special-methods-6">Time for Something Special &#8226; Special Methods in Python Classes</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/the-anatomy-of-a-for-loop">The Anatomy of a for Loop</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/python-getitem-special-method-library-manorhouse">The Manor House, the Oak-Panelled Library, the Vending Machine, and Python&#8217;s __getitem__()  [Part 1]</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/and-now-for-something-new-python-special-method">And Now for Something New</a></p></li><li><p><a href="https://thepythoncodingstack.substack.com/p/arithmetic-special-methods-python">Why Do 5 + &#8220;5&#8221; and &#8220;5&#8221; + 5 Give Different Errors in Python? &#8226; Do You Know The Whole Story?</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/my-life-the-autobiography-of-a-python-object">My Life &#8226; The Autobiography of a Python Object</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/telling-the-truthy-python-truthiness-falsiness">Telling The Truthy</a></p></li></ul>]]></content:encoded></item><item><title><![CDATA[The Journey From LBYL to EAFP]]></title><description><![CDATA[When it&#8217;s OK to just go for it and see what happens]]></description><link>https://www.thepythoncodingstack.com/p/the-journey-from-lbyl-to-eafp</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/the-journey-from-lbyl-to-eafp</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Thu, 19 Feb 2026 22:26:35 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/8c79170f-29bd-411d-9b29-14960988ca33_840x600.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>LBYL came more naturally to me in my early years of programming. It seemed to have fewer obstacles in those early stages, fewer tricky concepts.</p><p>And in my 10+ years of teaching Python, I also preferred teaching LBYL to beginners and delaying EAFP until later.</p><p>But over the years, as I came to understand Python&#8217;s psyche better, I gradually shifted my programming style&#8212;and then, my teaching style, too.</p><p>So, what are LBYL and EAFP? And which one is more suited to Python?</p><div class="pullquote"><p><em>I&#8217;m running a series of three live workshops starting this week.<br>Each workshop is 2 hours long, so plenty to time to explore core Python topics:</em></p><p><em>#1 &#8226; Python&#8217;s Plumbing: Dunder Methods and Python&#8217;s Hidden Interface<br>#2 &#8226; Pythonic Iteration: Iterables, Iterators, </em><code>itertools<br></code><em>#3 &#8226; To Inherit or Not? Inheritance, Composition, Abstract Base Classes, and Protocols</em></p><p><em>Read more and book your place here:<br><a href="https://www.thepythoncodingstack.com/p/when-it-works-is-not-good-enough">https://www.thepythoncodingstack.com/p/when-it-works-is-not-good-enough</a></em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/p/when-it-works-is-not-good-enough&quot;,&quot;text&quot;:&quot;Book Workshops&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/p/when-it-works-is-not-good-enough"><span>Book Workshops</span></a></p></div><h2><strong>Look Both Sides Before Crossing the Road</strong></h2><p>You should definitely look before you leap across a busy road&#8230;or any road, really. And programming also has a <em>Look Before You Leap</em> concept&#8212;that&#8217;s LBYL&#8212;when handling potential failure points in your code.</p><p>Let&#8217;s start by considering this basic example. You define a function that accepts a value and a list. The function adds the value to the list if the value is above a user-supplied threshold:</p><pre><code>def add_value_above_threshold(value, threshold, data):
    if value &gt;= threshold:
        data.append(value)</code></pre><p>You can confirm this short code works as intended:</p><pre><code># ...
prices = []
add_value_above_threshold(12, 5, prices)
add_value_above_threshold(3, 5, prices)
add_value_above_threshold(9, 5, prices)
print(prices)</code></pre><p>This code outputs the list with the two prices above the threshold:</p><pre><code>[12, 9]</code></pre><p>However, you want to ensure this can&#8217;t happen:</p><pre><code># ...
products = {}
add_value_above_threshold(12, 5, products)</code></pre><p>Now, <code>products</code> is a dictionary, but <code>add_value_above_threshold()</code> was designed to work with lists and not dictionaries:</p><pre><code>Traceback (most recent call last):
  ...
    add_value_above_threshold(12, 5, products)
    ~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
  ...
    data.append(value)
    ^^^^^^^^^^^
AttributeError: &#8216;dict&#8217; object has no attribute &#8216;append&#8217;</code></pre><p>One option is the look before you leap (LBYL):</p><pre><code>def add_value_above_threshold(value, threshold, data):
    if not isinstance(data, list):
        print(&#8221;Invalid format. &#8216;data&#8217; must be a list&#8221;)
        return
    if value &gt;= threshold:
        data.append(value)</code></pre><p>Now, the function prints a warning when you pass a dictionary, and it doesn&#8217;t crash the program!</p><p>But this is too restrictive.</p><p>Let&#8217;s assume you decide to use a <a href="https://www.thepythoncodingstack.com/p/clearing-the-deque-python-linked-list">deque</a> instead of a list:</p><pre><code>from collections import deque
&#8203;
# ...
&#8203;
prices = deque()
add_value_above_threshold(12, 5, prices)
add_value_above_threshold(3, 5, prices)
add_value_above_threshold(9, 5, prices)
print(prices)</code></pre><p>This code still complains that it wants a list and doesn&#8217;t play ball:</p><pre><code>Invalid format. &#8216;data&#8217; must be a list
Invalid format. &#8216;data&#8217; must be a list
Invalid format. &#8216;data&#8217; must be a list
deque([])</code></pre><p>But there&#8217;s no reason why this code shouldn&#8217;t work since <code>deque</code> also has an <code>.append()</code> method.</p><p>You could change the call to <code>isinstance()</code> to include the <code>deque</code> data type&#8212;<code>isinstance(data, list | deque)</code>&#8212;but then there may be other data structures that are valid and can be used in this function. You don&#8217;t want to have to write them all.</p><p>If you&#8217;re well-versed with the categories of data structures&#8212;perhaps because you devoured the <a href="https://www.thepythoncodingstack.com/p/the-main-data-structure-categories">The Python Data Structure Categories Series</a>&#8212;then you might conclude you need to check whether the object is a <code>MutableSequence</code> since all mutable sequences have an <code>.append()</code> method. You can import <code>MutableSequence</code> from <code>collections.abc</code> and use <code>isinstance(data, MutableSequence)</code>. Now you&#8217;re fine to use lists, deques, or any other mutable sequence.</p><p>This version fits better with Python&#8217;s duck-typing philosophy. It doesn&#8217;t restrict the function to a limited number of data types but to a category of data types. This category is defined by what the data types can do. In duck typing, you care about what an object <em>can do</em> rather than what <em>it is.</em> You can read more about duck typing in Python in this post: <a href="https://www.thepythoncodingstack.com/p/python-duck-typing-functions-classes-callables">When a Duck Calls Out &#8226; On Duck Typing and Callables in Python</a></p><p>However, you could still have other data types that have an <code>.append()</code> method but may not fully fit into the <code>MutableSequence</code> category. There&#8217;s no reason you should exclude those data types from working with your function.</p><p>Perhaps, you could use Python&#8217;s built-in <code>hasattr()</code> to check whether the object you pass has an <code>.append()</code> attribute. You&#8217;re now checking whether the object has the required attribute rather than what the object is.</p><p>But if you&#8217;re going through all this trouble, you can go a step further.</p><h2><strong>Just Go For It and See What Happens</strong></h2><p>Why not just run the line of code that includes <code>data.append()</code> and see what happens? Ah, but you don&#8217;t want the code to fail if you use the wrong data type&#8212;you only want to print a warning, say.</p><p>That&#8217;s where the <code>try..except</code> construct comes in:</p><pre><code>def add_value_above_threshold(value, threshold, data):
    if value &lt; threshold:  # inequality flipped to avoid nesting
        return
    try:
        data.append(value)
    except AttributeError:
        print(
            &#8220;Provided data structure does not support appending values.&#8221;
        )</code></pre><p>This is the <em>Easier to Ask for Forgiveness than Permission</em> (EAFP) philosophy. Just try the code. If it doesn&#8217;t work, you can then deal with it in the <code>except</code> block. Now, this fits even more nicely with Python&#8217;s duck typing philosophy. You&#8217;re asking the program whether <code>data</code> can append a value. It doesn&#8217;t matter what <code>data</code> is&#8211;can it append a value?</p><p>You don&#8217;t have to think about all the valid data types or which category they fall into. And rather than checking whether the data type has the <code>.append()</code> attribute first, you just try to run the code and deal with the consequences later. That&#8217;s why it&#8217;s easier to ask for forgiveness than permission.</p><p>But don&#8217;t use this philosophy when crossing a busy road. Stick with &#8220;look before you leap&#8221; there!</p><h2><strong>Another Example Comparing LBYL and EAFP</strong></h2>
      <p>
          <a href="https://www.thepythoncodingstack.com/p/the-journey-from-lbyl-to-eafp">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[What’s The Point of `itemgetter()` in Python?]]></title><description><![CDATA[You&#8217;ve come across `operator.itemgetter()`, but you feel it&#8217;s redundant? Let&#8217;s explore]]></description><link>https://www.thepythoncodingstack.com/p/whats-the-point-of-itemgetter-in-python</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/whats-the-point-of-itemgetter-in-python</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Sat, 07 Feb 2026 22:35:09 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/45a996f6-13fe-4334-b7b3-717bbb6f4cda_840x600.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The first time I saw <code>itemgetter()</code>, I did what I&#8217;d normally do when I come across a new tool. I looked up the docs, opened a REPL, and explored a bit.</p><p>And my reaction at first was: &#8220;So what?! This tool doesn&#8217;t do anything I couldn&#8217;t already do with other features in Python.&#8221;</p><p>So, why does <code>itemgetter()</code> exist?</p><p>But, before answering this question, let&#8217;s answer a more basic one&#8230;</p><h2><strong>What Does </strong><code>itemgetter()</code><strong> Do?</strong></h2>
      <p>
          <a href="https://www.thepythoncodingstack.com/p/whats-the-point-of-itemgetter-in-python">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Planning Meals, Weekly Shop, Alternative Constructors Using Class Methods]]></title><description><![CDATA[You can have more than one way of creating objects &#8226; alternative constructors using class methods]]></description><link>https://www.thepythoncodingstack.com/p/python-alternative-constructor-class-method</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/python-alternative-constructor-class-method</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Fri, 30 Jan 2026 14:18:49 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!mIQt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I&#8217;m sure we&#8217;re not the only family with this problem: deciding what meals to cook throughout the week. There seems to be just one dish that everyone loves, but we can hardly eat the same dish every day.</p><p>So we came up with a system, and I&#8217;m writing a Python program to implement it. We keep a list of meals we try out. Each family member assigns a score to each meal. Every Saturday, before we go to the supermarket for the weekly shop, we plan which meals we&#8217;ll cook on each day of the week. It&#8217;s not based solely on the preference ratings, of course, since my wife and I have the final say to ensure a good balance. Finally, the program provides us with the shopping list with the ingredients we need for all the week&#8217;s meals.</p><p>I know, we&#8217;ve reinvented the wheel. There are countless apps that do this. But the fun is in writing your own code to do <em>exactly</em> what you want.</p><p>I want to keep this article focussed on just one thing: alternative constructors using class methods. Therefore, I won&#8217;t go through the whole code in this post. Perhaps I&#8217;ll write about the full project in a future article.</p><p>So, here&#8217;s what you need to know to get our discussion started.</p><div class="pullquote"><p><em>Do you learn best from one-to-one sessions? The Python Coding Place offers one-to-one lessons on Zoom. Try them out, we bet you&#8217;ll love them. <a href="https://thepythoncodingplace.com/live-one-to-one-sessions?utm_source=the-python-coding-stack">Find out more about one-to-one private sessions.</a></em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thepythoncodingplace.com/live-one-to-one-sessions?utm_source=the-python-coding-stack&quot;,&quot;text&quot;:&quot;One-to-one Python sessions&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thepythoncodingplace.com/live-one-to-one-sessions?utm_source=the-python-coding-stack"><span>One-to-one Python sessions</span></a></p></div><h2><strong>Setting the Scene &#8226; Outlining the </strong><code>Meal</code><strong> and </strong><code>WeeklyMealPlanner</code><strong> Classes</strong></h2><p>Let me outline two of the classes in my code. The first is the <code>Meal</code> class. This class &#8211; you guessed it &#8211; deals with each meal. Here&#8217;s the class&#8217;s <code>.__init__()</code> method:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!zIoB!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!zIoB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.png 424w, https://substackcdn.com/image/fetch/$s_!zIoB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.png 848w, https://substackcdn.com/image/fetch/$s_!zIoB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.png 1272w, https://substackcdn.com/image/fetch/$s_!zIoB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!zIoB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.png" width="1200" height="714" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:714,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:65679,&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://www.thepythoncodingstack.com/i/186306815?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.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_!zIoB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.png 424w, https://substackcdn.com/image/fetch/$s_!zIoB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.png 848w, https://substackcdn.com/image/fetch/$s_!zIoB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.png 1272w, https://substackcdn.com/image/fetch/$s_!zIoB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F075e74fe-260e-4654-8ff2-e5fe7d303e68_1200x714.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">All code blocks are available in text format at the end of this article &#8226; #1</figcaption></figure></div><p>The meal has a name so we can easily refer to it, so there&#8217;s a <code>.name</code> data attribute. And the meals I cook are different from the meals my wife cooks, which is why there&#8217;s a <code>.person_cooking</code> data attribute. This matters as on some days of the week, only one of us is available to prepare dinner, so this attribute becomes relevant!</p><p>There are also days when we have busy afternoons and evenings with children&#8217;s activities, so we need to cook a quick meal. The <code>.quick_meal</code> data attribute is a Boolean flag to help with planning for these hectic days.</p><p>Then there&#8217;s the <code>.ingredients</code> data attribute. You don&#8217;t need me to explain this one. And since each family member rates each meal, there&#8217;s a <code>.ratings</code> dictionary to keep track of the scores.</p><p>The class has more methods, such as <code>add_ingredient()</code>, <code>remove_ingredient()</code>, <code>add_rating()</code>, and more. There&#8217;s also code to save to and load from CSV and JSON files. But these are not necessary for today&#8217;s article, so I&#8217;ll leave them out.</p><p>There&#8217;s also a <code>WeeklyMealPlanner</code> class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ojMZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ojMZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!ojMZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!ojMZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!ojMZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ojMZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png" width="1200" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:43690,&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://www.thepythoncodingstack.com/i/186306815?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.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_!ojMZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!ojMZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!ojMZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!ojMZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3f34bd48-49ff-4b76-8fa7-15bf24f388a5_1200x504.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#2</figcaption></figure></div><p>The <code>._meals</code> data attribute is a dictionary with the days of the week as keys and <code>Meal</code> instances as values. It&#8217;s defined as a non-public attribute to be used with the read-only <a href="https://thepythoncodingstack.substack.com/p/the-properties-of-python-property">property</a> <code>.meals</code>. The <code>.meals</code> property returns a shallow copy of the <code>._meals</code> dictionary. This makes it safer as it&#8217;s harder for a user to make changes directly to this dictionary. The dictionary is modified only through methods within <code>WeeklyMealPlanner</code>. I&#8217;ve omitted the rest of the methods in this class as they&#8217;re not needed for this article.</p><p>You can read more about properties in Python in this article: <a href="https://thepythoncodingstack.substack.com/p/the-properties-of-python-property">The Properties of Python&#8217;s &#8216;property&#8217;</a></p><p>So, each time we try a new dish, we create a <code>Meal</code> object, and each family member rates it. This meal then goes into our collection of meals to choose from each week. On Saturday, we choose the meals we want for the week, put them in a <code>WeeklyMealPlanner</code> instance, and we&#8217;re almost ready to go&#8230;</p><h2><strong>At the Supermarket</strong></h2><p>Well, we&#8217;re almost ready to go to the supermarket at this point. So, here&#8217;s another class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!dQ8F!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dQ8F!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png 424w, https://substackcdn.com/image/fetch/$s_!dQ8F!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png 848w, https://substackcdn.com/image/fetch/$s_!dQ8F!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png 1272w, https://substackcdn.com/image/fetch/$s_!dQ8F!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!dQ8F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png" width="1200" height="588" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:588,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:63204,&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://www.thepythoncodingstack.com/i/186306815?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.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_!dQ8F!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png 424w, https://substackcdn.com/image/fetch/$s_!dQ8F!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png 848w, https://substackcdn.com/image/fetch/$s_!dQ8F!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png 1272w, https://substackcdn.com/image/fetch/$s_!dQ8F!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F81589523-7082-4df7-a710-f14c5fd1041e_1200x588.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#3</figcaption></figure></div><p>A <code>ShoppingList</code> object has an <code>.ingredients</code> data attribute. This attribute is a dictionary. The keys are the ingredients, and the values are the quantities needed for each ingredient. I&#8217;m also showing the <code>.add_ingredient()</code> method, which I&#8217;ll need later on. So, you can create an instance of <code>ShoppingList</code> in the usual way:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8jdP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!8jdP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!8jdP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!8jdP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!8jdP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:7105,&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://www.thepythoncodingstack.com/i/186306815?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.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_!8jdP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!8jdP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!8jdP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!8jdP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5b557792-97b7-453f-a039-f1e9dbbc00e1_1200x168.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#4</figcaption></figure></div><p>Then, you can add ingredients as needed. But this is annoying for us on a Saturday. Here&#8217;s why&#8230;</p><div><hr></div><p><em>Do you want to master Python one article at a time? Then don&#8217;t miss out on the article in The Club which are exclusive to premium subscribers here on The Python Coding Stack</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><div><hr></div><h2><strong>Alternative Constructor</strong></h2><p>Before describing our Saturday problems, let&#8217;s briefly revisit what happens when you create an instance of a class. When you place parentheses after the class name, Python does two things: it creates a blank new object, and it initialises it. The creation of the new object almost always happens &#8220;behind the scenes&#8221;. The <code>.__new__()</code> method creates a new object, but you rarely need to override it. And the <code>.__init__()</code> method performs the object&#8217;s initialisation.</p><p>You can only have one <code>.__init__()</code> special method in a class. Does this mean there&#8217;s only one way to create an instance of a class?</p><p>Not quite, no. Although there&#8217;s no way to define more <code>.__init__()</code> methods, there are ways to create instances through different routes. The <code>@singledispatchmethod</code> decorator is a useful tool, but one I&#8217;ll discuss in a future post. Today, I want to talk about using <strong>class methods as alternative constructors</strong>.</p><p>Back to a typical Saturday in our household. We just finished choosing the seven dinners we plan to have this coming week, and we created a <code>WeeklyMealPlanner</code> instance. So we should now create a <code>ShoppingList</code> instance using <code>ShoppingList()</code> and then go through all the meals we chose, entering their ingredients.</p><p>Wouldn&#8217;t it be nice if we could just create a <code>ShoppingList</code> instance directly from the <code>WeeklyMealPlanner</code> instance? But that would require a different way to create an instance of <code>ShoppingList</code>.</p><p>Let&#8217;s define an alternative constructor, then:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Vutw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Vutw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png 424w, https://substackcdn.com/image/fetch/$s_!Vutw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png 848w, https://substackcdn.com/image/fetch/$s_!Vutw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png 1272w, https://substackcdn.com/image/fetch/$s_!Vutw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Vutw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png" width="1272" height="924" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:924,&quot;width&quot;:1272,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:117925,&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://www.thepythoncodingstack.com/i/186306815?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.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_!Vutw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png 424w, https://substackcdn.com/image/fetch/$s_!Vutw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png 848w, https://substackcdn.com/image/fetch/$s_!Vutw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png 1272w, https://substackcdn.com/image/fetch/$s_!Vutw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F72ce41a4-8120-420c-aa68-0f50eceb9bbf_1272x924.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#5</figcaption></figure></div><p>There&#8217;s a new method called <code>.from_meal_planner()</code>. However, this is not an instance method. It doesn&#8217;t belong to an instance of the class. Instead, it belongs to the class directly. The <code>@classmethod</code> decorator tells Python to treat this method as a <em>class method</em>. Note that the first parameter in this method is <em>not</em> <code>self</code>, as with the usual (instance) methods. Instead, you use <code>cls</code>, which is the parameter name used by convention to refer to the class.</p><p>Whereas <code>self</code> in an instance method represents the instance of a class, <code>cls</code> represents the class directly. So, unlike instance methods, class methods don&#8217;t have access to the instance. Therefore, class methods don&#8217;t have access to instance attributes.</p><p>The first line of this method creates an instance of the class. Look at the expression <code>cls()</code>, which comes after the <code>=</code> operator. Recall that <code>cls</code> refers to the class. So, <code>cls</code> is the same as <code>ShoppingList</code> in this example. But adding parentheses after the class creates an instance. You assign this new instance to the local variable <code>shopping_list</code>. You use <code>cls</code> rather than <code>ShoppingList</code> to make the class more robust in case you choose to subclass it later.</p><p>Fast-forward to the end of this class method, and you&#8217;ll see that the method returns this new instance, <code>shopping_list</code>. However, it makes changes to the instance before returning it. The method fetches all the ingredients from each meal in the <code>WeeklyMealPlanner</code> instance and populates the <code>.ingredients</code> data attribute in the new <code>ShoppingList</code> instance.</p><p>In summary, the class method doesn&#8217;t have access to an instance through the <code>self</code> parameter. But since it has access to the class, the method uses the class to <em>create</em> a new instance and initialise it, adding steps to the standard <code>.__init__()</code> method.</p><p>Therefore, this class method creates and returns an instance of <code>ShoppingList</code> with its <code>.ingredients</code> data attribute populated with the ingredients you need for all the meals in the week.</p><p>You now have an alternative way of creating an instance of <code>ShoppingList</code>:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!d8RF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.png 424w, https://substackcdn.com/image/fetch/$s_!d8RF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.png 848w, https://substackcdn.com/image/fetch/$s_!d8RF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.png 1272w, https://substackcdn.com/image/fetch/$s_!d8RF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!d8RF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.png" width="1326" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1326,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:21912,&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://www.thepythoncodingstack.com/i/186306815?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.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_!d8RF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.png 424w, https://substackcdn.com/image/fetch/$s_!d8RF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.png 848w, https://substackcdn.com/image/fetch/$s_!d8RF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.png 1272w, https://substackcdn.com/image/fetch/$s_!d8RF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd510c3f4-9ab5-46d0-876b-42152dac6703_1326x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#6</figcaption></figure></div><p>This class now has two ways to create instances. The standard one using <code>ShoppingList()</code> and the alternative one using <code>ShoppingList.from_meal_planner()</code>. It&#8217;s common for class methods used as alternative constructors to have names starting with <code>from_*</code>.</p><p>You can have as many alternative constructors as you need in a class.</p><p>Question: if it&#8217;s more useful to create a shopping list directly from the weekly meal planner, couldn&#8217;t you implement this logic directly in the <code>.__init__()</code> method? Yes, you could. But this would create a tight coupling between the two classes, <code>ShoppingList</code> and <code>WeeklyMealPlanner</code>. You can no longer use <code>ShoppingList</code> without an instance of <code>WeeklyMealPlanner</code>, and you can no longer easily create a blank <code>ShoppingList</code> instance.</p><p>Creating two constructors gives you the best of both worlds. <code>ShoppingList</code> is still flexible enough so you can use it as a standalone class or in conjunction with other classes in other projects. But you also have access to the alternative constructor <code>ShoppingList.from_meal_planner()</code> when you need it.</p><h2><strong>Alternative Constructors in the Wild</strong></h2><p>You may have already seen and used alternative constructors, perhaps without noticing.</p><p>Let&#8217;s consider dictionaries. The standard constructor is <code>dict()</code> &#8211; the name of the class followed by parentheses. As it happens, you have several options when using <code>dict()</code> &#8211; you can pass a mapping, or an iterable of pairs, or <code>**kwargs</code>. You can read more about these alternatives in this article: <a href="https://thepythoncodingstack.substack.com/p/python-dict-is-more-versatile-than-you-may-think">dict() is More Versatile Than You May Think</a>.</p><p>But there&#8217;s another alternative constructor that doesn&#8217;t use the standard constructor <code>dict()</code> but still creates a dictionary. This is <code>dict.fromkeys()</code>:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sbjC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!sbjC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!sbjC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!sbjC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!sbjC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:23351,&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://www.thepythoncodingstack.com/i/186306815?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.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_!sbjC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!sbjC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!sbjC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!sbjC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff79e158f-08ee-4a04-980d-db3617a80a1f_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#7</figcaption></figure></div><p>You can have a look at <code>help(dict.fromkeys)</code>. You&#8217;ll see the documentation text refer to this method as a <em>class method</em>, just like the <code>ShoppingList.from_meal_planner()</code> class method you defined earlier.</p><p>And if you use the <code>datetime</code> module, you most certainly have used alternative constructors using class methods. The standard constructor when creating a <code>datetime.datetime</code> instance is the following:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4VKB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!4VKB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!4VKB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!4VKB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!4VKB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:20663,&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://www.thepythoncodingstack.com/i/186306815?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.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_!4VKB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!4VKB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!4VKB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!4VKB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5e83a4f3-7482-427c-b372-132d2a0de525_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#8</figcaption></figure></div><p>However, there are several class methods you can use as alternative constructors:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WU7r!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WU7r!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!WU7r!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!WU7r!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!WU7r!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!WU7r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png" width="1200" height="336" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:336,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:32350,&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://www.thepythoncodingstack.com/i/186306815?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.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_!WU7r!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!WU7r!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!WU7r!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!WU7r!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F40a76edf-c2be-4b1c-abf8-d6a8301cb824_1200x336.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#9</figcaption></figure></div><p>Have a look at other <code>datetime.datetime</code> methods starting with <code>from_</code>.</p><div class="pullquote"><p><em>Your call&#8230;</em></p><p><em>The Python Coding Place offers something for everyone:</em></p><p><em>&#8226; a super-personalised one-to-one 6-month mentoring option</em><br><em>$ 4,750</em></p><p><em>&#8226; individual one-to-one sessions</em><br><em>$ 125</em></p><p><em>&#8226; a self-led route with access to 60+ hrs of exceptional video courses and a support forum</em><br><em>$ 400</em></p><p><em><a href="https://thepythoncodingplace.com?utm_source=the-python-coding-stack">Which The Python Coding Place student are you?</a></em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thepythoncodingplace.com?utm_source=the-python-coding-stack&quot;,&quot;text&quot;:&quot;Find Out Now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thepythoncodingplace.com?utm_source=the-python-coding-stack"><span>Find Out Now</span></a></p></div><h2><strong>Final Words</strong></h2><p>Python restricts you to defining only one <code>.__init__()</code> method. But there are still ways for you to create instances of a class through different routes. Class methods are a common way of creating alternative constructors for a class. You call them directly through the class and not through an instance of the class &#8211; <code>ShoppingList.from_meal_planner()</code>. The class method then creates an instance, modifies it as needed, and finally returns the customised instance.</p><p>Now, let me see what&#8217;s on tonight&#8217;s meal planner and, more importantly, whether it&#8217;s my turn to cook.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!mIQt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!mIQt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg 424w, https://substackcdn.com/image/fetch/$s_!mIQt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg 848w, https://substackcdn.com/image/fetch/$s_!mIQt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!mIQt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!mIQt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg" width="558" height="528.2732142857143" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:3181,&quot;width&quot;:3360,&quot;resizeWidth&quot;:558,&quot;bytes&quot;:2389343,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.thepythoncodingstack.com/i/186306815?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93f62cb6-8459-40ae-a12b-53a71b29b2e4_3360x5040.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_!mIQt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg 424w, https://substackcdn.com/image/fetch/$s_!mIQt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg 848w, https://substackcdn.com/image/fetch/$s_!mIQt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!mIQt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F560a54f2-d6fa-44a4-aa89-1eca5d6cea10_3360x3181.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em><a href="https://www.pexels.com/photo/boy-playing-the-piano-with-his-dog-9429183/">Photo by Katya Wolf</a></em></p><div><hr></div><p><em>Code in this article uses Python 3.14</em></p><p><em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify</a>.</em> <em>[Affiliate link]</em></p><p><em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts</a>, videos, a members&#8217; forum, and more.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><p><em>You can also support this publication by making a <a href="https://buy.stripe.com/00g3de2iGdgg4gg7su">one-off contribution of any amount you wish</a>.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://buy.stripe.com/00g3de2iGdgg4gg7su&quot;,&quot;text&quot;:&quot;Support The Python Coding Stack&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://buy.stripe.com/00g3de2iGdgg4gg7su"><span>Support The Python Coding Stack</span></a></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com/">stephengruppetta.com</a></em></p><p>Further reading related to this article&#8217;s topic:</p><ul><li><p><a href="https://thepythoncodingstack.substack.com/p/the-properties-of-python-property">The Properties of Python&#8217;s &#8216;property&#8217;</a></p></li><li><p><a href="https://thepythoncodingstack.substack.com/p/python-dict-is-more-versatile-than-you-may-think">dict() is More Versatile Than You May Think</a></p></li></ul><div><hr></div><h2>Appendix: Code Blocks</h2><h5>Code Block #1</h5><pre><code><code>class Meal:
    def __init__(
            self,
            name,
            person_cooking,
            quick_meal=False,
    ):
        self.name = name
        self.person_cooking = person_cooking
        self.quick_meal = quick_meal
        self.ingredients = {}  # ingredient: quantity
        self.ratings = {}  # person: rating

    # ... more methods
</code></code></pre><h5>Code Block #2</h5><pre><code><code>class WeeklyMealPlanner:
    def __init__(self):
        self._meals = {}  # day: Meal

    @property
    def meals(self):
        return dict(self._meals)

    # ... more methods
</code></code></pre><h5>Code Block #3</h5><pre><code><code>class ShoppingList:
    def __init__(self):
        self.ingredients = {}  # ingredient: quantity

    def add_ingredient(self, ingredient, quantity=1):
        if ingredient in self.ingredients:
            self.ingredients[ingredient] += quantity
        else:
            self.ingredients[ingredient] = quantity
            
    # ... more methods
</code></code></pre><h5>Code Block #4</h5><pre><code><code>ShoppingList()
</code></code></pre><h5>Code Block #5</h5><pre><code><code>class ShoppingList:
    def __init__(self):
        self.ingredients = {}  # ingredient: quantity

    @classmethod
    def from_meal_planner(cls, meal_planner: WeeklyMealPlanner):
        shopping_list = cls()
        for meal in meal_planner.meals.values():
            if meal is None:
                continue
            for ingredient, quantity in meal.ingredients.items():
                shopping_list.add_ingredient(ingredient, quantity)
        return shopping_list

    def add_ingredient(self, ingredient, quantity=1):
        if ingredient in self.ingredients:
            self.ingredients[ingredient] += quantity
        else:
            self.ingredients[ingredient] = quantity
</code></code></pre><h5>Code Block #6</h5><pre><code><code># if my_weekly_planner is an instance of 'WeeklyMealPlanner', then...

shopping_list = ShoppingList.from_meal_planner(my_weekly_planner)
</code></code></pre><h5>Code Block #7</h5><pre><code><code>dict.fromkeys(["James", "Bob", "Mary", "Jane"])
# {'James': None, 'Bob': None, 'Mary': None, 'Jane': None}
</code></code></pre><h5>Code Block #8</h5><pre><code><code>import datetime
datetime.datetime(2026, 1, 30)
# datetime.datetime(2026, 1, 30, 0, 0)
</code></code></pre><h5>Code Block #9</h5><pre><code><code>datetime.datetime.today()
# datetime.datetime(2026, 1, 30, 12, 54, 2, 243976)

datetime.datetime.fromisoformat("2026-01-30")
# datetime.datetime(2026, 1, 30, 0, 0)
</code></code></pre><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com/">stephengruppetta.com</a></em></p>]]></content:encoded></item><item><title><![CDATA[Need a Constant in Python? Enums Can Come in Useful]]></title><description><![CDATA[Python doesn&#8217;t have constants. But it has enums]]></description><link>https://www.thepythoncodingstack.com/p/python-enums-constants</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/python-enums-constants</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Mon, 12 Jan 2026 13:33:18 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!GVLT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Python doesn&#8217;t have constants. You probably learnt this early on when learning Python. Unlike many other programming languages, you can&#8217;t define a constant in Python. All variables are variable!</p><blockquote><p>&#8220;Ah, but there are immutable types.&#8221;</p></blockquote><p>Sure, you can have an object that doesn&#8217;t change throughout its lifetime. But you can&#8217;t have a reference to it that&#8217;s guaranteed not to change. The identifier (variable name) you use to refer to this immutable type can easily switch to refer to something else.</p><blockquote><p>&#8220;How about using all caps for the identifier. Doesn&#8217;t that make it a constant?&#8221;</p></blockquote><p>No, it doesn&#8217;t. That&#8217;s just a convention you use to show your intent as a programmer that an identifier refers to a value that shouldn&#8217;t change. But nothing prevents that value from changing.</p><p>Here&#8217;s an all-uppercase identifier that refers to an immutable object:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!lYU5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7134faa-1a55-4117-ac38-7b97411c1208_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!lYU5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7134faa-1a55-4117-ac38-7b97411c1208_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!lYU5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7134faa-1a55-4117-ac38-7b97411c1208_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!lYU5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7134faa-1a55-4117-ac38-7b97411c1208_1200x168.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!lYU5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7134faa-1a55-4117-ac38-7b97411c1208_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b7134faa-1a55-4117-ac38-7b97411c1208_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:9358,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7134faa-1a55-4117-ac38-7b97411c1208_1200x168.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_!lYU5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7134faa-1a55-4117-ac38-7b97411c1208_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!lYU5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7134faa-1a55-4117-ac38-7b97411c1208_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!lYU5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7134faa-1a55-4117-ac38-7b97411c1208_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!lYU5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb7134faa-1a55-4117-ac38-7b97411c1208_1200x168.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></div><figcaption class="image-caption">All code blocks are available in text format at the end of this article &#8226; #1</figcaption></figure></div><p>The identifier is all caps. The object is a tuple, which is immutable. Recall that you don&#8217;t need parentheses to create a tuple&#8212;the comma is sufficient.</p><p>So, you use an all-uppercase identifier for an immutable object. But that doesn&#8217;t stop you from changing the value of <code>FIXED_LOCATION</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_!ugIe!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ugIe!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!ugIe!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!ugIe!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!ugIe!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ugIe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png" width="1200" height="336" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:336,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:25553,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.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_!ugIe!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png 424w, https://substackcdn.com/image/fetch/$s_!ugIe!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png 848w, https://substackcdn.com/image/fetch/$s_!ugIe!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png 1272w, https://substackcdn.com/image/fetch/$s_!ugIe!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb031b0ea-7931-4073-a9ef-4a2678e95cfd_1200x336.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#2</figcaption></figure></div><p>Neither using an immutable object nor using uppercase identifiers prevents you from changing this value!</p><p>So, Python doesn&#8217;t have constants. But there are tools you can use to mimic constant behaviour depending on the use case you need. In this article I&#8217;ll explore one of these: <strong>Enums</strong>.</p><div><hr></div><p><em>All <a href="https://thepythoncodingplace.com">The Python Coding Place</a> video courses are included in a single, cost-effective bundle. The courses cover beginner and intermediate level courses, and you also get access to a members-only forum.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://thepythoncodingplace.thinkific.com/enroll/2731141&quot;,&quot;text&quot;:&quot;Get The All Courses Bundle&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://thepythoncodingplace.thinkific.com/enroll/2731141"><span>Get The All Courses Bundle</span></a></p><div><hr></div><p><strong>Jargon Corner</strong>: <em>Enum</em> is short for <em>enumeration</em>, and you&#8217;ll see why soon. But don&#8217;t confuse this with the built-in <code>enumerate()</code>, which does something else. See <a href="https://www.thepythoncodingstack.com/p/parkruns-pythons-enumerate-and-zip">Parkruns, Python&#8217;s enumerate and zip, and Why Python Loops Are Different from Other Languages &#8226; </a><em><a href="https://www.thepythoncodingstack.com/p/parkruns-pythons-enumerate-and-zip">[Note: This is a Club post]</a></em> for more on <code>enumerate()</code>.</p><div><hr></div><p>Let&#8217;s revisit our friend Alex from an article from a short while ago: <a href="https://thepythoncodingstack.substack.com/p/python-function-parameters-arguments-args-kwargs-optional-positional-keyword">&#8220;AI Coffee&#8221; Grand Opening This Monday</a>. This article explored the program Alex used in his new coffee shop and how the function signature changed over time to minimise confusion and errors when using it. It&#8217;s a fun article about all the various types and styles of parameters and arguments you can have in Python functions.</p><p>But it didn&#8217;t address another potential source of error when using this code. So let&#8217;s look at a simple version of the <code>brew_coffee()</code> function Alex used to serve his coffee-drinking customers:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!b13l!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!b13l!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!b13l!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!b13l!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!b13l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:22970,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.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_!b13l!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!b13l!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!b13l!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!b13l!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fed43f9f1-f893-4574-9ad4-16335707c70f_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#3</figcaption></figure></div><p>When you call the function, you pass the coffee you want to this function:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-25J!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!-25J!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!-25J!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!-25J!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!-25J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:16158,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.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_!-25J!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!-25J!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!-25J!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!-25J!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5d2c544a-73e3-45ff-b9c6-c55ee9abe9d5_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#4</figcaption></figure></div><p>And elsewhere in the code, these coffees are defined in a dictionary:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!3Hi7!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!3Hi7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png 424w, https://substackcdn.com/image/fetch/$s_!3Hi7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png 848w, https://substackcdn.com/image/fetch/$s_!3Hi7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png 1272w, https://substackcdn.com/image/fetch/$s_!3Hi7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!3Hi7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png" width="1434" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1434,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:80757,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.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_!3Hi7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png 424w, https://substackcdn.com/image/fetch/$s_!3Hi7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png 848w, https://substackcdn.com/image/fetch/$s_!3Hi7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png 1272w, https://substackcdn.com/image/fetch/$s_!3Hi7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F942ece64-6b14-4d42-bad1-4413b2c6eb83_1434x504.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#5</figcaption></figure></div><p>If you&#8217;ve written code like this in the past, you&#8217;ll know that it&#8217;s rather annoying&#8212;and error-prone&#8212;to keep using the strings with the coffee names wherever you need to refer to a specific coffee, such as when passing the coffees to <code>brew_coffee()</code>.</p><p>The names of the coffees and the parameters that define them do not change. They&#8217;re constant. It&#8217;s a shame Python doesn&#8217;t have constants, you may think.</p><p>But it has enums&#8230;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!fXVt!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!fXVt!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png 424w, https://substackcdn.com/image/fetch/$s_!fXVt!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png 848w, https://substackcdn.com/image/fetch/$s_!fXVt!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png 1272w, https://substackcdn.com/image/fetch/$s_!fXVt!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!fXVt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png" width="1200" height="546" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:546,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:34954,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.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_!fXVt!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png 424w, https://substackcdn.com/image/fetch/$s_!fXVt!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png 848w, https://substackcdn.com/image/fetch/$s_!fXVt!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png 1272w, https://substackcdn.com/image/fetch/$s_!fXVt!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e4cb4d5-fe36-4b10-b403-be192d639335_1200x546.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#6</figcaption></figure></div><p>The <code>CoffeeType</code> enum contains seven members. Each member has a name and a value. By convention, you use all-uppercase names for the members since they represent constants. And these enum members behave like constants:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CrFC!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CrFC!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!CrFC!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!CrFC!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!CrFC!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!CrFC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:42204,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.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_!CrFC!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!CrFC!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!CrFC!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!CrFC!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F281644aa-7dab-475d-9451-37fcc90b9a43_1200x630.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#7</figcaption></figure></div><p>When you attempt to reassign a value to a member, Python raises an exception:</p><pre><code>Traceback (most recent call last):
  File ..., line 12, in &lt;module&gt;
    CoffeeType.ESPRESSO = 10
    ^^^^^^^^^^^^^^^^^^^
  ...
AttributeError: cannot reassign member &#8216;ESPRESSO&#8217;</code></pre><p>The member names are also contained within the namespace of the <code>Enum</code> class&#8212;you use <code>CoffeeType.ESPRESSO</code> rather than just <code>ESPRESSO</code> outside the <code>Enum</code> class definition. So, you get autocomplete, refactor-friendly names, and fewer silent typos. With raw strings, <code>"capuccino"</code>  (with a single &#8220;p&#8221;) can sneak into your code, and nothing complains until a customer is already waiting at the counter.</p><p>For these enum members to act as constants, their names must be unique. You can&#8217;t have the same name appear more than once:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Uy35!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Uy35!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png 424w, https://substackcdn.com/image/fetch/$s_!Uy35!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png 848w, https://substackcdn.com/image/fetch/$s_!Uy35!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png 1272w, https://substackcdn.com/image/fetch/$s_!Uy35!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Uy35!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png" width="1200" height="588" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:588,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:38469,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.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_!Uy35!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png 424w, https://substackcdn.com/image/fetch/$s_!Uy35!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png 848w, https://substackcdn.com/image/fetch/$s_!Uy35!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png 1272w, https://substackcdn.com/image/fetch/$s_!Uy35!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7254c309-0745-4a57-8d5c-51665a407f55_1200x588.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#8</figcaption></figure></div><p>You include <code>ESPRESSO</code> twice with different values. But this raises an exception:</p><pre><code>Traceback (most recent call last):
  File ..., line 3, in &lt;module&gt;
    ...
    ESPRESSO = 8
    ^^^^^^^^
  ...
TypeError: &#8216;ESPRESSO&#8217; already defined as 1</code></pre><p>That&#8217;s good news. Otherwise, these enum members wouldn&#8217;t be very useful as constants.</p><p>However, you can have an alias. You can have more than one member sharing the same 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_!4lh8!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4lh8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png 424w, https://substackcdn.com/image/fetch/$s_!4lh8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png 848w, https://substackcdn.com/image/fetch/$s_!4lh8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png 1272w, https://substackcdn.com/image/fetch/$s_!4lh8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!4lh8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png" width="1200" height="588" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:588,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:40139,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.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_!4lh8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png 424w, https://substackcdn.com/image/fetch/$s_!4lh8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png 848w, https://substackcdn.com/image/fetch/$s_!4lh8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png 1272w, https://substackcdn.com/image/fetch/$s_!4lh8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F00aefa8b-ee47-490d-9958-5d20a0c344f6_1200x588.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#9</figcaption></figure></div><p>The members <code>MACCHIATO</code> and <code>ESPRESSO_MACCHIATO</code> both have the value <code>4</code>. Therefore, they represent the same item. They&#8217;re different names for the same coffee:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1m95!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!1m95!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!1m95!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!1m95!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!1m95!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:12054,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.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_!1m95!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!1m95!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!1m95!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!1m95!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F625a260d-4d6b-4fe8-b5a7-6879121c5560_1200x168.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#10</figcaption></figure></div><p>Note that Python always displays the first member associated with a value:</p><pre><code>CoffeeType.MACCHIATO</code></pre><p>The output says <code>CoffeeType.MACCHIATO</code> even though you pass <code>CoffeeType.ESPRESSO_MACCHIATO</code> to <code>print()</code>.</p><p>Incidentally, if you don&#8217;t want to have aliases, you can use the <code>@unique</code> decorator when defining the enum class.</p><div><hr></div><div class="subscription-widget-wrap-editor" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.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"><em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts for premium members</a>, videos, a members&#8217; forum, and more.</em></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>You can also access the name and value of an enum member:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!x5t5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!x5t5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!x5t5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!x5t5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!x5t5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:29226,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.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_!x5t5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!x5t5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!x5t5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!x5t5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F32fd6d46-2d3a-4e5f-8ee1-0afc68a3ae51_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#11</figcaption></figure></div><p>Here&#8217;s the output from this code:</p><pre><code>CoffeeType.ESPRESSO
ESPRESSO
1</code></pre><p>The <code>.name</code> attribute is a string, and the <code>.value</code> attribute is an integer in this case:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rhAx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffa515f-a93e-4bd9-8536-356666930b97_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!rhAx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffa515f-a93e-4bd9-8536-356666930b97_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!rhAx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffa515f-a93e-4bd9-8536-356666930b97_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!rhAx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffa515f-a93e-4bd9-8536-356666930b97_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!rhAx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffa515f-a93e-4bd9-8536-356666930b97_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cffa515f-a93e-4bd9-8536-356666930b97_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:32846,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffa515f-a93e-4bd9-8536-356666930b97_1200x294.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_!rhAx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffa515f-a93e-4bd9-8536-356666930b97_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!rhAx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffa515f-a93e-4bd9-8536-356666930b97_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!rhAx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffa515f-a93e-4bd9-8536-356666930b97_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!rhAx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcffa515f-a93e-4bd9-8536-356666930b97_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#12</figcaption></figure></div><p>Here&#8217;s the output when you display the types:</p><pre><code>&lt;enum &#8216;CoffeeType&#8217;&gt;
&lt;class &#8216;str&#8217;&gt;
&lt;class &#8216;int&#8217;&gt;</code></pre><p>You&#8217;ll often use integers as values for enum members&#8212;that&#8217;s why they&#8217;re called <em>enumerations</em>. But you don&#8217;t have to:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FZdb!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FZdb!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png 424w, https://substackcdn.com/image/fetch/$s_!FZdb!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png 848w, https://substackcdn.com/image/fetch/$s_!FZdb!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png 1272w, https://substackcdn.com/image/fetch/$s_!FZdb!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!FZdb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png" width="1200" height="714" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:714,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:77406,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.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_!FZdb!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png 424w, https://substackcdn.com/image/fetch/$s_!FZdb!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png 848w, https://substackcdn.com/image/fetch/$s_!FZdb!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png 1272w, https://substackcdn.com/image/fetch/$s_!FZdb!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8c35381d-0bed-4306-8301-ca99becfa669_1200x714.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#13</figcaption></figure></div><p>The values are now also strings:</p><pre><code>CoffeeType.ESPRESSO
ESPRESSO
espresso</code></pre><p>You can use these enum members instead of strings wherever you need to refer to each coffee type:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!K2QV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!K2QV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png 424w, https://substackcdn.com/image/fetch/$s_!K2QV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png 848w, https://substackcdn.com/image/fetch/$s_!K2QV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png 1272w, https://substackcdn.com/image/fetch/$s_!K2QV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!K2QV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png" width="1456" height="498" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:498,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:113411,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.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_!K2QV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png 424w, https://substackcdn.com/image/fetch/$s_!K2QV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png 848w, https://substackcdn.com/image/fetch/$s_!K2QV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png 1272w, https://substackcdn.com/image/fetch/$s_!K2QV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3d583c2e-1f9f-4e1c-ad7b-6d753a217bd0_1596x546.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#14</figcaption></figure></div><p>&#8230;and again when you call <code>brew_coffee()</code>:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BBOv!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff77b2333-b990-4014-a482-8dbd6490deca_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!BBOv!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff77b2333-b990-4014-a482-8dbd6490deca_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!BBOv!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff77b2333-b990-4014-a482-8dbd6490deca_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!BBOv!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff77b2333-b990-4014-a482-8dbd6490deca_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!BBOv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff77b2333-b990-4014-a482-8dbd6490deca_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f77b2333-b990-4014-a482-8dbd6490deca_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:11863,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff77b2333-b990-4014-a482-8dbd6490deca_1200x210.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_!BBOv!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff77b2333-b990-4014-a482-8dbd6490deca_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!BBOv!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff77b2333-b990-4014-a482-8dbd6490deca_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!BBOv!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff77b2333-b990-4014-a482-8dbd6490deca_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!BBOv!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff77b2333-b990-4014-a482-8dbd6490deca_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#15</figcaption></figure></div><p>Now you have a safer, neater, and more robust way to handle the coffee types... and treat them as constants.</p><h2><strong>A Bit More &#8226; </strong><code>StrEnum</code><strong> and </strong><code>IntEnum</code></h2><p>Let&#8217;s add some code to <code>brew_coffee()</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_!dz8V!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dz8V!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!dz8V!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!dz8V!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!dz8V!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!dz8V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png" width="1200" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:86076,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.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_!dz8V!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!dz8V!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!dz8V!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!dz8V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcc7e9f5c-8726-4e78-af34-efde650d7ce3_1200x756.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#16</figcaption></figure></div><p>This version is almost fine. But here&#8217;s a small problem:</p><pre><code>Brewing a CoffeeType.CORTADO with 30ml of coffee and 
    60ml of milk. Strength level: 2</code></pre><p>The output displays <code>CoffeeType.CORTADO</code> since <code>coffee_type</code> refers to an enum member. You&#8217;d like the output to just show the name of the coffee! Of course, you can use the <code>.value</code> attribute any time you need to fetch the string.</p><p>However, to make your coding simpler and more readable, you can ensure that the enum members are also strings themselves without having to rely on one of their attributes. You can use <code>StrEnum</code> instead of <code>Enum</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_!TCJa!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!TCJa!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png 424w, https://substackcdn.com/image/fetch/$s_!TCJa!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png 848w, https://substackcdn.com/image/fetch/$s_!TCJa!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png 1272w, https://substackcdn.com/image/fetch/$s_!TCJa!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!TCJa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png" width="1200" height="1218" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1218,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:136957,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.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_!TCJa!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png 424w, https://substackcdn.com/image/fetch/$s_!TCJa!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png 848w, https://substackcdn.com/image/fetch/$s_!TCJa!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png 1272w, https://substackcdn.com/image/fetch/$s_!TCJa!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1cb70ccb-e890-4aed-98d6-c55be9e57147_1200x1218.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#17</figcaption></figure></div><p>Members of a <code>StrEnum</code> also inherit all the string methods, such as:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!BqEx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!BqEx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!BqEx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!BqEx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!BqEx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:11325,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.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_!BqEx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!BqEx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!BqEx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!BqEx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb4fd1486-8d66-478f-b68b-2642e8b3df94_1200x168.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#18</figcaption></figure></div><p>You call the string method <code>.title()</code> directly on the <code>StrEnum</code> member:</p><pre><code>Macchiato</code></pre><p>There&#8217;s also an <code>IntEnum</code> that can be useful when you want your enum members to act as integers. Let&#8217;s replace the coffee strength values, which are currently integers, with <code>IntEnum</code> members:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tFTz!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tFTz!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png 424w, https://substackcdn.com/image/fetch/$s_!tFTz!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png 848w, https://substackcdn.com/image/fetch/$s_!tFTz!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png 1272w, https://substackcdn.com/image/fetch/$s_!tFTz!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!tFTz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png" width="1200" height="1302" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1302,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:116203,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.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_!tFTz!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png 424w, https://substackcdn.com/image/fetch/$s_!tFTz!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png 848w, https://substackcdn.com/image/fetch/$s_!tFTz!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png 1272w, https://substackcdn.com/image/fetch/$s_!tFTz!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1609bcf-0b4d-49fc-a48b-4af4830d0a0d_1200x1302.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#19</figcaption></figure></div><p>You could use a standard <code>Enum</code> in this case. But using an <code>IntEnum</code> allows you to manipulate its members directly as integers should you need to do so. Here&#8217;s an example:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0XN9!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!0XN9!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!0XN9!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!0XN9!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!0XN9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:13563,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.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_!0XN9!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!0XN9!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!0XN9!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!0XN9!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F93b886e5-fe50-4afa-a7ff-5c60c948b818_1200x168.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#20</figcaption></figure></div><p>This code is equivalent to printing <code>3 + 1</code>. You wouldn&#8217;t be able to do this with enums unless you use the <code>.value</code> attributes.</p><h3><strong>And A Couple More Things About Enums</strong></h3><p>Let&#8217;s explore a couple of other useful enum features before we wrap up this article.</p><p>An enum class is iterable. Here are all the coffee types in a <code>for</code> loop:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rZZB!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!rZZB!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!rZZB!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!rZZB!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!rZZB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:13244,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.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_!rZZB!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!rZZB!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!rZZB!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!rZZB!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F09ff2045-c44e-4561-a700-b15e993f0c12_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#21</figcaption></figure></div><p>Note that <code>CoffeeType</code> is the class name. But it&#8217;s an enum (a <code>StrEnum</code> in this case), so it&#8217;s iterable:</p><pre><code>Brewing a espresso with 30ml of coffee and 0ml of milk. Strength level: 3
Brewing a latte with 30ml of coffee and 150ml of milk. Strength level: 1
Brewing a cappuccino with 30ml of coffee and 100ml of milk. Strength level: 2
Brewing a macchiato with 30ml of coffee and 10ml of milk. Strength level: 3
Brewing a flat_white with 30ml of coffee and 120ml of milk. Strength level: 2
Brewing a ristretto with 20ml of coffee and 0ml of milk. Strength level: 4
Brewing a cortado with 30ml of coffee and 60ml of milk. Strength level: 2</code></pre><p>I&#8217;ll let you sort out the text displayed to make sure you get &#8216;<em>an</em> espresso&#8217; when brewing an espresso and to remove the underscore in the flat white!</p><p>And there will be times when you don&#8217;t care about the value of an enum member. You just want to use an enum to give your constants a consistent name. In this case, you can use the automatic value assignment:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1FdV!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1FdV!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!1FdV!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!1FdV!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!1FdV!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!1FdV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png" width="1200" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:43789,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.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_!1FdV!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!1FdV!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!1FdV!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!1FdV!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F405ead1e-65cf-49ae-9eba-a4bd54424be1_1200x504.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#22</figcaption></figure></div><p>Python assigns integers incrementally in the order you define the members for <code>Enum</code> classes. Note that these start from <code>1</code>, not <code>0</code>.</p><p>The same integers are used if you use <code>IntEnum</code> classes. However, when you use <code>StrEnum</code> classes, Python behaves differently since the values should be strings in this case:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ssfu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ssfu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!Ssfu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!Ssfu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!Ssfu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ssfu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png" width="1200" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:49176,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.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_!Ssfu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!Ssfu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!Ssfu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!Ssfu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F94a86e8e-2c3d-46c6-befb-5307f45880c2_1200x504.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#23</figcaption></figure></div><p>The values are now the lowercase strings representing the members&#8217; names.</p><p>Of course, the default values you get when you use <code>auto()</code> may be the values you need, after all. This is the case for both enums you created in this article, <code>CoffeeType</code> and  <code>CoffeeStrength</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_!0ZP-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0ZP-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png 424w, https://substackcdn.com/image/fetch/$s_!0ZP-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png 848w, https://substackcdn.com/image/fetch/$s_!0ZP-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png 1272w, https://substackcdn.com/image/fetch/$s_!0ZP-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!0ZP-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png" width="1200" height="798" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:798,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:77495,&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://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.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_!0ZP-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png 424w, https://substackcdn.com/image/fetch/$s_!0ZP-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png 848w, https://substackcdn.com/image/fetch/$s_!0ZP-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png 1272w, https://substackcdn.com/image/fetch/$s_!0ZP-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70813c6a-e4f3-4c60-b67a-947cd1857036_1200x798.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#24</figcaption></figure></div><p>Using <code>auto()</code> when appropriate makes it easier to write your code and expand it later if you need to add more enum members.</p><h2><strong>Final Words</strong></h2><p>You can get by without ever using enums. But there are many situations where you&#8217;d love to reach for a constant, and an enum will do just fine. Sure, Python doesn&#8217;t have constants. But it has enums!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GVLT!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GVLT!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg 424w, https://substackcdn.com/image/fetch/$s_!GVLT!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg 848w, https://substackcdn.com/image/fetch/$s_!GVLT!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!GVLT!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!GVLT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg" width="584" height="793.7747252747253" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1979,&quot;width&quot;:1456,&quot;resizeWidth&quot;:584,&quot;bytes&quot;:6305403,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.thepythoncodingstack.com/i/184308498?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.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_!GVLT!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg 424w, https://substackcdn.com/image/fetch/$s_!GVLT!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg 848w, https://substackcdn.com/image/fetch/$s_!GVLT!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!GVLT!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc8396ef2-9864-4c82-b6fa-7873b81ea513_5464x7428.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em><a href="https://www.pexels.com/photo/a-coffee-machine-is-displayed-in-a-coffee-shop-27969804/">Photo by Valeria Boltneva</a></em></p><div><hr></div><p><em>Code in this article uses Python 3.14</em></p><p><em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify</a>.</em> <em>[Affiliate link]</em></p><p><em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts</a>, videos, a members&#8217; forum, and more.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><p><em>You can also support this publication by making a <a href="https://buy.stripe.com/00g3de2iGdgg4gg7su">one-off contribution of any amount you wish</a>.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://buy.stripe.com/00g3de2iGdgg4gg7su&quot;,&quot;text&quot;:&quot;Support The Python Coding Stack&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://buy.stripe.com/00g3de2iGdgg4gg7su"><span>Support The Python Coding Stack</span></a></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com/">stephengruppetta.com</a></em></p><div><hr></div><h2>Appendix: Code Blocks</h2><h5>Code Block #1</h5><pre><code><code>FIXED_LOCATION = 51.75, 0.34
</code></code></pre><h5>Code Block #2</h5><pre><code><code>FIXED_LOCATION
# (51.75, 0.34)
FIXED_LOCATION = "Oops!"
FIXED_LOCATION
# 'Oops!'
</code></code></pre><h5>Code Block #3</h5><pre><code><code>def brew_coffee(coffee_type):
    # Actual code goes here...
    # It's not relevant for this article
</code></code></pre><h5>Code Block #4</h5><pre><code><code>brew_coffee("espresso")
brew_coffee("cappuccino")
</code></code></pre><h5>Code Block #5</h5><pre><code><code>coffee_types = {
    "espresso": {"strength": 3, "coffee_amount": 30, "milk_amount": 0},
    "latte": {"strength": 1, "coffee_amount": 30, "milk_amount": 150},
    "cappuccino": {"strength": 2, "coffee_amount": 30, "milk_amount": 100},
    "macchiato": {"strength": 3, "coffee_amount": 30, "milk_amount": 10},
    "flat_white": {"strength": 2, "coffee_amount": 30, "milk_amount": 120},
    "ristretto": {"strength": 4, "coffee_amount": 20, "milk_amount": 0},
    "cortado": {"strength": 2, "coffee_amount": 30, "milk_amount": 60},
}
</code></code></pre><h5>Code Block #6</h5><pre><code><code>from enum import Enum

class CoffeeType(Enum):
    ESPRESSO = 1
    LATTE = 2
    CAPPUCCINO = 3
    MACCHIATO = 4
    FLAT_WHITE = 5
    RISTRETTO = 6
    CORTADO = 7
</code></code></pre><h5>Code Block #7</h5><pre><code><code>from enum import Enum

class CoffeeType(Enum):
    ESPRESSO = 1
    LATTE = 2
    CAPPUCCINO = 3
    MACCHIATO = 4
    FLAT_WHITE = 5
    RISTRETTO = 6
    CORTADO = 7

CoffeeType.ESPRESSO = 10
</code></code></pre><h5>Code Block #8</h5><pre><code><code>from enum import Enum

class CoffeeType(Enum):
    ESPRESSO = 1
    LATTE = 2
    CAPPUCCINO = 3
    MACCHIATO = 4
    FLAT_WHITE = 5
    RISTRETTO = 6
    CORTADO = 7
    ESPRESSO = 8
</code></code></pre><h5>Code Block #9</h5><pre><code><code>from enum import Enum

class CoffeeType(Enum):
    ESPRESSO = 1
    LATTE = 2
    CAPPUCCINO = 3
    MACCHIATO = 4
    FLAT_WHITE = 5
    RISTRETTO = 6
    CORTADO = 7
    ESPRESSO_MACCHIATO = 4
</code></code></pre><h5>Code Block #10</h5><pre><code><code>print(CoffeeType.ESPRESSO_MACCHIATO)
</code></code></pre><h5>Code Block #11</h5><pre><code><code># ...
print(CoffeeType.ESPRESSO)
print(CoffeeType.ESPRESSO.name)
print(CoffeeType.ESPRESSO.value)
</code></code></pre><h5>Code Block #12</h5><pre><code><code># ...
print(type(CoffeeType.ESPRESSO))
print(type(CoffeeType.ESPRESSO.name))
print(type(CoffeeType.ESPRESSO.value))
</code></code></pre><h5>Code Block #13</h5><pre><code><code>from enum import Enum

class CoffeeType(Enum):
    ESPRESSO = "espresso"
    LATTE = "latte"
    CAPPUCCINO = "cappuccino"
    MACCHIATO = "macchiato"
    FLAT_WHITE = "flat_white"
    RISTRETTO = "ristretto"
    CORTADO = "cortado"

print(CoffeeType.ESPRESSO)
print(CoffeeType.ESPRESSO.name)
print(CoffeeType.ESPRESSO.value)
</code></code></pre><h5>Code Block #14</h5><pre><code><code># ...
coffee_types = {
    CoffeeType.ESPRESSO: {"strength": 3, "coffee_amount": 30, "milk_amount": 0},
    CoffeeType.LATTE: {"strength": 1, "coffee_amount": 30, "milk_amount": 150},
    CoffeeType.CAPPUCCINO: {"strength": 2, "coffee_amount": 30, "milk_amount": 100},
    CoffeeType.MACCHIATO: {"strength": 3, "coffee_amount": 30, "milk_amount": 10},
    CoffeeType.FLAT_WHITE: {"strength": 2, "coffee_amount": 30, "milk_amount": 120},
    CoffeeType.RISTRETTO: {"strength": 4, "coffee_amount": 20, "milk_amount": 0},
    CoffeeType.CORTADO: {"strength": 2, "coffee_amount": 30, "milk_amount": 60},
}
</code></code></pre><h5>Code Block #15</h5><pre><code><code># ...
brew_coffee(CoffeeType.CORTADO)
</code></code></pre><h5>Code Block #16</h5><pre><code><code># ...

def brew_coffee(coffee_type):
    coffee_details = coffee_types.get(coffee_type)
    if not coffee_details:
        print("Unknown coffee type!")
        return
    print(
        f"Brewing a {coffee_type} "
        f"with {coffee_details['coffee_amount']}ml of coffee "
        f"and {coffee_details['milk_amount']}ml of milk. "
        f"Strength level: {coffee_details['strength']}"
    )

brew_coffee(CoffeeType.CORTADO)
</code></code></pre><h5>Code Block #17</h5><pre><code><code>from enum import StrEnum

class CoffeeType(StrEnum):
    ESPRESSO = "espresso"
    LATTE = "latte"
    CAPPUCCINO = "cappuccino"
    MACCHIATO = "macchiato"
    FLAT_WHITE = "flat_white"
    RISTRETTO = "ristretto"
    CORTADO = "cortado"

# ...

def brew_coffee(coffee_type):
    coffee_details = coffee_types.get(coffee_type)
    if not coffee_details:
        print("Unknown coffee type!")
        return
    print(
        f"Brewing a {coffee_type} "
        f"with {coffee_details['coffee_amount']}ml of coffee "
        f"and {coffee_details['milk_amount']}ml of milk. "
        f"Strength level: {coffee_details['strength']}"
    )

brew_coffee(CoffeeType.CORTADO)
</code></code></pre><h5>Code Block #18</h5><pre><code><code>print(CoffeeType.MACCHIATO.title())
</code></code></pre><h5>Code Block #19</h5><pre><code><code># ...

class CoffeeStrength(IntEnum):
    WEAK = 1
    MEDIUM = 2
    STRONG = 3
    EXTRA_STRONG = 4

coffee_types = {
    CoffeeType.ESPRESSO: {
      "strength": CoffeeStrength.STRONG, 
      "coffee_amount": 30, 
      "milk_amount": 0,
    },
    CoffeeType.LATTE: {
      "strength": CoffeeStrength.WEAK, 
      "coffee_amount": 30, 
      "milk_amount": 150,
    },
    CoffeeType.CAPPUCCINO: {
      "strength": CoffeeStrength.MEDIUM, 
      "coffee_amount": 30, 
      "milk_amount": 100,
    },
    # ... and so on...
}

# ...
</code></code></pre><h5>Code Block #20</h5><pre><code><code>print(CoffeeStrength.STRONG + CoffeeStrength.WEAK)
</code></code></pre><h5>Code Block #21</h5><pre><code><code># ...

for coffee in CoffeeType:
    brew_coffee(coffee)
</code></code></pre><h5>Code Block #22</h5><pre><code><code>from enum import Enum, auto
class Test(Enum):
    FIRST = auto()
    SECOND = auto()

Test.FIRST
# &lt;Test.FIRST: 1&gt;
Test.SECOND
# &lt;Test.SECOND: 2&gt;
</code></code></pre><h5>Code Block #23</h5><pre><code><code>from enum import StrEnum, auto
class Test(StrEnum):
    FIRST = auto()
    SECOND = auto()
   
Test.FIRST
# &lt;Test.FIRST: 'first'&gt;
Test.SECOND
# &lt;Test.SECOND: 'second'&gt;
</code></code></pre><h5>Code Block #24</h5><pre><code><code># ...
class CoffeeType(StrEnum):
    ESPRESSO = auto()
    LATTE = auto()
    CAPPUCCINO = auto()
    MACCHIATO = auto()
    FLAT_WHITE = auto()
    RISTRETTO = auto()
    CORTADO = auto()

class CoffeeStrength(IntEnum):
    WEAK = auto()
    MEDIUM = auto()
    STRONG = auto()
    EXTRA_STRONG = auto()
# ...
</code></code></pre><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com/">stephengruppetta.com</a></em></p>]]></content:encoded></item><item><title><![CDATA[Parkruns, Python’s enumerate and zip, and Why Python Loops Are Different from Other Languages]]></title><description><![CDATA[Don&#8217;t forget about enumerate() and zip() when coding in Python &#8226; A short post]]></description><link>https://www.thepythoncodingstack.com/p/parkruns-pythons-enumerate-and-zip</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/parkruns-pythons-enumerate-and-zip</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Fri, 09 Jan 2026 13:57:38 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/27fc31b3-78c7-4cf3-8e56-ce6f271540a9_840x600.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If you live in the UK, you&#8217;re probably familiar with the Parkrun tradition: a friendly 5k run held every Saturday morning in hundreds of parks across the UK. Runners range from Olympians to people trying to lose some weight. It&#8217;s a well-oiled format replicated across all <a href="https://www.parkrun.org.uk/events/events/#geo=5.06/54.91/-3.42">893 Parkrun locations</a>.</p><p>And here&#8217;s how they deal with the finish line logistics. Runners don&#8217;t wear bibs with numbers. When they cross the finish line, they enter a &#8220;funnel&#8221; marked by plastic cones and are handed a token with their position number. They then proceed to another official, who scans their personal barcode, which runners carry in their pockets or on a wristband, and the position token they received a few seconds earlier. This process matches the runner with their finishing position.</p><p>What&#8217;s this got to do with Python loops? And how does it help us understand why Python does loops differently from other languages?</p><p>First step, let&#8217;s create the Parkrun funnel. I&#8217;ll just put the first five finishers in this example:</p><pre><code>&gt;&gt;&gt; funnel = [&#8221;Jonathan&#8221;, &#8220;Michael&#8221;, &#8220;Samantha&#8221;, &#8220;Jessica&#8221;, &#8220;Daniel&#8221;]</code></pre><p>Now, here&#8217;s something you definitely know already because it&#8217;s always one of the first things you&#8217;re taught when learning Python: <em><strong>Don&#8217;t</strong></em> loop through this list like this:</p><pre><code># Avoid this when coding in Python
&gt;&gt;&gt; i = 0
&gt;&gt;&gt; while i &lt; len(funnel):
...     name = funnel[i]
...     print(name)
...     i += 1
...    
Jonathan
Michael
Samantha
Jessica
Daniel</code></pre><p>This style mimics how other languages may work: you manually define and increment the index. To be fair, most people who shift from other languages are more likely to write the following version at some point:</p><pre><code># Also best to avoid this in Python
&gt;&gt;&gt; for i in range(len(funnel)):
...     name = funnel[i]
...     print(name)
...    
Jonathan
Michael
Samantha
Jessica
Daniel</code></pre><p>This version may seem more Pythonic since it uses Python tools such as <code>range()</code>, but still fails to make the most of Python&#8217;s iteration protocol. The Pythonic way of looping through this list is the following:</p><pre><code>&gt;&gt;&gt; for name in funnel:
...     print(name)
...    
Jonathan
Michael
Samantha
Jessica
Daniel</code></pre><p>A question that&#8217;s often asked but rarely answered is: Why is this version preferred over the other two? I&#8217;ll write another short post to answer this question soon as I want to keep these <em>The Club</em> posts short whenever possible. So, let me state just a few reasons (there are more) and then I&#8217;ll move on to my main topic for today.</p><ul><li><p>It&#8217;s more readable</p></li><li><p>It&#8217;s more efficient (try timing the versions above using <code>timeit</code>&#8212;remove the <code>print()</code> calls first)</p></li><li><p>It&#8217;s less prone to errors and bugs</p></li><li><p>It works with a broader selection of data structures, not just sequences</p></li></ul><p>While you wait for my follow-up post on this, you can read more about Python&#8217;s Iterator Protocol, iterables, and iterators here:</p><ul><li><p><a href="https://www.thepythoncodingstack.com/p/the-anatomy-of-a-for-loop">The Anatomy of a for Loop</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/python-iterable-data-structures">Iterable: Python&#8217;s Stepping Stones</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/iterators-in-python-data-structure-6">A One-Way Stream of Data &#8226; Iterators in Python</a></p></li></ul><p>But let&#8217;s move on.</p><p>Let&#8217;s say you want to print out the names alongside each runner&#8217;s position. You&#8217;d like the following output:</p><pre><code>1. Jonathan
2. Michael
3. Samantha
4. Jessica
5. Daniel</code></pre><p>&#8220;Aha!&#8221; I&#8217;m often told by some learners, &#8220;This is when you need to use the <code>for i in range(len(funnel))</code> idiom, since you need the index!&#8221;</p><p>Python&#8217;s <code>for</code> loop doesn&#8217;t explicitly use the index, so you don&#8217;t have access to the index within the <code>for</code> loop. Many revert to the non-Pythonic idioms for this.</p><p>But Python provides tools that let you stay within the pure Pythonic style. Python&#8217;s <code>for</code> loop needs an <a href="https://www.thepythoncodingstack.com/p/iterators-in-python-data-structure-6">iterator</a>&#8212;it will create one from the <a href="https://www.thepythoncodingstack.com/p/python-iterable-data-structures">iterable</a> you provide. All Python iteration needs iterators, not just <code>for</code> loops. Iterators are Python&#8217;s tool for any iteration.</p><p>And there are some bespoke iterators in Python that handle most of your iteration needs. I recently wrote a series about the <code>itertools</code> module. The <code>itertools</code> module contains many such tools. Here&#8217;s the series: <a href="https://www.thepythoncodingstack.com/p/the-itertools-series">The itertools Series</a>.</p><p>But there are also two built-in tools that many forget, but are extremely useful. The first one is <code>enumerate()</code>.</p><p>Here&#8217;s how you can use it to display the Parkrun results:</p><pre><code>&gt;&gt;&gt; for index, name in enumerate(funnel, start=1):
...     print(f&#8221;{index}. {name}&#8221;)
...    
1. Jonathan
2. Michael
3. Samantha
4. Jessica
5. Daniel</code></pre>
      <p>
          <a href="https://www.thepythoncodingstack.com/p/parkruns-pythons-enumerate-and-zip">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[If You Love Queuing, Will You Also Love Priority Queuing?]]></title><description><![CDATA[Exploring Python&#8217;s heapq]]></description><link>https://www.thepythoncodingstack.com/p/python-heapq-heap-priority-queue</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/python-heapq-heap-priority-queue</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Mon, 15 Dec 2025 16:53:19 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/515cd013-b57e-4e17-85ff-495630761833_840x600.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>You provide three tiers to your customers: Gold, Silver, and Bronze. And one of the perks of the higher tiers is priority over the others when your customers need you.</p><p>Gold customers get served first. When no Gold customers are waiting, you serve Silver customers. Bronze customers get served when there&#8217;s no one in the upper tiers waiting.</p><p>How do you set up this queue in your Python program?</p><p>You need to consider which data structure to use to keep track of the waiting customers and what code you&#8217;ll need to write to keep track of the complex queuing rules.</p><p>Sure, you could keep three separate lists (or better still, three <a href="https://thepythoncodingstack.substack.com/p/clearing-the-deque-python-linked-list">`deque` objects</a>). But that&#8217;s not fun! And what if you had more than three priority categories? Perhaps a continuous range of priorities rather than a discrete number?</p><p>There&#8217;s a Python tool for this!</p><p>So let&#8217;s start coding. First, create the data structure to hold the customer names in the queue:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GsIo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!GsIo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!GsIo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!GsIo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GsIo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:6542,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.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_!GsIo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!GsIo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!GsIo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!GsIo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8e709724-0fe6-425f-a08d-50aaa727f0e7_1200x168.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></div><figcaption class="image-caption">All code blocks are available in text format at the end of this article &#8226; #1 &#8226; <em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify</a>. [Affiliate link]</em></figcaption></figure></div><p>&#8220;You told me there&#8217;s a special tool for this? But this is just a bog-standard list, Stephen!!&#8221;</p><p>Don&#8217;t send your complaints just yet. Yes, that&#8217;s a list, but bear with me. We&#8217;ll use the list just as the structure to hold the data, but we&#8217;ll rely on another tool for the fun stuff. It&#8217;s time to import the <code>heapq</code> module, which is part of the Python standard library:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!32fP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!32fP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!32fP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!32fP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!32fP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:7194,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.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_!32fP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!32fP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!32fP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!32fP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F426e85cf-714b-4b9d-a299-4c6b46ed6868_1200x168.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#2</figcaption></figure></div><p>This module contains the tools to create and manage a <em>heap queue</em>, which is also known as a <em>priority queue</em>. I&#8217;ll use the terms &#8216;heap queue&#8217; and &#8216;priority queue&#8217; interchangeably in this post. If you did a computer science degree, you&#8217;d have studied this at some point in your course. But if, like me and many others, you came to programming through a different route, then read on&#8230;</p><p>Let&#8217;s bundle the customer&#8217;s name and priority level into a single item. Jim is the first person to join the queue. He&#8217;s a Silver-tier member. Here&#8217;s what his entry would look like:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JJsO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!JJsO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!JJsO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!JJsO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!JJsO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:5345,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.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_!JJsO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!JJsO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!JJsO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!JJsO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F05810bb7-a9f6-48de-9117-f5a24c3df04f_1200x168.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#3</figcaption></figure></div><p>It&#8217;s a tuple with two elements. The integer <code>2</code> refers to the Silver tier, which has the second priority level. Gold members get a <code>1</code> and Bronze members&#8212;you guessed it&#8212;a <code>3</code>.</p><p>But don&#8217;t use <code>.append()</code> to add Jim to <code>service_queue</code>. Instead, let&#8217;s use <code>heapq.heappush()</code> to <em>push</em> an item onto the <em>heap</em>:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZhD3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2117888-a126-46a8-8714-bbac3a195b46_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!ZhD3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2117888-a126-46a8-8714-bbac3a195b46_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!ZhD3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2117888-a126-46a8-8714-bbac3a195b46_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!ZhD3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2117888-a126-46a8-8714-bbac3a195b46_1200x168.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZhD3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2117888-a126-46a8-8714-bbac3a195b46_1200x168.png" width="1200" height="168" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b2117888-a126-46a8-8714-bbac3a195b46_1200x168.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:168,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:10374,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2117888-a126-46a8-8714-bbac3a195b46_1200x168.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_!ZhD3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2117888-a126-46a8-8714-bbac3a195b46_1200x168.png 424w, https://substackcdn.com/image/fetch/$s_!ZhD3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2117888-a126-46a8-8714-bbac3a195b46_1200x168.png 848w, https://substackcdn.com/image/fetch/$s_!ZhD3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2117888-a126-46a8-8714-bbac3a195b46_1200x168.png 1272w, https://substackcdn.com/image/fetch/$s_!ZhD3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb2117888-a126-46a8-8714-bbac3a195b46_1200x168.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#4</figcaption></figure></div><p>Note that <code>heapq</code> is the name of a module. It&#8217;s not a data type&#8212;you don&#8217;t create an instance of type <code>heapq</code> as you would with data structures. You use a list as the data structure, which is why you pass the list <code>service_queue</code> as the first argument to <code>.heappush()</code>. The second argument is the item you want to push to the heap. In this case, it&#8217;s the tuple <code>(2, &#8220;Jim&#8221;)</code>. You&#8217;ll see later on why you need to put the integer <code>2</code> first in this tuple.</p><p>The <code>heapq</code> module doesn&#8217;t provide a new data structure. Instead, it provides algorithms for creating and managing a priority queue using a list.</p><p>Here&#8217;s the list <code>service_queue</code>:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!av-x!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!av-x!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!av-x!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!av-x!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!av-x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:9152,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.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_!av-x!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!av-x!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!av-x!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!av-x!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc1872af1-f36e-431d-a5e9-759b9e7168f7_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#5</figcaption></figure></div><p>&#8220;So what!&#8221; I hear you say. You would have got the same result if you had used <code>.append()</code>. Bear with me.</p><p>Pam comes in next. She&#8217;s a Gold-tier member:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rxm0!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!rxm0!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!rxm0!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!rxm0!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!rxm0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:18676,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.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_!rxm0!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!rxm0!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!rxm0!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!rxm0!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd3260504-8b6c-4c12-804d-5a220e9cb9c4_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#6</figcaption></figure></div><p>OK, cool, Pam was added at the beginning of the list since she&#8217;s a Gold member. What&#8217;s all the fuss?</p><p>Let&#8217;s see what happens after Dwight and Michael join the queue. Dwight is a Bronze-tier member. He&#8217;s followed in the queue by Michael, who&#8217;s a Silver-tier member:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!V1ab!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!V1ab!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!V1ab!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!V1ab!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!V1ab!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:23340,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.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_!V1ab!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!V1ab!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!V1ab!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!V1ab!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F42adf231-57f2-4fb8-a94b-d4557515aa6e_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#7</figcaption></figure></div><p>OK, this is what you&#8217;d expect once Dwight joins the queue, right? Dwight is a low-priority customer, so he&#8217;s last. Is this just a way of automatically ordering the list, then? Not so fast&#8230;</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ef1s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!ef1s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!ef1s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!ef1s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ef1s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:25597,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.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_!ef1s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!ef1s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!ef1s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!ef1s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F999335a1-290c-4d68-93b0-b730c63d38a7_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#8</figcaption></figure></div><p>The fourth customer to walk in is Michael, who&#8217;s a Silver-tier customer. But he ends up in the last position in the list. What&#8217;s happening here?</p><p>It&#8217;s time to start understanding the heap queue algorithm.</p><h3><strong>Heap Queue &#8226; What&#8217;s Going On?</strong></h3><p>Let&#8217;s go back to when the queue was empty. The first person to join the queue was Jim (Silver tier). Let&#8217;s place Jim in a <em>node</em>:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1eJn!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1eJn!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png 424w, https://substackcdn.com/image/fetch/$s_!1eJn!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png 848w, https://substackcdn.com/image/fetch/$s_!1eJn!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png 1272w, https://substackcdn.com/image/fetch/$s_!1eJn!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!1eJn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png" width="1200" height="462" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:462,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:16005,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4673931c-30cb-4b1d-84ef-bef299e27353_1200x900.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_!1eJn!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png 424w, https://substackcdn.com/image/fetch/$s_!1eJn!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png 848w, https://substackcdn.com/image/fetch/$s_!1eJn!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png 1272w, https://substackcdn.com/image/fetch/$s_!1eJn!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F563cab96-e2fa-4a40-85c5-9a0b7458f0b9_1200x462.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>So far, there&#8217;s nothing too exciting. But let&#8217;s start defining some of the rules in the heap queue algorithm:</p><ul><li><p>Each node can have at most two child nodes&#8212;that&#8217;s two nodes connected to it.</p></li></ul><p>So let&#8217;s add more nodes as more customers join the queue.</p><p>Pam joined next. So Pam&#8217;s node starts as a child node linked to the only node you have so far:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!-r1Z!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!-r1Z!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png 424w, https://substackcdn.com/image/fetch/$s_!-r1Z!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png 848w, https://substackcdn.com/image/fetch/$s_!-r1Z!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png 1272w, https://substackcdn.com/image/fetch/$s_!-r1Z!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!-r1Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png" width="1200" height="679" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:679,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:29378,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fdabc9ac2-ec21-4054-85f1-8551927011fd_1200x900.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_!-r1Z!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png 424w, https://substackcdn.com/image/fetch/$s_!-r1Z!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png 848w, https://substackcdn.com/image/fetch/$s_!-r1Z!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png 1272w, https://substackcdn.com/image/fetch/$s_!-r1Z!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ac3b6e5-f258-4dd1-8422-0d2b4337cc58_1200x679.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>However, here&#8217;s the second rule for dealing with a heap queue:</p><ul><li><p>A child cannot have a higher priority than its parent. If it does, swap places between child and parent.</p></li></ul><p>Recall that <code>1</code> represents the highest priority:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!H4ty!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!H4ty!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png 424w, https://substackcdn.com/image/fetch/$s_!H4ty!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png 848w, https://substackcdn.com/image/fetch/$s_!H4ty!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png 1272w, https://substackcdn.com/image/fetch/$s_!H4ty!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!H4ty!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png" width="1200" height="669" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:669,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:34980,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1877e40a-2582-4ba0-acb2-ef419b915e41_1200x900.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_!H4ty!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png 424w, https://substackcdn.com/image/fetch/$s_!H4ty!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png 848w, https://substackcdn.com/image/fetch/$s_!H4ty!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png 1272w, https://substackcdn.com/image/fetch/$s_!H4ty!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3e1e596e-2b6a-4d94-928d-ccabc5ed5cb4_1200x669.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Pam (Gold tier / 1) is now the parent node, and Jim (Silver tier / 2) is now the child node and lies in the second layer in the hierarchy.</p><p>Bronze-tier member Dwight joined next. Recall that each parent node can have at most two child nodes. Since Pam&#8217;s node still has an empty slot, you add Dwight as a child node to Pam&#8217;s node:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NKXy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88f4569a-3943-4899-974d-e7114f153615_1200x675.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NKXy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88f4569a-3943-4899-974d-e7114f153615_1200x675.png 424w, https://substackcdn.com/image/fetch/$s_!NKXy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88f4569a-3943-4899-974d-e7114f153615_1200x675.png 848w, https://substackcdn.com/image/fetch/$s_!NKXy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88f4569a-3943-4899-974d-e7114f153615_1200x675.png 1272w, https://substackcdn.com/image/fetch/$s_!NKXy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88f4569a-3943-4899-974d-e7114f153615_1200x675.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!NKXy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88f4569a-3943-4899-974d-e7114f153615_1200x675.png" width="1200" height="675" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/88f4569a-3943-4899-974d-e7114f153615_1200x675.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:675,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:36421,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e048e04-bd83-48f5-a243-e0ad097ed249_1200x900.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_!NKXy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88f4569a-3943-4899-974d-e7114f153615_1200x675.png 424w, https://substackcdn.com/image/fetch/$s_!NKXy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88f4569a-3943-4899-974d-e7114f153615_1200x675.png 848w, https://substackcdn.com/image/fetch/$s_!NKXy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88f4569a-3943-4899-974d-e7114f153615_1200x675.png 1272w, https://substackcdn.com/image/fetch/$s_!NKXy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F88f4569a-3943-4899-974d-e7114f153615_1200x675.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Let&#8217;s apply the second rule: the child node cannot have a higher priority than its parent. Dwight is a Bronze-tier member, and so he has a lower priority than Pam. All fine. No swaps needed.</p><p>Michael joined the queue next. He&#8217;s a Silver-tier member. Since Pam&#8217;s node already has two child nodes, you can&#8217;t add more child nodes to Pam. The second layer of the hierarchy is full. So, you take the first node in the second layer, and this now becomes a parent node. So you can add a child node to Jim:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Y5at!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Y5at!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png 424w, https://substackcdn.com/image/fetch/$s_!Y5at!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png 848w, https://substackcdn.com/image/fetch/$s_!Y5at!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png 1272w, https://substackcdn.com/image/fetch/$s_!Y5at!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Y5at!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png" width="1200" height="900" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:900,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:24508,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.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_!Y5at!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png 424w, https://substackcdn.com/image/fetch/$s_!Y5at!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png 848w, https://substackcdn.com/image/fetch/$s_!Y5at!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png 1272w, https://substackcdn.com/image/fetch/$s_!Y5at!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8d9491f4-ff98-47c4-b0e2-9a0b27fe3de2_1200x900.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Time to apply the second rule. But Michael, who&#8217;s in the child node, has the same membership tier as Jim, who&#8217;s in the parent node. Python doesn&#8217;t stop here to resolve the tie. But you&#8217;ll explore this later in this post. For now, just take my word that no swap is needed.</p><p>Let&#8217;s look at the list <code>service_queue</code> again. Recall that this list is hosting the priority queue:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!pcHl!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!pcHl!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!pcHl!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!pcHl!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!pcHl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:15448,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.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_!pcHl!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!pcHl!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!pcHl!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!pcHl!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3c4e6611-a2b0-42e9-9463-3ab9a250ad13_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#9</figcaption></figure></div><p>The priority queue has one node in the top layer. So the first item in the list represents the only node in the top layer. That&#8217;s <code>(1, Pam)</code>.</p><p>The second and third items in the list represent the second layer. There can only be at most two items in this second layer. The fourth item in the list is therefore the start of the third layer. That&#8217;s why it&#8217;s fine for Michael to come after Dwight in the order in the list. It&#8217;s not the actual order in the list that matters, but the relationship between nodes in the heap tree.</p><p>But there&#8217;s more fun to come as we add more customers and start serving them&#8212;and therefore remove them from the priority queue! Let&#8217;s add some more customers first.</p><p>Angela, a Bronze-tier member, joins the queue next. Let&#8217;s add the new node to the tree first:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aQ4B!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aQ4B!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png 424w, https://substackcdn.com/image/fetch/$s_!aQ4B!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png 848w, https://substackcdn.com/image/fetch/$s_!aQ4B!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png 1272w, https://substackcdn.com/image/fetch/$s_!aQ4B!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!aQ4B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png" width="1200" height="900" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:900,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:28987,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.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_!aQ4B!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png 424w, https://substackcdn.com/image/fetch/$s_!aQ4B!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png 848w, https://substackcdn.com/image/fetch/$s_!aQ4B!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png 1272w, https://substackcdn.com/image/fetch/$s_!aQ4B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6d5b651f-d82e-40e2-b3dd-f3df8722329c_1200x900.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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 relationship between parent and child doesn&#8217;t violate the heap queue rule. Angela (Bronze) has a lower priority than the person in the parent node, Jim (Silver):</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!H-Bf!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.png 424w, https://substackcdn.com/image/fetch/$s_!H-Bf!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.png 848w, https://substackcdn.com/image/fetch/$s_!H-Bf!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.png 1272w, https://substackcdn.com/image/fetch/$s_!H-Bf!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!H-Bf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.png" width="1344" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1344,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:27220,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.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_!H-Bf!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.png 424w, https://substackcdn.com/image/fetch/$s_!H-Bf!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.png 848w, https://substackcdn.com/image/fetch/$s_!H-Bf!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.png 1272w, https://substackcdn.com/image/fetch/$s_!H-Bf!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe944e1df-73e4-40e7-912f-b8bc993d84ed_1344x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#10</figcaption></figure></div><p>One more client comes in. It&#8217;s Kevin, and he&#8217;s a Gold-tier member:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!l2mh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!l2mh!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png 424w, https://substackcdn.com/image/fetch/$s_!l2mh!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png 848w, https://substackcdn.com/image/fetch/$s_!l2mh!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png 1272w, https://substackcdn.com/image/fetch/$s_!l2mh!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!l2mh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png" width="1200" height="900" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:900,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:31961,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.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_!l2mh!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png 424w, https://substackcdn.com/image/fetch/$s_!l2mh!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png 848w, https://substackcdn.com/image/fetch/$s_!l2mh!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png 1272w, https://substackcdn.com/image/fetch/$s_!l2mh!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F308fda37-1ed7-4169-bfef-6392466fb893_1200x900.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>There are no more free slots linked to Jim&#8217;s node, so you add Kevin as a child node linked to Dwight. But Kevin has a higher priority than Dwight, so you swap the nodes:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!I5iP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!I5iP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png 424w, https://substackcdn.com/image/fetch/$s_!I5iP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png 848w, https://substackcdn.com/image/fetch/$s_!I5iP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png 1272w, https://substackcdn.com/image/fetch/$s_!I5iP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!I5iP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png" width="1200" height="900" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:900,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:36198,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.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_!I5iP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png 424w, https://substackcdn.com/image/fetch/$s_!I5iP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png 848w, https://substackcdn.com/image/fetch/$s_!I5iP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png 1272w, https://substackcdn.com/image/fetch/$s_!I5iP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56168380-485c-4fec-89c2-b76b29106fbb_1200x900.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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 now you need to compare Kevin&#8217;s node with its parent. Pam and Kevin both have the same membership level. They&#8217;re Gold-tier members.</p><p>But how does Python decide priority in this case?</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AaT7!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!AaT7!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!AaT7!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!AaT7!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!AaT7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:9583,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.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_!AaT7!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!AaT7!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!AaT7!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!AaT7!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F22b01007-780e-4e7c-9538-848b9a7862b4_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#11</figcaption></figure></div><p>Python thinks that <code>(1, &#8220;Kevin&#8221;)</code> has a higher priority than <code>(1, &#8220;Pam&#8221;)</code>&#8212;in Python&#8217;s heap queue algorithm, an item takes priority if it&#8217;s <em>less than</em> another item. Python is comparing tuples. It doesn&#8217;t know anything about your multi-tier queuing system.</p><p>When Python compares tuples, it first compares the first element of each tuple and determines which is smaller. The whole tuple is considered smaller than the other if the first element is smaller than the matching first element in the other tuple. However, if there&#8217;s a tie, Python looks at the second element from each tuple.</p><p>Let&#8217;s briefly assume there&#8217;s a Gold-tier member called Adam:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!vxei!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!vxei!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!vxei!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!vxei!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!vxei!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.png" width="1200" height="210" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:210,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:11018,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.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_!vxei!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.png 424w, https://substackcdn.com/image/fetch/$s_!vxei!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.png 848w, https://substackcdn.com/image/fetch/$s_!vxei!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.png 1272w, https://substackcdn.com/image/fetch/$s_!vxei!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F526fdb6d-37d4-47cc-8c28-c915e3fec9d6_1200x210.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#12</figcaption></figure></div><p>Python now considers <code>(1, &#8220;Adam&#8221;)</code> as the item with a higher priority.</p><p>The second element of each tuple is a string. Therefore, Python sorts these out using alphabetical order (<a href="https://en.wikipedia.org/wiki/Lexicographic_order">lexicographic</a> order, technically).</p><p>That&#8217;s why Kevin takes priority over Pam even though they&#8217;re both Gold-tier members. &#8216;K&#8217; comes before &#8216;P&#8217; in the alphabet! You must swap Kevin and Pam:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!uD9W!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!uD9W!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png 424w, https://substackcdn.com/image/fetch/$s_!uD9W!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png 848w, https://substackcdn.com/image/fetch/$s_!uD9W!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png 1272w, https://substackcdn.com/image/fetch/$s_!uD9W!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!uD9W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png" width="1200" height="900" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:900,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:36008,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.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_!uD9W!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png 424w, https://substackcdn.com/image/fetch/$s_!uD9W!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png 848w, https://substackcdn.com/image/fetch/$s_!uD9W!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png 1272w, https://substackcdn.com/image/fetch/$s_!uD9W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F421b0fc0-0a46-4afd-b30f-7bb83fb07a64_1200x900.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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>Note that the algorithm only needs to consider items along one branch of the tree hierarchy. Jim, Michael, and Angela weren&#8217;t disturbed to figure out where Kevin should go. This technique makes this algorithm efficient, especially as the number of items in the heap increases.</p><p>Incidentally, you can go back to when you added Michael to the queue and see why he didn&#8217;t leapfrog Jim even though they were both members of the same tier. &#8216;M&#8217; comes after &#8216;J&#8217; in the alphabet.</p><p>Now, we can argue that it&#8217;s not fair to give priority to someone just because their name comes first in alphabetical order. We&#8217;ll add timestamps later in this code to act as tie-breakers. But for now, let&#8217;s keep it simple and stick with this setup, where clients&#8217; names are used to break ties.</p><p>Let&#8217;s check that the <code>service_queue</code> list matches the diagram above:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!V1qX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!V1qX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!V1qX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!V1qX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!V1qX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:29820,&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://www.thepythoncodingstack.com/i/181668518?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.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_!V1qX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!V1qX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!V1qX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!V1qX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8ba34974-87a0-4157-b900-ecb0175b5af2_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div></figure></div><p>Kevin is in the first slot in the list, which represents the node at the top of the hierarchy. Jim and Pam are in the second layer, and Michael, Angela, and Dwight are the third generation of nodes. There&#8217;s still one more space in this layer. So, the next client would be added to this layer initially. But we&#8217;ll stop adding clients here in this post.</p><h3><strong>And How Does the Heap Queue Work When Removing Items?</strong></h3><p>It&#8217;s time to start serving these clients and removing them from the priority queue.</p>
      <p>
          <a href="https://www.thepythoncodingstack.com/p/python-heapq-heap-priority-queue">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[My Life • The Autobiography of a Python Object]]></title><description><![CDATA[A short post showing Python from the eyes of object 0x101dd38c0]]></description><link>https://www.thepythoncodingstack.com/p/my-life-the-autobiography-of-a-python-object</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/my-life-the-autobiography-of-a-python-object</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Sun, 30 Nov 2025 11:10:25 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/ec57de47-f6b7-4e0e-9990-f9b83485bc72_2160x2700.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>And that&#8217;s it. I exist.</p><p>I have no recollection of anything before this instant. But I&#8217;m very aware of what I am now. I&#8217;m an object.</p><p>This is the line of code that brought me into existence:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!s_65!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!s_65!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!s_65!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!s_65!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!s_65!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:19198,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.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_!s_65!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!s_65!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!s_65!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!s_65!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff74de7d9-349e-4365-a4f2-f1502bb75552_1200x294.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></div><figcaption class="image-caption">All code blocks are available in text format at the end of this article &#8226; #1 &#8226; <em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify.</a> [Affiliate link]</em></figcaption></figure></div><p>My first recollection from a few moments ago was of being inside <code>Team.__new__()</code>. And I felt an affinity with my clan right away. I was a <code>Team</code> instance&#8212;an object of type <code>Team</code>.</p><p>But then I was whisked from <code>Team.__new__()</code> straight into <code>Team.__init__()</code>. I wasn&#8217;t alone. There were two other objects there with me as we all entered <code>.__init__()</code>. But these other objects weren&#8217;t from my own clan. One was from the <code>str</code> clan, <code>&#8220;The Invincibles&#8221;</code>, and the other was a <code>list</code> object, <code>[&#8221;Claire&#8221;, &#8220;Ishaan&#8221;, &#8220;Margaret&#8221;, &#8220;Dan&#8221;]</code>.</p><p>This was my initiation ceremony to become a proper member of the <code>Team</code> clan:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!5_2O!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!5_2O!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!5_2O!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!5_2O!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!5_2O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:20972,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.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_!5_2O!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!5_2O!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!5_2O!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!5_2O!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa3d0fa4-961f-4351-8f65-a3726f3779f9_1200x294.png 1456w" sizes="100vw"></picture><div></div></div></div><figcaption class="image-caption">#2</figcaption></figure></div><p>Now, I have a closer bond with the other objects that entered <code>.__init__()</code> with me. They&#8217;re my data attributes. They go wherever I go.</p><p>It&#8217;s quite pleasant here. There&#8217;s plenty of camaraderie between objects. Some are very much like me, <code>Team</code> objects. Others are somewhat different. But we&#8217;re all here to help each other achieve a common goal.</p><div><hr></div><p><em>Make sure you don&#8217;t miss a thing here at</em> The Python Coding Stack. <em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts</a>, videos, a members&#8217; forum, and more.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><p><em>&#8230;and you&#8217;ll be supporting this publication by becoming a member of</em> The Club.</p><div><hr></div><p>I&#8217;m being rather rude. I apologise. I haven&#8217;t introduced myself yet.</p><p>I&#8217;m <code>&lt;__main__.Team object at 0x101dd38c0&gt;</code>. Yes, that&#8217;s me. Honest. If you don&#8217;t like hexadecimal numbers, you can use the decimal version of my unique identity number:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Rqme!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!Rqme!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!Rqme!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!Rqme!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!Rqme!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:13769,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.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_!Rqme!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!Rqme!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!Rqme!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!Rqme!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F29543247-0a01-4bca-bd86-d6b96697ca1e_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#3</figcaption></figure></div><p>That number is who I am. It&#8217;s the slot in memory I was allocated when I came into existence. It&#8217;s the only way you can identify me for as long as I exist. Python gives each one of us objects a unique number so it can distinguish us.</p><p>But you can&#8217;t call me by that number. That&#8217;s not my name, it&#8217;s my identity.</p><p>You can call me <code>the_invincibles</code>. That&#8217;s also easier than using a number, right? Just bear in mind that some other object may steal that name from me later. But for the time being, <code>the_invincibles</code> will do just fine.</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FaL8!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!FaL8!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!FaL8!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!FaL8!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!FaL8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:13557,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.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_!FaL8!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!FaL8!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!FaL8!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!FaL8!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa535548-82cc-4bb9-ae02-7e295d0ecc58_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#4</figcaption></figure></div><p>And now you have another way to call me if you prefer. I&#8217;ll also respond to <code>all_teams[0]</code>. I have two names now!</p><p>But if you enquire who I am in the Python program using <code>print()</code>, you won&#8217;t get either of those names. Confusing, I know:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!rXmU!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!rXmU!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!rXmU!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!rXmU!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!rXmU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:9477,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.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_!rXmU!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!rXmU!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!rXmU!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!rXmU!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F26902e5e-78e0-4a1c-920a-4bb012f29838_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#5</figcaption></figure></div><p>Python needs to display me on the screen. It asks me for help to do this.</p><p>&#8220;Hey, object 0x101dd38c0, do you have a <code>.__str__()</code> special method?&#8221;, Python asks me.</p><p>&#8220;I don&#8217;t&#8221;, I respond.</p><p>&#8220;How about <code>.__repr__()</code>? Do you have one of those?&#8221;</p><p>Yes, as it happens, I 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_!dV1B!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!dV1B!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!dV1B!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!dV1B!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!dV1B!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!dV1B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png" width="1200" height="504" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:504,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:51251,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.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_!dV1B!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png 424w, https://substackcdn.com/image/fetch/$s_!dV1B!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png 848w, https://substackcdn.com/image/fetch/$s_!dV1B!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png 1272w, https://substackcdn.com/image/fetch/$s_!dV1B!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7c06b94d-ce96-4566-b4f2-1d6d8faf21db_1200x504.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#6</figcaption></figure></div><p>So Python asks me to give it whatever this method returns, and it uses it as the return value for <code>print()</code>:</p><pre><code>Team(
    team_name=&#8217;The Invincibles&#8217;,
    members=[&#8217;Claire&#8217;, &#8216;Ishaan&#8217;, &#8216;Margaret&#8217;, &#8216;Dan&#8217;]
)</code></pre><p>Python can&#8217;t do anything without my help. I feel good about this!</p><p>-- --</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!hINP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!hINP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!hINP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!hINP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!hINP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:15190,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.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_!hINP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!hINP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!hINP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!hINP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6fb63eff-46b0-4952-bf22-077cb8eaadc6_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#7</figcaption></figure></div><p>Python found this code later in the program.</p><p>&#8220;Hey there again, you&#8221;, Python tells me. &#8220;I need to ask you something else. Do you have the <code>.__iter__()</code> special method?&#8221;</p><p>&#8220;Yes, I do. What do you need?&#8221; I respond.</p><p>&#8220;Can you give me the iterator from that method, please?&#8221;</p><p>Here&#8217;s the class showing my <code>.__iter__()</code> method, too:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DU_W!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DU_W!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!DU_W!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!DU_W!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!DU_W!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!DU_W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:63642,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.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_!DU_W!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!DU_W!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!DU_W!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!DU_W!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F2e54fc41-09da-4113-98b6-0fe1f6571816_1200x630.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#8</figcaption></figure></div><p>Python now knows what to do to iterate through me:</p><pre><code>Claire
Ishaan
Margaret
Dan</code></pre><p>I told you, Python can&#8217;t do anything on its own. It needs my help with everything. Good thing I&#8217;m here, and I have all the instructions Python needs to deal with me!</p><p>-- --</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!UR84!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!UR84!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!UR84!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!UR84!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!UR84!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:11765,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.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_!UR84!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!UR84!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!UR84!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!UR84!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe425a9ff-647d-4859-956c-6dd99f6b4924_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#9</figcaption></figure></div><p>&#8220;Psst, it&#8217;s me again&#8221;, says Python. &#8220;Do you know what this <code>.add_member</code> thing is?&#8221;</p><p>&#8220;Yes, yes, it&#8217;s one of my attributes, the stuff I carry with me, like everyone else in my <code>Team</code> clan&#8221;, I say.</p><p>Here&#8217;s the 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_!9JjY!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9JjY!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!9JjY!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!9JjY!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!9JjY!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!9JjY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png" width="1200" height="756" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:756,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:78162,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.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_!9JjY!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png 424w, https://substackcdn.com/image/fetch/$s_!9JjY!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png 848w, https://substackcdn.com/image/fetch/$s_!9JjY!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png 1272w, https://substackcdn.com/image/fetch/$s_!9JjY!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F555144a6-e690-4645-985b-ef4f7b5478b4_1200x756.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#10</figcaption></figure></div><p>-- --</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1RWI!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!1RWI!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!1RWI!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!1RWI!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!1RWI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:8379,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.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_!1RWI!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!1RWI!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!1RWI!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!1RWI!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7b2f56ba-29ef-4425-9d7f-36e2229cc82b_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#11</figcaption></figure></div><p>Oh no! I&#8217;ve lost my name. But I&#8217;m still here, don&#8217;t worry. I still exist. Remember that you can still call me using <code>all_teams[0]</code>:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!z4-y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!z4-y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!z4-y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!z4-y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!z4-y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:14522,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.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_!z4-y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!z4-y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!z4-y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!z4-y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F69a22fb5-9351-4742-a5e3-015a76a3038b_1200x294.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#12</figcaption></figure></div><p>Here&#8217;s proof I still exist:</p><pre><code>Claire
Ishaan
Margaret
Dan
Keith</code></pre><p>But wait a moment. I just caught a glimpse of the next line of code&#8230;</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kLwr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!kLwr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!kLwr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!kLwr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!kLwr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.png" width="1200" height="252" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:252,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:7221,&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://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.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_!kLwr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.png 424w, https://substackcdn.com/image/fetch/$s_!kLwr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.png 848w, https://substackcdn.com/image/fetch/$s_!kLwr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.png 1272w, https://substackcdn.com/image/fetch/$s_!kLwr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffc5d952a-3ac9-47ad-a39f-0a8c475ee098_1200x252.png 1456w" sizes="auto, 100vw" loading="lazy"></picture><div></div></div></div><figcaption class="image-caption">#13</figcaption></figure></div><p>&#8220;Hey object, can I check something with you, please?&#8221; It&#8217;s Python again. What does it want this time?</p><p>&#8220;Do you still have any names left? Any references left?&#8221;</p><p>I was worried Python would ask me this. There was a time I had two references&#8212;two ways you could get to me: <code>the_invincibles</code> and <code>all_teams[0]</code>. But first I lost the name <code>the_invincibles</code>. Now, the object <code>all_teams</code> no longer exists.</p><p>I no longer have any references pointing towards me&#8230;</p><h2><strong>Epilogue</strong></h2><p>Object 0x101dd38c0 would have loved to be here to say goodbye to you in person, but the object is no longer here. Its existence was brief yet fulfilling. Python has no mercy. The moment it realised there was nothing left in the program referring to object 0x101dd38c0, it sharpened the guillotine and&#8230;</p><p>The irony is that Python still needed help from the object to figure out that there weren&#8217;t any references left. Objects keep track themselves of how many references point to them!</p><p>It&#8217;s what object 0x101dd38c0 had been telling us all along. Python can&#8217;t get anything done without the information that objects carry around with them wherever they go!</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!IWBR!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!IWBR!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg 424w, https://substackcdn.com/image/fetch/$s_!IWBR!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg 848w, https://substackcdn.com/image/fetch/$s_!IWBR!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!IWBR!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!IWBR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg" width="566" height="707.5" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1820,&quot;width&quot;:1456,&quot;resizeWidth&quot;:566,&quot;bytes&quot;:127630,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.thepythoncodingstack.com/i/180307057?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.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_!IWBR!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg 424w, https://substackcdn.com/image/fetch/$s_!IWBR!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg 848w, https://substackcdn.com/image/fetch/$s_!IWBR!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!IWBR!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe2fcc54e-ef15-4a38-be4a-111e04da4dbe_2160x2700.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em>Photo by Dayan Rodio: <a href="https://www.pexels.com/photo/a-man-reading-book-while-sitting-on-a-bed-4132936/">https://www.pexels.com/photo/a-man-reading-book-while-sitting-on-a-bed-4132936/</a></em></p><div><hr></div><p><em>Code in this article uses Python 3.14</em></p><p><em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify</a>.</em> <em>[Affiliate link]</em></p><p><em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts</a>, videos, a members&#8217; forum, and more.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><p><em>You can also support this publication by making a <a href="https://buy.stripe.com/00g3de2iGdgg4gg7su">one-off contribution of any amount you wish</a>.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://buy.stripe.com/00g3de2iGdgg4gg7su&quot;,&quot;text&quot;:&quot;Support The Python Coding Stack&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://buy.stripe.com/00g3de2iGdgg4gg7su"><span>Support The Python Coding Stack</span></a></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com/">stephengruppetta.com</a></em></p><p>Further reading related to this article&#8217;s topic:</p><ul><li><p><a href="https://thepythoncodingstack.substack.com/p/python-garbage-collection-reference-counting-and-cyclic">When You No Longer Need That Object &#8226; Dealing With Garbage in Python</a></p></li><li><p><a href="https://thepythoncodingstack.substack.com/p/and-now-for-something-new-python-special-method">And Now for Something New</a></p></li><li><p><a href="https://realpython.com/python-repr-vs-str/">When Should You Use </a><code>.__repr__()</code><a href="https://realpython.com/python-repr-vs-str/"> vs </a><code>.__str__()</code><a href="https://realpython.com/python-repr-vs-str/"> in Python? &#8211; Real Python</a></p></li><li><p><a href="https://www.thepythoncodingstack.com/p/whats-in-a-name-python-namespace-objects-names">What&#8217;s in a Name?</a></p></li></ul><div><hr></div><h2>Appendix: Code Blocks</h2><h5>Code Block #1</h5><pre><code><code>the_invincibles = Team(
    &#8220;The Invincibles&#8221;,
    [&#8221;Claire&#8221;, &#8220;Ishaan&#8221;, &#8220;Margaret&#8221;, &#8220;Dan&#8221;],
)
</code></code></pre><h5>Code Block #2</h5><pre><code><code>class Team:
    def __init__(self, team_name, members):
        self.team_name = team_name
        self.members = members
</code></code></pre><h5>Code Block #3</h5><pre><code><code># ...

print(id(the_invincibles))
# 4326242496
</code></code></pre><h5>Code Block #4</h5><pre><code><code># ...

all_teams = []
all_teams.append(the_invincibles)
</code></code></pre><h5>Code Block #5</h5><pre><code><code># ...

print(the_invincibles)
</code></code></pre><h5>Code Block #6</h5><pre><code><code>class Team:
    def __init__(self, team_name, members):
        self.team_name = team_name
        self.members = members

    def __repr__(self):
        return (f&#8221;{type(self).__name__}(&#8221;
                f&#8221;team_name={self.team_name!r}, &#8220;
                f&#8221;members={self.members!r})&#8221;)
</code></code></pre><h5>Code Block #7</h5><pre><code><code># ...

for team_member in the_invincibles:
    print(team_member)
</code></code></pre><h5>Code Block #8</h5><pre><code><code>class Team:
    def __init__(self, team_name, members):
        self.team_name = team_name
        self.members = members

    def __repr__(self):
        return (f&#8221;{type(self).__name__}(&#8221;
                f&#8221;team_name={self.team_name!r}, &#8220;
                f&#8221;members={self.members!r})&#8221;)

    def __iter__(self):
        return iter(self.members)
</code></code></pre><h5>Code Block #9</h5><pre><code><code># ...

the_invincibles.add_member(&#8221;Keith&#8221;)
</code></code></pre><h5>Code Block #10</h5><pre><code><code>class Team:
    def __init__(self, team_name, members):
        self.team_name = team_name
        self.members = members

    def __repr__(self):
        return (f&#8221;{type(self).__name__}(&#8221;
                f&#8221;team_name={self.team_name!r}, &#8220;
                f&#8221;members={self.members!r})&#8221;)

    def __iter__(self):
        return iter(self.members)

    def add_member(self, name):
        self.members.append(name)
</code></code></pre><h5>Code Block #11</h5><pre><code><code># ...

del the_invincibles
</code></code></pre><h5>Code Block #12</h5><pre><code><code># ...

for team_member in all_teams[0]:
    print(team_member)
</code></code></pre><h5>Code Block #13</h5><pre><code><code># ...

del all_teams
</code></code></pre><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com/">stephengruppetta.com</a></em></p>]]></content:encoded></item><item><title><![CDATA[I Don’t Like Magic • Exploring The Class Attributes That Aren’t Really Class Attributes]]></title><description><![CDATA[This syntax, used for data classes and typing.NamedTuple, confused me when first learning about these topics. Here&#8217;s why, and why it&#8217;s no longer confusing.]]></description><link>https://www.thepythoncodingstack.com/p/i-dont-like-magic-exploring-the-class</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/i-dont-like-magic-exploring-the-class</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Tue, 18 Nov 2025 22:01:25 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/29c36185-05bf-45e2-aa70-510fca9f86aa_840x600.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I don&#8217;t like magic. I don&#8217;t mean the magic of the Harry Potter kind&#8212;that one I&#8217;d like if only I could have it. It&#8217;s the &#8220;magic&#8221; that happens behind the scenes when a programming language like Python does things out of sight. You&#8217;ll often find things you have to &#8220;just learn&#8221; along the Python learning journey. &#8220;That&#8217;s the way things are,&#8221; you&#8217;re told.</p><p>That&#8217;s the kind of magic I don&#8217;t like. I want to know how things work. So let me take you back to when I first learnt about named tuples&#8212;the <code>NamedTuple</code> in the <code>typing</code> module, not the other one&#8212;and data classes. They share a similar syntax, and it&#8217;s this shared syntax that confused me at first. I found these topics harder to understand because of this.</p><p>Their syntax is different from other stuff I had learnt up to that point. And I could not reconcile it with the stuff I knew. That bothered me. It also made me doubt the stuff I already knew. Here&#8217;s what I mean. Let&#8217;s look at a standard class first:</p><pre><code>class Person:
    classification = &#8220;Human&#8221;
&#8203;
    def __init__(self, name, age, profession):
        self.name = name
        self.age = age
        self.profession = profession</code></pre><p>You define a class attribute, <code>.classification</code>, inside the class block, but outside any of the special methods. All instances will share this class attribute. Then you define the <code>.__init__()</code> special method and create three instance attributes: <code>.name</code>, <code>.age</code>, and <code>.profession</code>. Each instance will have its own versions of these instance attributes. If you&#8217;re not familiar with class attributes and instance attributes, you can read my seven-part series on object-oriented programming: <a href="https://www.thepythoncodingstack.com/p/a-magical-tour-through-object-oriented">A Magical Tour Through Object-Oriented Programming in Python &#8226; Hogwarts School of Codecraft and Algorithmancy</a></p><p>Now, let&#8217;s assume you don&#8217;t actually need the class attribute and that this class will only store data. It won&#8217;t have any additional methods. You decide to use a data class instead:</p><pre><code>from dataclasses import dataclass
&#8203;
@dataclass
class Person:
    name: str
    age: int
    profession: str</code></pre><p>Or you prefer to use a named tuple, and you reach out for <code>typing.NamedTuple</code>:</p><pre><code>from typing import NamedTuple
&#8203;
class Person(NamedTuple):
    name: str
    age: int
    profession: str</code></pre><p>The syntax is similar. I&#8217;ll tell you why I used to find this confusing soon.</p><p>Whichever option you choose, you can create an instance using <code>Person(&#8221;Matthew&#8221;, 30, &#8220;Python Programmer&#8221;)</code>. And each instance you create will have its own instance attributes <code>.name</code>, <code>.age</code>, and <code>.profession</code>.</p><p>But wait a minute! The data class and the named tuple use syntax that&#8217;s similar to creating <em>class</em> attributes. You define these just inside the class block and not in an <code>.__init__()</code>  method. How come they create instance attributes? &#8220;That&#8217;s just how they work&#8221; is not good enough for me.</p><p>These aren&#8217;t class attributes. Not yet. There&#8217;s no value associated with these identifiers. Therefore, they can&#8217;t be class attributes, even though you write them where you&#8217;d normally add class attributes in a standard class. However, they can be class attributes if you include a default value:</p><pre><code>@dataclass
class Person:
    name: str
    age: int
    profession: str = &#8220;Python Programmer&#8221;</code></pre><p>The <code>.profession</code> attribute now has a string assigned to it. In a data class, this represents the default value. But if this weren&#8217;t a data class, you&#8217;d look at <code>.profession</code> and recognise it as a class attribute. But in a data class, it&#8217;s not a class attribute, it&#8217;s an instance attribute, as are <code>.name</code> and <code>.age</code>, which look like&#8230;what do they look like, really? They&#8217;re just type hints. Yes, type hints without any object assigned. Python type hints allow you to do this:</p><pre><code>&gt;&gt;&gt; first_name: str</code></pre><p>This line is valid in Python. It does not create the variable <code>name</code>. You can confirm this:</p><pre><code>&gt;&gt;&gt; first_name
Traceback (most recent call last):
  File &#8220;&lt;input&gt;&#8221;, line 1, in &lt;module&gt;
NameError: name &#8216;first_name&#8217; is not defined</code></pre><p>Although you cannot just write <code>first_name</code> if the identifier doesn&#8217;t exist, you can use <code>first_name: str</code>. This creates an annotation which serves as the type hint. Third-party tools now know that when you create the variable <code>first_name</code> and assign it a value, it ought to be a string.</p><p>So, let&#8217;s go back to the latest version of the <code>Person</code> data class with the default value for one of the attributes:</p><pre><code>@dataclass
class Person:
    name: str
    age: int
    profession: str = &#8220;Python Programmer&#8221;</code></pre><p>But let&#8217;s ignore the <code>@dataclass</code> decorator for now. Indeed, let&#8217;s remove this decorator:</p><pre><code>class Person:
    name: str
    age: int
    profession: str = &#8220;Python Programmer&#8221;</code></pre><p>You define a class with one class attribute, <code>.profession</code> and three type hints:</p><ul><li><p><code>name: str</code></p></li><li><p><code>age: int</code></p></li><li><p><code>profession: str</code></p></li></ul><p>How can we convert this information into instance attributes when creating an instance of the class? I won&#8217;t try to reverse engineer <code>NamedTuple</code> or data classes here. Instead, I&#8217;ll explore my own path to get a sense of what might be happening in those tools.</p><p>Let&#8217;s start hacking away&#8230;</p>
      <p>
          <a href="https://www.thepythoncodingstack.com/p/i-dont-like-magic-exploring-the-class">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[The Misunderstood Hashable Types and Why Dictionaries Are Called Dictionaries]]></title><description><![CDATA[What does hashable really mean? And what&#8217;s the real superpower in dictionaries?]]></description><link>https://www.thepythoncodingstack.com/p/the-misunderstood-hashable-types</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/the-misunderstood-hashable-types</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Sun, 09 Nov 2025 13:09:33 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/470a3dd0-3aed-438a-9320-0b6d1aab9fa8_840x600.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Pick up a dictionary. No, not that one. The <em>real</em> dictionary you have on your bookshelf, the one that has pages made of paper, which you use to look up the meaning of English words. Or whatever other language. But let&#8217;s assume it&#8217;s an English dictionary. Now, look up <em>zymology</em>.</p><p>I&#8217;ll wait&#8230;</p><p>Done? It probably didn&#8217;t take you too long to find <em>zymology</em>. Probably it took you longer to find the dictionary on your bookshelf, the one you haven&#8217;t used in years!</p><p>You know <em>z</em> is the last letter of the alphabet, so you opened the dictionary on a page towards the end of the book. Then you looked at a random word on the page or maybe the word listed in the header. Does it start with <em>z</em>? Yes? Look at the word&#8217;s second letter. No? Open the book to another page further in the dictionary.</p><p>You get the idea. I know you know how to find a word in a dictionary.</p><p>But now, imagine that you didn&#8217;t know the alphabet. Bear with me. Just assume you can recognise letters, so you can read words, but you don&#8217;t know the order of the letters in the alphabet. You don&#8217;t know that <em>A</em> comes first and <em>D</em> is the fourth one, and so on.</p><p>How would you find <em>zymology</em> now? And how long do you reckon it will take you to find the word?</p><p>There you go, now you understand the purpose of using hash values for hashable objects. Or you can read on&#8230;</p><p><em>Today, I also explore the topic in a short video where I can communicate differently. But if you prefer to just read, then go ahead and skip the video.</em></p><div class="native-video-embed" data-component-name="VideoPlaceholder" data-attrs="{&quot;mediaUploadId&quot;:&quot;bf9ba53f-bef7-4aca-af21-553bac4afa0f&quot;,&quot;duration&quot;:null}"></div><p></p><p>Let&#8217;s continue exploring dictionaries and hashable objects.</p>
      <p>
          <a href="https://www.thepythoncodingstack.com/p/the-misunderstood-hashable-types">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[And Now You Know Your ABC]]></title><description><![CDATA[How helping at my track club's championships led to Python Abstract Base Classes]]></description><link>https://www.thepythoncodingstack.com/p/and-now-you-know-your-abc-python-abstract-base-classes</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/and-now-you-know-your-abc-python-abstract-base-classes</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Sat, 01 Nov 2025 12:52:51 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/$s_!0Wu3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I may have already mentioned in a previous post that I&#8217;ve rekindled an old passion: track and field athletics. I&#8217;m even writing about it in another publication: <em><a href="https://backonthetrack.substack.com/">Back on the Track</a></em> (look out for the new series on sprint biomechanics, if you&#8217;re so inclined!)</p><p>This post is inspired by a brief thought that crossed my mind when I considered writing software to assist my club&#8212;in the end, I chose not to. (But I already volunteer three hours a week coaching members of the youth team. So no, I don&#8217;t feel guilty.)</p><p>Here&#8217;s the task. I want to create a class to represent a track and field event held in a competition. This entry allows you to enter the raw results as reported by the officials&#8212;the athlete&#8217;s bib number and the time they clocked in a race. It then computes the event&#8217;s full results.</p><h2><strong>Athletes and Events</strong></h2><p>A good starting point is to define two classes, <code>Athlete</code> and <code>Event</code>. I&#8217;ll focus on the <code>Event</code> class in this post, so I&#8217;ll keep the <code>Athlete</code> class fairly basic:</p><div class="captioned-image-container"><figure><div class="image-link image2" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!8Ehp!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!8Ehp!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!8Ehp!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!8Ehp!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!8Ehp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.png" width="1200" height="294" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:294,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:21200,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.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_!8Ehp!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.png 424w, https://substackcdn.com/image/fetch/$s_!8Ehp!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.png 848w, https://substackcdn.com/image/fetch/$s_!8Ehp!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.png 1272w, https://substackcdn.com/image/fetch/$s_!8Ehp!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F70c5b762-5b29-4520-b588-7d3b8b29b8d8_1200x294.png 1456w" sizes="100vw" fetchpriority="high"></picture><div></div></div></div><figcaption class="image-caption">All code blocks are available in text format at the end of this article &#8226; #1 &#8226; <em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify.</a> [Affiliate link]</em></figcaption></figure></div><p>There&#8217;s more we could add to make this class more complete. But I won&#8217;t. You can create a list of athletes that are competing in the track and field meeting:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Y2cQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Y2cQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!Y2cQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!Y2cQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!Y2cQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Y2cQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.png" width="1200" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/fa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:71850,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.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_!Y2cQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.png 424w, https://substackcdn.com/image/fetch/$s_!Y2cQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.png 848w, https://substackcdn.com/image/fetch/$s_!Y2cQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.png 1272w, https://substackcdn.com/image/fetch/$s_!Y2cQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ffa2c66e5-7119-429f-a5b9-be9261d09d28_1200x630.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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#2</figcaption></figure></div><p>To make it easy and efficient to obtain the <code>Athlete</code> object just from a bib number, you can create a <code>bib_to_athlete</code> dictionary:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!sO2P!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!sO2P!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png 424w, https://substackcdn.com/image/fetch/$s_!sO2P!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png 848w, https://substackcdn.com/image/fetch/$s_!sO2P!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png 1272w, https://substackcdn.com/image/fetch/$s_!sO2P!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!sO2P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png" width="1218" height="336" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:336,&quot;width&quot;:1218,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:15558,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.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_!sO2P!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png 424w, https://substackcdn.com/image/fetch/$s_!sO2P!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png 848w, https://substackcdn.com/image/fetch/$s_!sO2P!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png 1272w, https://substackcdn.com/image/fetch/$s_!sO2P!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F58a40556-b3b0-4924-9555-9484d61124c1_1218x336.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#3</figcaption></figure></div><p></p><p>The dictionary&#8217;s keys are the bib numbers as integers and the values are the <code>Athlete</code> objects. Therefore, <code>print(bib_to_athlete[259].name)</code> displays <code>&#8220;Carl Lewis&#8221;</code>.</p><p>Now, let&#8217;s move to the <code>Event</code> class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!c4ei!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!c4ei!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png 424w, https://substackcdn.com/image/fetch/$s_!c4ei!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png 848w, https://substackcdn.com/image/fetch/$s_!c4ei!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png 1272w, https://substackcdn.com/image/fetch/$s_!c4ei!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!c4ei!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png" width="1200" height="420" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:420,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:29657,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.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_!c4ei!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png 424w, https://substackcdn.com/image/fetch/$s_!c4ei!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png 848w, https://substackcdn.com/image/fetch/$s_!c4ei!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png 1272w, https://substackcdn.com/image/fetch/$s_!c4ei!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd0082180-6b82-4192-850e-05d2d755c8b5_1200x420.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#4</figcaption></figure></div><p>Let&#8217;s go through the data attributes in <code>Event.__init__()</code>:</p><ul><li><p><code>.event_name</code> is a string with the name of the event. You could use other data types, such as an <code>Enum</code>, but I&#8217;ll keep this simple here and use a string.</p></li><li><p><code>.participants</code> is a list containing <code>Athlete</code> instances. These are the athletes participating in this particular event at the track and field meeting.</p></li><li><p><code>.results</code> contains each athlete&#8217;s performance. We have choices. The simplest option is to use a list of tuples, where each tuple contains the athlete and the performance. However, since we&#8217;re working in the object-oriented domain, perhaps we could create a <code>Result</code> class, and <code>.results</code> becomes a list of <code>Result</code> instances.</p></li></ul><p>So, let&#8217;s create the <code>Result</code> class at the top of the script:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!4GQF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!4GQF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png 424w, https://substackcdn.com/image/fetch/$s_!4GQF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png 848w, https://substackcdn.com/image/fetch/$s_!4GQF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png 1272w, https://substackcdn.com/image/fetch/$s_!4GQF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!4GQF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png" width="1200" height="378" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:378,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:25593,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.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_!4GQF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png 424w, https://substackcdn.com/image/fetch/$s_!4GQF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png 848w, https://substackcdn.com/image/fetch/$s_!4GQF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png 1272w, https://substackcdn.com/image/fetch/$s_!4GQF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe6df8351-5dc3-43b6-b862-18d4fc578614_1200x378.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#5</figcaption></figure></div><p>We&#8217;ll show an example of <code>Event</code> and <code>Result</code> instances soon. But first we need some methods. Let&#8217;s get back to the <code>Event</code> class and define <code>.add_result()</code>, which allows you to add a raw result in the format provided by the officials&#8212;the officials only provide the bib number and the performance, such as the time clocked by the athlete:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GSKH!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GSKH!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png 424w, https://substackcdn.com/image/fetch/$s_!GSKH!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png 848w, https://substackcdn.com/image/fetch/$s_!GSKH!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png 1272w, https://substackcdn.com/image/fetch/$s_!GSKH!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!GSKH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png" width="1236" height="630" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:630,&quot;width&quot;:1236,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:60645,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.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_!GSKH!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png 424w, https://substackcdn.com/image/fetch/$s_!GSKH!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png 848w, https://substackcdn.com/image/fetch/$s_!GSKH!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png 1272w, https://substackcdn.com/image/fetch/$s_!GSKH!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F6c77315d-6b88-4982-992d-29a1b1d8f761_1236x630.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#6</figcaption></figure></div><p>You add checks for the scenarios when a bib number doesn&#8217;t match any athlete in the whole meeting or when the bib number doesn&#8217;t match any athlete in the specific event. The dictionary <code>.get()</code> method returns <code>None</code> by default if the key is not present in the dictionary.</p><p>If the bib number is valid, you create a <code>Result</code> instance and add it to <code>.results</code>.</p><p>Once you add all the results from the officials, you&#8217;re ready to finalise the results:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!tZ5Y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!tZ5Y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png 424w, https://substackcdn.com/image/fetch/$s_!tZ5Y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png 848w, https://substackcdn.com/image/fetch/$s_!tZ5Y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png 1272w, https://substackcdn.com/image/fetch/$s_!tZ5Y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!tZ5Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png" width="1200" height="420" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:420,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:27237,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.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_!tZ5Y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png 424w, https://substackcdn.com/image/fetch/$s_!tZ5Y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png 848w, https://substackcdn.com/image/fetch/$s_!tZ5Y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png 1272w, https://substackcdn.com/image/fetch/$s_!tZ5Y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1995d6a9-5383-4465-a8c5-bfca29e2a785_1200x420.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#7</figcaption></figure></div><p>This method sorts the list of results based on the value of the <code>.performance</code> data attribute.</p><p>If you&#8217;re not familiar with <code>lambda</code> functions, you can read <a href="https://thepythoncodingstack.substack.com/p/whats-all-the-fuss-about-python-lambda-functions">What&#8217;s All the Fuss About &#8216;lambda&#8217; Functions in Python</a>. And to read more about the <code>key</code> parameter in  <code>.sort()</code>, see <a href="https://www.thepythoncodingstack.com/p/the-key-to-the-key-parameter-in-python">The Key to the &#8216;key&#8217; Parameter in Python</a>.</p><p>Let&#8217;s try this class to see everything is as we expect:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!j46s!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!j46s!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png 424w, https://substackcdn.com/image/fetch/$s_!j46s!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png 848w, https://substackcdn.com/image/fetch/$s_!j46s!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png 1272w, https://substackcdn.com/image/fetch/$s_!j46s!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!j46s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png" width="1290" height="714" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:714,&quot;width&quot;:1290,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:73160,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.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_!j46s!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png 424w, https://substackcdn.com/image/fetch/$s_!j46s!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png 848w, https://substackcdn.com/image/fetch/$s_!j46s!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png 1272w, https://substackcdn.com/image/fetch/$s_!j46s!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F06bd8e7e-a43f-4bf4-b55b-b37aff90e267_1290x714.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#8</figcaption></figure></div><p>You create an <code>Event</code> instance for the 100m sprint race. Then you add three individual results. Finally, you finalise the results to get the athletes and their positions in the race.</p><p>Since <code>.finalise_results()</code> sorts based on the performace, the athlete with the fastest time takes the first position in the list, and so on. Here&#8217;s the output from the <code>for</code> loop displaying the athletes in <code>.results</code> in order:</p><pre><code>Usain Bolt: 9.58
Carl Lewis: 9.86
Jesse Owens: 10.3</code></pre><p>Usain Bolt is first with the fastest time, followed by Carl Lewis, and Jesse Owens in third. Everything seems to be working well&#8230; But &#8220;It works&#8221; are the two most dangerous words in programming!</p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><h2><strong>It&#8217;s Time For The Long Jump</strong></h2><p>The long jump results come in next from the officials. You know how to input the data and finalise the results now:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!ZsCK!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!ZsCK!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png 424w, https://substackcdn.com/image/fetch/$s_!ZsCK!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png 848w, https://substackcdn.com/image/fetch/$s_!ZsCK!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png 1272w, https://substackcdn.com/image/fetch/$s_!ZsCK!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!ZsCK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png" width="1200" height="672" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/bf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:672,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:66803,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.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_!ZsCK!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png 424w, https://substackcdn.com/image/fetch/$s_!ZsCK!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png 848w, https://substackcdn.com/image/fetch/$s_!ZsCK!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png 1272w, https://substackcdn.com/image/fetch/$s_!ZsCK!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbf5c8dce-9156-40eb-aa49-a2e5f7443ae3_1200x672.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#9</figcaption></figure></div><p>And here are the results displayed:</p><pre><code>Carl Lewis: 8.87
Mike Powell: 8.95</code></pre><p>But, but&#8230; Mike Powell&#8217;s 8.95m is better than Carl Lewis&#8217;s 8.87m. The order is wrong!</p><p>Of course! In the 100m sprint the fastest time wins, and the fastest time is the lowest number. But in the long jump it&#8217;s the longest jump that wins, and that&#8217;s the largest number!</p><p>The <code>.finalise_results()</code> method no longer works for the long jump or for other field events. For field events, the sorting needs to happen in reverse order.</p><p>There are several ways to deal with this problem. There are always several ways to solve a problem in programming.</p><p>The simplest is to add an <code>.is_field_event</code> Boolean data attribute in <code>Event</code> and then add an <code>if</code> statement in <code>.finalise_results()</code>. And if this were the only difference between running and field events, this would indeed be a fine option.</p><p>However, if there are more differences to account for, the extra fields and <code>if</code> statements scattered throughout the class make the class harder to maintain.</p><p>So, let&#8217;s look at another option.</p><h2><strong>Creating Separate Classes for Track Events and Field Events</strong></h2><p>You could create two classes instead of one: <code>TrackEvent</code> and <code>FieldEvent</code>. Each class will take care of getting the <code>finalise_results()</code> method right and also deal with any other differences we may find between track events and field events.</p><p>However, you don&#8217;t want to create two unrelated classes since these classes will have a lot in common. Sure, you can copy and paste the code that&#8217;s common between the two classes, but you don&#8217;t need me to tell you that&#8217;s not a good idea. Will you remember to make changes in both places when you decide to change the implementation later?</p><p>You also want to make sure they have the same data attribute names for similar things. For example, you don&#8217;t want one class to have <code>.finalise_results()</code> and the other <code>.final_results()</code>, say, or change the spelling by mistake. Now, I know you&#8217;ll pay attention when creating these methods to make sure this doesn&#8217;t happen, but why take the risk?</p><p>And when you come back to your code in six months&#8217; time (or a colleague starts working on the code) and you decide you need another class that follows the same principles, will you remember what methods you need to include? You can spend time studying your old classes, of course. But wouldn&#8217;t you like to make your life a bit simpler? Of course you would.</p><p>Inheritance offers one solution. If you need a refresher on inheritance, you can read the fifth article in the classic Harry Potter OOP series: <a href="https://thepythoncodingstack.substack.com/p/python-oop-inheritance-5">&#8220;You Have Your Mother&#8217;s Eyes&#8221; &#8226; Inheritance in Python Classes</a>.</p><p>However, <code>TrackEvent</code> shouldn&#8217;t inherit from <code>FieldEvent</code> since a track event <strong>is not</strong> a field event. The same applies the other way around. These classes are siblings, so they can&#8217;t have a parent-child relationship.</p><p>Instead, they could both inherit from a common parent. So, let&#8217;s keep the <code>Event</code> class as a common parent for both <code>TrackEvent</code> and <code>FieldEvent</code>.</p><p>However, the only purpose of <code>Event</code> is to serve as a starting point for the two child classes. You no longer want a user to create instances of <code>Event</code> now that you have <code>TrackEvent</code> and <code>FieldEvent</code>. They should only create instances of <code>TrackEvent</code> or <code>FieldEvent</code>. How can you make this clear in your code and perhaps even prevent users from creating an instance of the parent class, <code>Event</code>?</p><h2><strong>Abstract Base Classes (ABCs)</strong></h2><p>The answer is Abstract Base Classes, often shortened to ABCs. The ABC acronym gives the impression these are as easy as ABC&#8212;they&#8217;re not, but there&#8217;s no reason they need to be difficult, either. The title of this article is also a reference to a rhyme my children used to sing when they were toddlers learning their ABC!</p><p>Let&#8217;s refresh your memory about different terms often used to describe the inheritance relationship between classes:</p><ul><li><p>You can refer to <em>parent class</em> and <em>child class</em>. The child class inherits from the parent class.</p></li><li><p>Or you can refer to <em>superclass</em> and <em>subclass</em>. The subclass inherits from the superclass. This is where the built-in <code>super()</code> gets its name.</p></li><li><p>Or you can refer to <em>base class</em> and <em>derived class</em>. The derived class inherits from the base class.</p></li></ul><p>Whatever terms you choose to use, they refer to the same things!</p><p>So, an ABC is a base class, since other classes are derived from it. That deals with the BC in ABC. And it&#8217;s abstract because you&#8217;re never going to create a concrete instance of this class.</p><p>You&#8217;re not meant to create an instance of an abstract base class and often you&#8217;ll be prevented from doing so. But you can use it to derive other classes.</p><p>Let&#8217;s turn <code>Event</code> into an abstract base class:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!aDtw!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!aDtw!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png 424w, https://substackcdn.com/image/fetch/$s_!aDtw!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png 848w, https://substackcdn.com/image/fetch/$s_!aDtw!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png 1272w, https://substackcdn.com/image/fetch/$s_!aDtw!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!aDtw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png" width="1236" height="1428" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1428,&quot;width&quot;:1236,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:150197,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.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_!aDtw!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png 424w, https://substackcdn.com/image/fetch/$s_!aDtw!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png 848w, https://substackcdn.com/image/fetch/$s_!aDtw!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png 1272w, https://substackcdn.com/image/fetch/$s_!aDtw!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17894280-7fd0-4ab9-a30c-bd575f76cfad_1236x1428.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#10</figcaption></figure></div><p>The changes from the previous version are highlighted. Let&#8217;s go through each change:</p><ul><li><p>From the <code>abc</code> module&#8212;and now you know what these letters stand for&#8212;you import <code>ABC</code> and <code>abstractmethod</code>. You&#8217;ll see both of these referred to and explained in the bullets below.</p></li><li><p>When you define the <code>Event</code> class, you include <code>ABC</code> as its base or parent class. When a class inherits from the <code>ABC</code> class, the class itself becomes an abstract base class. Anyone reading your code will immediately understand the role of this class.</p></li><li><p>You add the <code>@abstractmethod</code> decorator before defining <code>.finalise_results()</code> and you also remove the contents of this method. Since you can&#8217;t leave the body of a function or method blank, you include the <code>pass</code> statement as the method&#8217;s body. This method doesn&#8217;t do anything, but it&#8217;s there, and it&#8217;s marked as an abstract method. Let&#8217;s see what this means&#8230;</p></li></ul><p>Here&#8217;s what you&#8217;re effectively stating when you create this ABC with the <code>.finalise_results()</code> abstract method: Any class derived from the <code>Event</code> ABC <em>must</em> include a <code>.finalise_results()</code> method.</p><p>Let&#8217;s explore this by defining <code>TrackEvent</code> and <code>FieldEvent</code>. At first, you&#8217;ll keep them simple:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!6RhF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!6RhF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png 424w, https://substackcdn.com/image/fetch/$s_!6RhF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png 848w, https://substackcdn.com/image/fetch/$s_!6RhF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!6RhF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!6RhF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png" width="1290" height="1092" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1092,&quot;width&quot;:1290,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:58794,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.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_!6RhF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png 424w, https://substackcdn.com/image/fetch/$s_!6RhF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png 848w, https://substackcdn.com/image/fetch/$s_!6RhF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png 1272w, https://substackcdn.com/image/fetch/$s_!6RhF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F68484bd4-f624-4272-bbdb-2118e048fd53_1290x1092.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#11</figcaption></figure></div><p>You define the two new classes <code>TrackEvent</code> and <code>FieldEvent</code>. They inherit from <code>Event</code>, which is an abstract base class. You just include <code>pass</code> as the body of each class for now. This means that these classes inherit everything from the parent class and have no changes or additions. They&#8217;re identical to the parent class.</p><p>Note that you now use <code>TrackEvent</code> and <code>FieldEvent</code> to create instances for the 100m race and the long jump.</p><p>However, you get an error when you try to create these instances:</p><pre><code>Traceback (most recent call last):
  File ... line 53, in &lt;module&gt;
    track_100m = TrackEvent(
        &#8220;100m Sprint&#8221;,
        [bib_to_athlete[259], bib_to_athlete[161], bib_to_athlete[362]]
    )
TypeError: Can&#8217;t instantiate abstract class TrackEvent without
    an implementation for abstract method &#8216;finalise_results&#8217;</code></pre><p>The abstract base class includes the method <code>.finalise_results()</code>, which is marked as an abstract method. Python is expecting a concrete implementation of this method. Any class that inherits from the <code>Event</code> ABC <em>must</em> have a concrete implementation of this method. Let&#8217;s fix 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_!N95V!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!N95V!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.png 424w, https://substackcdn.com/image/fetch/$s_!N95V!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.png 848w, https://substackcdn.com/image/fetch/$s_!N95V!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.png 1272w, https://substackcdn.com/image/fetch/$s_!N95V!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!N95V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.png" width="1200" height="714" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/8570e821-7641-4f69-849b-b721016c8aff_1200x714.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:714,&quot;width&quot;:1200,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:58560,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.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_!N95V!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.png 424w, https://substackcdn.com/image/fetch/$s_!N95V!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.png 848w, https://substackcdn.com/image/fetch/$s_!N95V!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.png 1272w, https://substackcdn.com/image/fetch/$s_!N95V!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F8570e821-7641-4f69-849b-b721016c8aff_1200x714.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#12</figcaption></figure></div><p>In <code>TrackEvent</code>, you include the same code you had in the original <code>Event.finalise_results()</code> since this algorithm works well for track events where the smallest numbers (the fastest times) represent the best performances.</p><p>However, you pass <code>reverse=True</code> to <code>.sort()</code> in <code>FieldEvent.finalise_results()</code> since the largest numbers (longest distances) represent the best performances in this case.</p><p>You can now try these new classes on the 100m race results and the long jump results you used earlier:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!SX5o!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!SX5o!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png 424w, https://substackcdn.com/image/fetch/$s_!SX5o!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png 848w, https://substackcdn.com/image/fetch/$s_!SX5o!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png 1272w, https://substackcdn.com/image/fetch/$s_!SX5o!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!SX5o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png" width="1290" height="1302" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1302,&quot;width&quot;:1290,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:153184,&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://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.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_!SX5o!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png 424w, https://substackcdn.com/image/fetch/$s_!SX5o!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png 848w, https://substackcdn.com/image/fetch/$s_!SX5o!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png 1272w, https://substackcdn.com/image/fetch/$s_!SX5o!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56f618af-ff4a-4946-a2d1-7891e83d828a_1290x1302.png 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><figcaption class="image-caption">#13</figcaption></figure></div><p>You now use the new derived classes <code>TrackEvent</code> and <code>FieldEvent</code> in this code instead of <code>Event</code>. You also add two new printouts to separate the results.</p><p>Here&#8217;s the output now:</p><pre><code>100m Sprint Results:
Usain Bolt: 9.58
Carl Lewis: 9.86
Jesse Owens: 10.3
&#8203;
Long Jump Results:
Mike Powell: 8.95
Carl Lewis: 8.87</code></pre><p>The 100m results show the fastest times (smallest values) as the best performances. The long jump results show the longer jump (larger value) as the best performance. All as it should be!</p><h2><strong>Wind Readings and Breaking Ties</strong></h2><p>But there are more differences we need to account for. In some track and field events, the wind reading matters. In these events, if the wind reading is larger than 2.0 m/s, the results still stand but the performances cannot be used for official records.</p><p>But does this affect track events or field events? So should you account for this in the <code>TrackEvent</code> class or in the <code>FieldEvent</code> class?</p><p>It&#8217;s not so simple. Wind readings matter in some track events, but not all. And they also matter in some field events, but not all. So, you have a different subset of events to account for now. The 100m, 200m, 110m hurdles and 100m hurdles, which are all track events, are in the same category as the long jump and triple jump, which are field events.</p><p>But before we find a solution for this, here&#8217;s something else to mess things up even more. What happens when there&#8217;s a tie&#8212;when two athletes have the same performance value? The tie-breaking rules also depend on the event. Let&#8217;s ignore the track events here, since depending on what timing system is used, it&#8217;s either the officials who decide or the higher precision times from the automatic timing systems.</p><p>But what about the field events? In most of them, if there&#8217;s a tie, the next best performance is taken into account. However, the rules are different for the high jump and pole vault events where there&#8217;s a count back system used. Explaining the rules of track and field is not the purpose of this article, so I won&#8217;t!</p><p>So that&#8217;s yet another subset to consider: tie breaks in the vertical jumps are different from tie breaks in the horizontal jumps and throws.</p><p>How can we account for all these subsets of events?</p><h2><strong>To ABC or Not To ABC</strong></h2><p>There are always many solutions to the same problem. You can extend the idea of using ABCs to cater for all options. But the Venn diagram of which event falls under which category is a bit complicated in this case.</p><p>The 100m, 200m, 100m hurdles and 110m hurdles are all track events affected by wind readings. But the long jump and triple jump are also affected by wind readings but they&#8217;re field events. The discus and other throw events are field events&#8212;so the longest throw wins&#8212;but aren&#8217;t affected by high wind readings. And the long jump, triple jump, and the throws have a next-best jump/throw tie-breaking rule. But the pole vault and high jump are field events not affected by the wind but with different tie-breaking rules.</p><p>Are you still with me? Confused? Can you think of an abstract base class structure to account for all these combinations. It&#8217;s not impossible, but you&#8217;ll need several layers in the hierarchy.</p><p>Instead, I&#8217;ll explore a different route in a second article, which I&#8217;ll publish soon!</p><div><hr></div><p><em>The follow-up article will be part of</em> The Club <em>here at</em> The Python Coding Stack. <em>These are the articles for paid subscribers. So, if you&#8217;d like to read about a different way</em>&#8212;<em>arguably, a better way</em>&#8212;<em>of merging all these requirements into our classes,</em> <em><a href="https://www.thepythoncodingstack.com/subscribe">join</a></em><a href="https://www.thepythoncodingstack.com/subscribe"> The Club </a><em><a href="https://www.thepythoncodingstack.com/subscribe">by upgrading to a paid subscription</a></em>.</p><div><hr></div><h2><strong>Final Words for This Article &#8226; Ready for Part 2?</strong></h2><p>Inheritance is a great tool. And abstract base classes enable you to organise your hierarchies by creating common base classes for concrete classes you may need to define.</p><p>However, inheritance hierarchies can get quite complex. Since inheritance provides a tight coupling between classes, deep hierarchies can cause a bit of a headache.</p><p>Still, abstract base classes provide a great tool to make code cleaner, more readable, and more robust. In the follow-up to this article (coming soon), we&#8217;ll look at another tool you can use along with inheritance to solve these complex relationships. So <a href="https://www.thepythoncodingstack.com/subscribe">join </a><em><a href="https://www.thepythoncodingstack.com/subscribe">The Club</a></em> to carry on reading about the track and field classes and how mixins and composition can help manage the complexity.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!0Wu3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!0Wu3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg 424w, https://substackcdn.com/image/fetch/$s_!0Wu3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg 848w, https://substackcdn.com/image/fetch/$s_!0Wu3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!0Wu3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg 1456w" sizes="auto, 100vw"><img src="https://substackcdn.com/image/fetch/$s_!0Wu3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg" width="444" height="442.6125" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1276,&quot;width&quot;:1280,&quot;resizeWidth&quot;:444,&quot;bytes&quot;:482054,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/jpeg&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://www.thepythoncodingstack.com/i/177711190?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd298dff4-5bbe-4f31-aa26-2ef470ec3570_1280x1920.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_!0Wu3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg 424w, https://substackcdn.com/image/fetch/$s_!0Wu3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg 848w, https://substackcdn.com/image/fetch/$s_!0Wu3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!0Wu3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F17667c24-6f6e-4131-a845-49cdf0dbdb6c_1280x1276.jpeg 1456w" sizes="auto, 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 buttonBase-GK1x3M"><svg aria-hidden="true" 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" class="icon-noB79L"><g><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 buttonBase-GK1x3M"><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 icon-noB79L"><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><em>Image by <a href="https://pixabay.com/users/tianazz-18707913/?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=6296890">TianaZZ</a> from <a href="https://pixabay.com//?utm_source=link-attribution&amp;utm_medium=referral&amp;utm_campaign=image&amp;utm_content=6296890">Pixabay</a></em></p><div><hr></div><p><em>Code in this article uses Python 3.14</em></p><p><em>The code images used in this article are created using <a href="https://snappify.cello.so/f4AsFrwgwov">Snappify</a>.</em> <em>[Affiliate link]</em></p><p><em><strong><a href="https://www.thepythoncodingstack.com/subscribe">Join</a></strong></em><strong><a href="https://www.thepythoncodingstack.com/subscribe"> The Club</a></strong><em>, the exclusive area for paid subscribers for <a href="https://www.thepythoncodingstack.com/s/the-club">more Python posts</a>, videos, a members&#8217; forum, and more.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://www.thepythoncodingstack.com/subscribe?&quot;,&quot;text&quot;:&quot;Subscribe now&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://www.thepythoncodingstack.com/subscribe?"><span>Subscribe now</span></a></p><p><em>You can also support this publication by making a <a href="https://buy.stripe.com/00g3de2iGdgg4gg7su">one-off contribution of any amount you wish</a>.</em></p><p class="button-wrapper" data-attrs="{&quot;url&quot;:&quot;https://buy.stripe.com/00g3de2iGdgg4gg7su&quot;,&quot;text&quot;:&quot;Support The Python Coding Stack&quot;,&quot;action&quot;:null,&quot;class&quot;:null}" data-component-name="ButtonCreateButton"><a class="button primary" href="https://buy.stripe.com/00g3de2iGdgg4gg7su"><span>Support The Python Coding Stack</span></a></p><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com/">stephengruppetta.com</a></em></p><p>Further reading related to this article&#8217;s topic:</p><ul><li><p><a href="https://thepythoncodingstack.substack.com/p/python-oop-inheritance-5">&#8220;You Have Your Mother&#8217;s Eyes&#8221; &#8226; Inheritance in Python Classes</a></p></li><li><p> <a href="https://thepythoncodingstack.substack.com/p/whats-all-the-fuss-about-python-lambda-functions">What&#8217;s All the Fuss About &#8216;lambda&#8217; Functions in Python</a></p></li><li><p> <a href="https://www.thepythoncodingstack.com/p/the-key-to-the-key-parameter-in-python">The Key to the &#8216;key&#8217; Parameter in Python</a></p></li></ul><div><hr></div><h2>Appendix: Code Blocks</h2><h5>Code Block #1</h5><pre><code><code>class Athlete:
    def __init__(self, name, bib_number):
        self.name = name
        self.bib_number = bib_number
</code></code></pre><h5>Code Block #2</h5><pre><code><code># ...

list_of_athletes = [
    Athlete(&#8221;Carl Lewis&#8221;, 259),
    Athlete(&#8221;Jesse Owens&#8221;, 161),
    Athlete(&#8221;Usain Bolt&#8221;, 362),
    Athlete(&#8221;Mike Powell&#8221;, 412),
    Athlete(&#8221;Florence Griffith-Joyner&#8221;, 263),
    Athlete(&#8221;Allyson Felix&#8221;, 298),
    Athlete(&#8221;David Rudisha&#8221;, 177),
    # ...  Add more athletes as needed
]
</code></code></pre><h5>Code Block #3</h5><pre><code><code># ...

bib_to_athlete = {
    athlete.bib_number: athlete for athlete in list_of_athletes
}
</code></code></pre><h5>Code Block #4</h5><pre><code><code># ...

class Event:
    def __init__(self, event_name, participants):
        self.event_name = event_name
        self.participants = participants
        self.results = []
</code></code></pre><h5>Code Block #5</h5><pre><code><code>class Result:
    def __init__(self, athlete, performance):
        self.athlete = athlete
        self.performance = performance

# ...
</code></code></pre><h5>Code Block #6</h5><pre><code><code># ...

class Event:
    # ...
        
    def add_result(self, bib_number, performance):
        athlete = bib_to_athlete.get(bib_number)
        if not athlete or athlete not in self.participants:
            raise ValueError(f&#8221;Invalid bib number {bib_number}&#8221;)
        self.results.append(
            Result(athlete, performance)
        )
</code></code></pre><h5>Code Block #7</h5><pre><code><code># ...

class Event:
    # ...
    
    def finalise_results(self):
        self.results.sort(key=lambda item: item.performance)
</code></code></pre><h5>Code Block #8</h5><pre><code><code># ...

track_100m = Event(
    &#8220;100m Sprint&#8221;,
    [bib_to_athlete[259], bib_to_athlete[161], bib_to_athlete[362]]
)

track_100m.add_result(259, 9.86)
track_100m.add_result(161, 10.3)
track_100m.add_result(362, 9.58)
track_100m.finalise_results()

for result in track_100m.results:
    print(f&#8221;{result.athlete.name}: {result.performance}&#8221;)
</code></code></pre><h5>Code Block #9</h5><pre><code><code># ...

field_long_jump = Event(
    &#8220;Long Jump&#8221;,
    [bib_to_athlete[412], bib_to_athlete[259]]
)

field_long_jump.add_result(412, 8.95)
field_long_jump.add_result(259, 8.87)
field_long_jump.finalise_results()

for result in field_long_jump.results:
    print(f&#8221;{result.athlete.name}: {result.performance}&#8221;)
</code></code></pre><h5>Code Block #10</h5><pre><code><code>from abc import ABC, abstractmethod

class Result:
    def __init__(self, athlete, performance):
        self.athlete = athlete
        self.performance = performance

class Athlete:
    def __init__(self, name, bib_number):
        self.name = name
        self.bib_number = bib_number

class Event(ABC):
    def __init__(self, event_name, participants):
        self.event_name = event_name
        self.participants = participants
        self.results = []

    def add_result(self, bib_number, performance):
        athlete = bib_to_athlete.get(bib_number)
        if not athlete or athlete not in self.participants:
            raise ValueError(f&#8221;Invalid bib number {bib_number}&#8221;)
        self.results.append(
            Result(athlete, performance)
        )
    
    @abstractmethod
    def finalise_results(self):
        pass

# ...
</code></code></pre><h5>Code Block #11</h5><pre><code><code># ...

class TrackEvent(Event):
    pass

class FieldEvent(Event):
    pass

# ...

track_100m = TrackEvent(
    &#8220;100m Sprint&#8221;,
    [bib_to_athlete[259], bib_to_athlete[161], bib_to_athlete[362]]
)

# ...

field_long_jump = FieldEvent(
    &#8220;Long Jump&#8221;,
    [bib_to_athlete[412], bib_to_athlete[259]]
)

# ...
</code></code></pre><h5>Code Block #12</h5><pre><code><code># ...

class TrackEvent(Event):
    def finalise_results(self):
        self.results.sort(key=lambda item: item.performance)

class FieldEvent(Event):
    def finalise_results(self):
        self.results.sort(
            key=lambda item: item.performance,
            reverse=True,
        )

# ...
</code></code></pre><h5>Code Block #13</h5><pre><code><code># ...

track_100m = TrackEvent(
    &#8220;100m Sprint&#8221;,
    [bib_to_athlete[259], bib_to_athlete[161], bib_to_athlete[362]]
)

track_100m.add_result(259, 9.86)
track_100m.add_result(161, 10.3)
track_100m.add_result(362, 9.58)
track_100m.finalise_results()

print(&#8221;100m Sprint Results:&#8221;)
for result in track_100m.results:
    print(f&#8221;{result.athlete.name}: {result.performance}&#8221;)

field_long_jump = FieldEvent(
    &#8220;Long Jump&#8221;,
    [bib_to_athlete[412], bib_to_athlete[259]]
)

field_long_jump.add_result(412, 8.95)
field_long_jump.add_result(259, 8.87)
field_long_jump.finalise_results()

print(&#8221;\nLong Jump Results:&#8221;)
for result in field_long_jump.results:
    print(f&#8221;{result.athlete.name}: {result.performance}&#8221;)
</code></code></pre><div><hr></div><p><em>For more Python resources, you can also visit</em> <em><a href="https://realpython.com?utm_source=the-python-coding-stack">Real Python</a>&#8212;you may even stumble on one of my own articles or courses there!</em></p><p><em>Also, are you interested in technical writing? You&#8217;d like to make your own writing more narrative, more engaging, more memorable? Have a look at</em> <em><a href="http://stephengruppetta.com/breaking-the-rules">Breaking the Rules</a></em>.</p><p><em>And you can find out more about me at</em> <em><a href="https://stephengruppetta.com/">stephengruppetta.com</a></em></p>]]></content:encoded></item><item><title><![CDATA[Impostors • How Even The Python Docs Get This Wrong*]]></title><description><![CDATA[*Spoiler alert: The docs don&#8217;t really get it &#8220;wrong&#8221;]]></description><link>https://www.thepythoncodingstack.com/p/impostors-how-even-the-python-docs</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/impostors-how-even-the-python-docs</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Sun, 26 Oct 2025 08:52:48 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9627d400-da61-4566-8d63-602fabc3b532_840x600.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Can you spot all the errors in the following paragraph? There are several:</p><blockquote><p>Two functions that enable you to work effectively with loops in Python are <code>zip()</code> and <code>enumerate()</code>. Along with the <code>range()</code> function, they&#8217;re some of the most common tools you&#8217;ll see in <code>for</code> loops. And when you master them, you can start exploring the functions in the <code>itertools</code> module.</p></blockquote><p>The correct number of errors in this text is either four or zero. Confused? I don&#8217;t blame you. And here&#8217;s a bit more confusion for you. It doesn&#8217;t matter either way.</p><p>Let&#8217;s talk about impostors in Python.</p><p>It&#8217;s likely that one of the first examples you saw when learning about <code>for</code> loops used the <code>range()</code> function as part of the <code>for</code> statement.</p><p>But you were fooled. That example, whichever one it was, didn&#8217;t do such a thing.</p>
      <p>
          <a href="https://www.thepythoncodingstack.com/p/impostors-how-even-the-python-docs">
              Read more
          </a>
      </p>
   ]]></content:encoded></item><item><title><![CDATA[Are Tuples More Like Lists or Strings? And Why We Don't Really Care]]></title><description><![CDATA[This post is not about tuples.]]></description><link>https://www.thepythoncodingstack.com/p/are-tuples-more-like-lists-or-strings</link><guid isPermaLink="false">https://www.thepythoncodingstack.com/p/are-tuples-more-like-lists-or-strings</guid><dc:creator><![CDATA[Stephen Gruppetta]]></dc:creator><pubDate>Mon, 20 Oct 2025 10:02:15 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/d019e417-1f45-4c0c-924d-9fde8950e81c_840x600.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This post is not about tuples. It&#8217;s not about lists or strings, either. It&#8217;s about Python, about its philosophy when dealing with data types, about how you should think about data types when coding in Python.</p><p>Tuples are usually introduced to Python learners after lists and strings. They&#8217;re almost always described as &#8220;like lists, but a bit different&#8221;.</p><p>And that&#8217;s not a bad thing. I say similar things when I introduce tuples to students. But then, fast-forward a few levels of proficiency, and I&#8217;m having different discussions with students. Are tuples like lists? Are they like strings? But the point is that those questions don&#8217;t really make sense. Other questions matter a lot more in Python. Let&#8217;s explore.</p><div><hr></div><p>This is the first post in <em>The Club</em>, so allow me a word or three before getting back to tuples. I sent out an email last week about the new chapter in <em>The Python Coding Stack</em>. Paid subscribers are now members of <em>The Club</em>. I&#8217;ll write more frequent, shorter posts for <em>The Club</em>, sometimes accompanied by short videos (videos will complement the text, they won&#8217;t replace it). And all the other stuff: forum, Q&amp;As, code reviews, and more.</p><p>I recall when I first started <em>The Python Coding Stack</em>, I agonised over what the first article should be about. It&#8217;s the first. It should be special. But then I just published about whatever topic I was thinking about at the time.</p><p>I took the same route when writing the first post on <em>The Club</em> &#8211; this one. And I&#8217;ll do this every week. I&#8217;ll write about whatever comes up in my coding, in my teaching, whatever I think you&#8217;ll find interesting. Or send me your questions, and they may inspire me to write about them. Don&#8217;t be shy.</p><p>Now back to tuples.</p><div><hr></div><p>A long time ago, on a social media platform (now) far, far away, I wrote a series of threads exploring real-world objects from the perspective of Python data types. I recall one of them was about a row of houses. Would a dictionary, or a list, or a tuple, or something else be the &#8220;ideal data structure&#8221; if I wanted to represent this row of houses as a data type? But there was another question I needed to ask first.</p>
      <p>
          <a href="https://www.thepythoncodingstack.com/p/are-tuples-more-like-lists-or-strings">
              Read more
          </a>
      </p>
   ]]></content:encoded></item></channel></rss>