<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aaron Maxwell</title>
    <description>The latest articles on DEV Community by Aaron Maxwell (@aaronmaxwell).</description>
    <link>https://dev.to/aaronmaxwell</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3908175%2F84bc7da8-4df4-4cb9-aef1-95a5d3ecfc52.jpg</url>
      <title>DEV Community: Aaron Maxwell</title>
      <link>https://dev.to/aaronmaxwell</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aaronmaxwell"/>
    <language>en</language>
    <item>
      <title>If You Are Overwhelmed, It's Because You Are Not Setting Boundaries</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Sun, 31 May 2026 14:09:08 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/if-you-are-overwhelmed-its-because-you-are-not-setting-boundaries-373g</link>
      <guid>https://dev.to/aaronmaxwell/if-you-are-overwhelmed-its-because-you-are-not-setting-boundaries-373g</guid>
      <description>&lt;p&gt;Do any of the following describe you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Working longer hours than you expected&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agreeing to things you do not want to agree to&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Accumulating technical debt, because new tasks eat up all your time&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Feeling manipulated into taking on responsibilities you do not want&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Feeling pressured to accept deadlines you do not think are realistic&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Getting burnt out, without any clear sustainable solution&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Feeling disempowered, like you do not have the autonomy and self-direction you expected you would have&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If so, you are in good company. Many of my colleagues, and I would say many people who work in technology, have the same issue.&lt;/p&gt;

&lt;p&gt;I could write thousands of words on the root cause of this, and the strategy of what to do about it.&lt;/p&gt;

&lt;p&gt;But instead, I will cut to the chase:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The reason you have these problems is that you do not know how to set boundaries properly, in your interactions at work, and without causing negative consequences.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The solution is to learn HOW to safely set those boundaries, and then set them.&lt;/p&gt;

&lt;p&gt;To do this, get the book titled:&lt;/p&gt;

&lt;p&gt;"When I Say No, I Feel Guilty"&lt;/p&gt;

&lt;p&gt;Written by Manuel J. Smith. You can find it anywhere, but make sure you buy it new, not used (it is extremely cheap). And buy the print version, not digital or audiobook.&lt;/p&gt;

&lt;p&gt;Skip the front matter and chapter 1; go directly to the first page of chapter 2. Read chapters 2, 3 and 4. They will teach you something called the "Broken Record" technique.&lt;/p&gt;

&lt;p&gt;Then pause reading, and write in a journal (paper or digital) about how you can use Broken Record in &lt;em&gt;specific&lt;/em&gt; situations at work.&lt;/p&gt;

&lt;p&gt;For extra impact: over the next week, write a quick note in that journal every day, about how you were able to use Broken Record, and what the results were; AND any opportunities that day where you could have used Broken Record, but did not realize it in the moment. This will help you use it when that situation repeats.&lt;/p&gt;

&lt;p&gt;If you do this, you will have a lifelong skill that will increase your dominion over your own life, and help you avoid feeling overwhelmed in the future.&lt;/p&gt;

</description>
      <category>career</category>
      <category>discuss</category>
      <category>mentalhealth</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How To "Market" Yourself As A Tech Pro</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Fri, 22 May 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/how-to-market-yourself-as-a-tech-pro-32p9</link>
      <guid>https://dev.to/aaronmaxwell/how-to-market-yourself-as-a-tech-pro-32p9</guid>
      <description>&lt;p&gt;As you build your technical skills, your next step is to create your own open-source software project, to demonstrate those skills to the world.&lt;/p&gt;

&lt;p&gt;Ideally it will be a project that is fun for you to create, and also will teach you about a new technology you are interested in...&lt;/p&gt;

&lt;p&gt;But its primary purpose is to be &lt;em&gt;marketing asset&lt;/em&gt;. An asset that is marketing YOU.&lt;/p&gt;

&lt;p&gt;I call this your &lt;em&gt;Artifact&lt;/em&gt;. Your Artifact is a dynamic marketing asset which efficiently signals your elite status to the job market, and attracts the opportunities you want.&lt;/p&gt;

&lt;p&gt;Every word of this matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It is an &lt;em&gt;asset&lt;/em&gt;. Meaning something you create, which generates more of what you want, as a side effect of its existence.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is a &lt;em&gt;marketing&lt;/em&gt; asset. Its purpose is to market you. It is a tool for professional self-promotion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It is &lt;em&gt;dynamic&lt;/em&gt;. As technology and the world evolves, you refine your Artifact to adapt to new job-market conditions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It &lt;em&gt;signals&lt;/em&gt; your value. It demonstrates your expertise, communicates your skills, and broadcasts your value to the job market. As your goals change (and you learn to think bigger for yourself), you pivot the Artifact to signal differently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It signals &lt;em&gt;efficiently&lt;/em&gt;. What your Artifact communicates about you is communicated immediately. It is instantly believed with little or no skepticism. Just like an author of a book is assumed to be an expert in that book’s topic, so your Artifact creates instant and powerful first impressions of you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It signals &lt;em&gt;status&lt;/em&gt;. Your professional status, your industry reputation, and the esteem in which others at the top of your profession perceive you.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It &lt;em&gt;attracts&lt;/em&gt; the opportunities, the professional relationships, and ultimately the career you want.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your Artifact takes the form of an ongoing project. This Artifact can be&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A software tool, used by your peers to do their work&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A software library, used by your peers when they write code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A web application, useful to people in your domain of technology&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It can also be a book, though that is much harder (&lt;a href="https://powerfulpython.com/book/" rel="noopener noreferrer"&gt;speaking from experience&lt;/a&gt;). I recommend you do one of the above first.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Creating your Artifact does NOT need to be difficult, or require a lot of work. The notion that success can only come from extreme exertion is a limiting belief. The career-boosting results of your Artifact are largely independent of the effort and time you put into it.&lt;/p&gt;

&lt;p&gt;It's more of a mindset. Asking yourself: what Artifact can you create, that will attract the opportunities you want?&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>career</category>
      <category>marketing</category>
      <category>opensource</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>First Principles</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Wed, 20 May 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/first-principles-1n1m</link>
      <guid>https://dev.to/aaronmaxwell/first-principles-1n1m</guid>
      <description>&lt;p&gt;Every domain of human activity has its own &lt;em&gt;first principles&lt;/em&gt;. These are the foundational concepts, distinctions, ideas, and mental models upon which that domain is based.&lt;/p&gt;

&lt;p&gt;And in my experience, the most useful first principles are not generic and hand-wavy. Instead, they are precise and specific.&lt;/p&gt;

&lt;p&gt;One example: Python's "function object" abstraction.&lt;/p&gt;

&lt;p&gt;In Python, functions are objects. That means you can store them in a variable. Like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; def praise(name):
...     print(f"{name} is tall and handsome!")

&amp;gt;&amp;gt;&amp;gt; describe = praise

&amp;gt;&amp;gt;&amp;gt; describe("Aaron")
Aaron is tall and handsome!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This has some big implications. You can write a function that creates and returns a different function. You can pass functions around just like you might pass around an int or a list or an instance of a class; as far as Python is concerned, a function is just another value.&lt;/p&gt;

&lt;p&gt;That lets you do some very powerful things.&lt;/p&gt;

&lt;p&gt;One example: the Strategy design pattern.&lt;/p&gt;

&lt;p&gt;Do you remember this one?  It lets you select an algorithm at runtime. And in most languages, you need to write a special class with a special method to make it work. But in Python, you can just pass a function object instead. Like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; numbers = [7, -2, 3, 12, -5]

&amp;gt;&amp;gt;&amp;gt; # Sort the numbers.
&amp;gt;&amp;gt;&amp;gt; sorted(numbers)
[-5, -2, 3, 7, 12]

&amp;gt;&amp;gt;&amp;gt; # Sort them by absolute value.
&amp;gt;&amp;gt;&amp;gt; sorted(numbers, key=abs)
[-2, 3, -5, 7, 12]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the last line, where it says "key=abs"? Notice there is no open parentheses after "abs". You are passing in the "abs" function, not calling it.&lt;/p&gt;

&lt;p&gt;And this is without even opening the metaprogramming can of worms, filled with vibrantly wriggling features like decorators.&lt;/p&gt;

&lt;p&gt;Again, this function-object thing is just ONE of the first principles of programming in Python. There are many more; other languages and technologies have their own, uniquely valuable first principles too. And it goes far above the language level, to the system design level and beyond.&lt;/p&gt;

&lt;p&gt;When you learn to recognize, leverage and apply first principles in your own work, you find you can do things you just couldn't do before.&lt;/p&gt;

&lt;p&gt;If that doesn't give you an unfair advantage in this frenetic age of AI, setting you apart from the drooling vibe coders, then nothing will.&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>learning</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Is Python High Level Or Low Level?</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Mon, 18 May 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/is-python-high-level-or-low-level-d73</link>
      <guid>https://dev.to/aaronmaxwell/is-python-high-level-or-low-level-d73</guid>
      <description>&lt;p&gt;Imagine you need to fill a list with square numbers - or more complex objects, but we'll just use square numbers to keep it simple. Here's one way to do it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;MAX_ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAX_ROOT&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Does the job, and much easier to follow than the C version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="cp"&gt;#define MAX_VALUE 100
&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MAX_VALUE&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;MAX_VALUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;MAX_VALUE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%d %d&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What makes it easier to follow? Several things, which I would summarize as: "the Python code is higher level".&lt;/p&gt;

&lt;p&gt;'Higher Level' means it abstracts over details of HOW to accomplish what you want... so you focus more on specifying WHAT you want, and the language figures out how to make it happen.&lt;/p&gt;

&lt;p&gt;But we can go higher level than this. For example, a list comprehension:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAX_ROOT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is more 'declarative', which is one way to make a language higher level. You design the language so you can declare what you want, rather than spell out how to assemble it.&lt;/p&gt;

&lt;p&gt;But what if you want to create your own high-level, declarative syntax? Not a list comprehension, but something else entirely?&lt;/p&gt;

&lt;p&gt;In fact, Python provides a way to do this:&lt;/p&gt;

&lt;p&gt;OOP.&lt;/p&gt;

&lt;p&gt;This may be surprising. You know the benefits of OOP already, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code becomes more reusable&lt;/li&gt;
&lt;li&gt;More organized, so your code is easier to reason about&lt;/li&gt;
&lt;li&gt;More encapsulated, thus de-inter-twining the logic&lt;/li&gt;
&lt;li&gt;Code is more testable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But there is one underappreciated benefit of OOP. Which is that - when you do it right - you can make your code more high level.&lt;/p&gt;

&lt;p&gt;For example, this class that represents a range of dates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DateRange&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;End date &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; must be after start date &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__contains__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__len__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it thusly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from datetime import date
&amp;gt;&amp;gt;&amp;gt; date_range = DateRange(date(2050, 3, 1), date(2050, 3, 15))
&amp;gt;&amp;gt;&amp;gt; len(date_range)
15
&amp;gt;&amp;gt;&amp;gt; date(2050, 3, 10) in date_range
True
&amp;gt;&amp;gt;&amp;gt; date(2050, 7, 1) in date_range
False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do you see how this abstraction called DateRange is higher level than mucking about with datetime.date() objects? That it is cleaner, which means it is easier to reason about; and common operations are encapsulated in simple methods, some of which even merge with the baked-in Python syntax.&lt;/p&gt;

&lt;p&gt;You can extend these ideas further, for example to create domain-specific languages. Like the filtering in square brackets that Pandas provides for DataFrames:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read_csv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;/path/to/big/file.csv&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And even if you have been writing classes in Python for years...&lt;/p&gt;

&lt;p&gt;Consider there may be more to OOP than you realize. Especially when writing high-quality, engineering-grade code you are proud of.&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>computerscience</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Dark Python Patterns</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Sat, 16 May 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/dark-python-patterns-8lo</link>
      <guid>https://dev.to/aaronmaxwell/dark-python-patterns-8lo</guid>
      <description>&lt;p&gt;Here are some terrible ideas you should avoid at all costs:&lt;/p&gt;

&lt;h2&gt;
  
  
  Import Everything
&lt;/h2&gt;

&lt;p&gt;Avert your eyes from this dangerous code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;somelib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The "import *" will import EVERYTHING contained in that module, and dump it right in your current namespace.&lt;/p&gt;

&lt;p&gt;What makes it dangerous is that you won't know there is any problem right away. The problem comes when somelib, or even your own code, gets updated...&lt;/p&gt;

&lt;p&gt;Weeks, months, years later...&lt;/p&gt;

&lt;p&gt;And suddenly you have a namespace collision that breaks your code, in the most confusing way possible. This create bugs that take ages to even figure out what is going on.&lt;/p&gt;

&lt;p&gt;Better: write "import somelib", or "import somelib as sl" (or some other short, handy abbreviation).&lt;/p&gt;

&lt;p&gt;That makes all the components in somelib available, safely contained in their own namespace.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blanket Except Clause
&lt;/h2&gt;

&lt;p&gt;Look away, from the most self-destructive code a Python developer can write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="nf"&gt;do_something&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
   &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What it does is execute the code in the try block.&lt;/p&gt;

&lt;p&gt;And if an error is raised - ANY exception whatsoever...&lt;/p&gt;

&lt;p&gt;You won't know. You can't know. Until it's too late.&lt;/p&gt;

&lt;p&gt;Because the "except: pass" will not only silently suppresses the exception.  It will hide from you the fact that there was an error AT ALL.&lt;/p&gt;

&lt;p&gt;It does not just hide normal exceptions, like TypeError if you accidently add an integer to a string. Or ValueError, if you convert a string like "not a number" into an int(). If you mis-type a variable name? That's a NameError. And it is COMPLETELY HIDDEN by this diabolical dark pattern. Creating the worst kind of bug, that is almost impossible to detect in development, and will wreak mayhem in production.&lt;/p&gt;

&lt;p&gt;Better: pin-point the except clause to the specific exception type you want to ignore. For example, "except ValueError: pass".&lt;/p&gt;

&lt;p&gt;Or if that is not appropriate, at least call "logging.exception()" in the except block. Look that up; it gives you a full stack trace in the logs.&lt;/p&gt;

&lt;p&gt;Those are two dark Python patterns you should strike from your mind, so you never even think to do them.&lt;/p&gt;

&lt;p&gt;Have you found other dark Python patterns? Comment and tell me.&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>coding</category>
      <category>python</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>So Does AI Boost Coding Speed Or Not?</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Thu, 14 May 2026 14:45:00 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/so-does-ai-boost-coding-speed-or-not-oh</link>
      <guid>https://dev.to/aaronmaxwell/so-does-ai-boost-coding-speed-or-not-oh</guid>
      <description>&lt;p&gt;Marc Andreessen, a former revolutionary software engineer and now venture capitalist at Andreessen Horowitz (aka a16z), said this in a recent interview:&lt;/p&gt;

&lt;p&gt;"At our leading edge companies, estimates are the leading edge programmers are like 20x more productive than they were a year ago. It's like the most dramatic increase in programmer productivity in like ever."&lt;/p&gt;

&lt;p&gt;He's not the only respectable voice claiming this. Silicon Valley veteran Naval Ravikant, Brian Chesky (founder of AirBNB), and many other credible folks have made similar claims recently. And this is ignoring the less-credible claims of people who run AI companies.&lt;/p&gt;

&lt;p&gt;So is this 20X thing real?&lt;/p&gt;

&lt;p&gt;Or even 10X, 5X, maybe 2X?&lt;/p&gt;

&lt;p&gt;I think it only makes sense to look at long-term productivity, over a time scale of a year or more.&lt;/p&gt;

&lt;p&gt;So "20X" means that an individual, or a team, gets 20 years of pre-AI work done in a single year. Because if the long-term increase falls short of that, it's not really 20X, is it?&lt;/p&gt;

&lt;p&gt;And if you look for verifiable, objectively measurable evidence of those 20X (or 10X or 2X) productivity gains...&lt;/p&gt;

&lt;p&gt;Well, there just does not seem to be any.&lt;/p&gt;

&lt;p&gt;That does not mean it is not happening. Maybe I just do not know about it. If you know of an example, tell me, please.&lt;/p&gt;

&lt;p&gt;But it seems like there should be at least one clear, widely-recognized, and uncontested example by now, if that 20X (or 10X, 2X, etc.) claim is true.&lt;/p&gt;

&lt;p&gt;What I think is happening:&lt;/p&gt;

&lt;p&gt;AI tools speed up development in proportion to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your baseline of software development expertise,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How well-characterized the problem is among open-source codebases, and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your ability to evaluate the quality of the AI tool's output.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for certain particular tasks, that can certainly 2X, 10X, even 20X productivity.&lt;/p&gt;

&lt;p&gt;A good example from my own experience: configuring a Django web service that used nginx, reversed-proxied into gunicorn (which is a Python-specific webapp server), and integrating another tool called uvicorn (with a "v") to enable websockets, all interfacing with the configuration of something called ASGI in the Django config.&lt;/p&gt;

&lt;p&gt;Don't worry about what all those words mean.&lt;/p&gt;

&lt;p&gt;The point is that it was a realistic, complex, production-grade task.&lt;/p&gt;

&lt;p&gt;And the way I would have done it before LLMs is to spend three days reading the manuals of nginx, gunicorn, uvicorn and Django in detail, until I figured out how to configure these completely separate systems to work gracefully together.&lt;/p&gt;

&lt;p&gt;Instead, I wrote a prompt to ChatGPT about what I wanted, and had a production-ready solution in an hour. 1 hour, versus over 20 hours; a true and objective 20X boost in productivity.&lt;/p&gt;

&lt;p&gt;But that was just one task. One step of many to creating, refining and deploying this complex web application.&lt;/p&gt;

&lt;p&gt;I am increasingly convinced that those who claim 10X and 20X boosts to development productivity from AI are incorrectly extrapolating one boosted experience to their entire work year.&lt;/p&gt;

&lt;p&gt;Again, if you know of a credible, objectively verifiable exception, please tell me.&lt;/p&gt;

&lt;p&gt;In the meantime, the best strategy, in my view:&lt;/p&gt;

&lt;p&gt;Continue to invest in your software development/engineering skills. I.e. your ability to write great software in the first place.&lt;/p&gt;

&lt;p&gt;That way, whatever AI does or does not do in the coming months and years, you are positioned to excel and reap juicy rewards.&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Deterministic AI</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Sun, 10 May 2026 13:45:00 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/deterministic-ai-423h</link>
      <guid>https://dev.to/aaronmaxwell/deterministic-ai-423h</guid>
      <description>&lt;p&gt;The enthusiasm around AI has been focused on large language models for years now. For quite a few folks, this is their first real experience with AI at all. And I am sure you have noticed something:&lt;/p&gt;

&lt;p&gt;LLMs are non-deterministic.&lt;/p&gt;

&lt;p&gt;In other words, repeated invocations of the algorithm with the same inputs typically produces different outputs.&lt;/p&gt;

&lt;p&gt;You can demonstrate this yourself. Open a chat AI tool in two incognito tabs, asking it a substantial prompt like "explain LLMs to me", and you will see the responses are different.&lt;/p&gt;

&lt;p&gt;With all the noise about generative AI like this in the past 5 years, it's easy to forget there is a whole universe of AI that is completely deterministic.&lt;/p&gt;

&lt;p&gt;The simplest example is linear regression.&lt;/p&gt;

&lt;p&gt;Lots of great info about this online, so I will not explain it here. But when someone asked me recently how to start learning AI - not just how to use AI tools, but actually understand AI from first principles - my suggestion was that he start by learning linear regression. It is tremendously useful in the real world today, and is simple enough that you can actually grok it without a PhD.&lt;/p&gt;

&lt;p&gt;The relevant fact about linear regression here:&lt;/p&gt;

&lt;p&gt;It is deterministic.&lt;/p&gt;

&lt;p&gt;The nuance is that some algorithms used to train linear regression - for example, gradient descent - deliberately inject randomness, because it is useful to do so.&lt;/p&gt;

&lt;p&gt;But once trained, linear regression models are completely deterministic. Every time you stuff the same input into one, the exact same output comes out.&lt;/p&gt;

&lt;p&gt;This has implications for the software systems we design.&lt;/p&gt;

&lt;p&gt;When a program needs an AI component, and you are able to use a deterministic algorithm:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can write unit tests and have a good time doing it.&lt;/li&gt;
&lt;li&gt;QA will have a much easier time nailing down any issues and making them reproducible (and thus much easier to fix).&lt;/li&gt;
&lt;li&gt;You won't have bizarre surprising behavior pop up in production as often.&lt;/li&gt;
&lt;li&gt;That part of the software system will behave in more consistent and understandable ways.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of course, if your application actually needs an LLM - or any other form of nondeterministic AI - then that's what you have to use. But if and when you have a choice, these are some things to think about.&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;P.S. When we say "LLMs are non-deterministic", that is technically a lie. It is more correct to say that LLMs are chaotic, in the mathematical sense of sensitive dependence on initial conditions; and on top of that, deliberate randomness is injected into how the LLM is applied, via the temperature parameter.&lt;/p&gt;

&lt;p&gt;But nobody understands all that. "Non-deterministic" does describe how LLM-based tools feel to people at the UX level, so I'll go with the crowd and use that term.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>llm</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>"Prime Testable" Code</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Sat, 09 May 2026 16:30:00 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/prime-testable-code-2cmd</link>
      <guid>https://dev.to/aaronmaxwell/prime-testable-code-2cmd</guid>
      <description>&lt;p&gt;What is the EASIEST Python code to test?&lt;/p&gt;

&lt;p&gt;Because writing unit tests is a superpower. It's great. Completely changes what you are capable of as a developer.&lt;/p&gt;

&lt;p&gt;Think of the last time you wrote an incredible piece of software... Literally surprising yourself with the beauty, the power, the sheer awesomeness of what you created.&lt;/p&gt;

&lt;p&gt;Writing unit tests make that feeling COMMON. You want to live that life.&lt;/p&gt;

&lt;p&gt;And part of using them effectively is learning how to make your code &lt;em&gt;easily testable&lt;/em&gt;. Out of the bulging universe of different choices for how to organize your code, choosing a way that makes high-impact, high-value tests easiest to write.&lt;/p&gt;

&lt;p&gt;In other words, working smarter, not harder.&lt;/p&gt;

&lt;p&gt;And while easy-to-test code is not always practical... It often is. You want to learn how to discern.&lt;/p&gt;

&lt;p&gt;The easiest code to test is what I call "prime testable" code, which has these two qualities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The code has no side effects, and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The code is deterministic.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'll explain:&lt;/p&gt;

&lt;p&gt;"No side effects" means that the code does some calculation or look-up, and returns a value... and that's it.&lt;/p&gt;

&lt;p&gt;It does NOT write to a database, create a file, or open your garage door. Those are all side effects.&lt;/p&gt;

&lt;p&gt;"Deterministic" means that it ALWAYS returns the same outputs, when you feed it the same inputs.&lt;/p&gt;

&lt;p&gt;Calculating the 217th prime number, or splitting a string into a list of words, or sorting a sequence - these are all deterministic.&lt;/p&gt;

&lt;p&gt;Fetching the number of visitors to your website in the past hour? Not deterministic at all.&lt;/p&gt;

&lt;p&gt;If a function or method you write has these two qualities, it is prime testable. And it is the easiest thing in the world to quickly write powerful tests for.&lt;/p&gt;

&lt;p&gt;Which means you will write more tests for it. Which means your life is BETTER.&lt;/p&gt;

&lt;p&gt;Often, if you have some code that must be non-deterministic or must have side effects - and every real program has code like that - then you can spin out the prime-testable part in a separate function, method or class.&lt;/p&gt;

&lt;p&gt;Shove as much of your program's error-prone complexity as you can into that spun-out component. Test the heck out of it. Then any code using it will be reliable and solid.&lt;/p&gt;

&lt;p&gt;If you are struggling to write a test, step back and see if you can organize your application code differently. The more of your code you stuff into prime-testable methods and functions, the easier the tests will flow.&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>codequality</category>
      <category>productivity</category>
      <category>python</category>
      <category>testing</category>
    </item>
    <item>
      <title>Emergent Abstractions</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Fri, 08 May 2026 14:28:19 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/emergent-abstractions-2ghd</link>
      <guid>https://dev.to/aaronmaxwell/emergent-abstractions-2ghd</guid>
      <description>&lt;p&gt;Here's an interesting class, from a program I wrote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;MINYEAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;MAXYEAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DateInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;BEGINNING_OF_TIME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MINYEAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;END_OF_TIME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MAXYEAR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BEGINNING_OF_TIME&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;END_OF_TIME&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Start date &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; must not be after end date &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;

    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BEGINNING_OF_TIME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;END_OF_TIME&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__contains__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__iter__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;num_days&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;end&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_days&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;days&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; interval = DateInterval(date(2050, 1, 1), date(2059, 12, 31))
&amp;gt;&amp;gt;&amp;gt; some_day = date(2050, 5, 3)
&amp;gt;&amp;gt;&amp;gt; another_day = date(2060, 1, 1)
&amp;gt;&amp;gt;&amp;gt;
&amp;gt;&amp;gt;&amp;gt; some_day in interval
True
&amp;gt;&amp;gt;&amp;gt; another_day in interval
False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Classes are abstractions. Some of these abstractions are concrete nouns. If you wrote code for an online shopping website, you may have classes named&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Customer&lt;/li&gt;
&lt;li&gt;Product&lt;/li&gt;
&lt;li&gt;Coupon&lt;/li&gt;
&lt;li&gt;ShoppingCart&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Or your role-playing game may have classes for&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Player&lt;/li&gt;
&lt;li&gt;HealingPotion&lt;/li&gt;
&lt;li&gt;Goblin (which inherits from Monster)&lt;/li&gt;
&lt;li&gt;Sword (which inherits from Weapon)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And so on.&lt;/p&gt;

&lt;p&gt;Notice these classes are all something you can visualize. Each is something you can at least imagine to be real, that you could pick up, move around, put in a wheelbarrow.&lt;/p&gt;

&lt;p&gt;But other abstractions are, well, &lt;em&gt;abstract&lt;/em&gt;. Like DateInterval. Have you ever held a DateInterval in your hand? Could you put THAT in a wheelbarrow? No way. It's a pure abstraction, an idea, that only exists and only makes sense inside the ethereal context of a running program.&lt;/p&gt;

&lt;p&gt;I find that in real software, many of my most useful classes are non-tangible in this same way.&lt;/p&gt;

&lt;p&gt;And perhaps because of that, I sometimes don't imagine them at first. Instead, they EMERGE.&lt;/p&gt;

&lt;p&gt;That's what happened with DateInterval. Originally I didn't have it in my code. But at some point, I had a more or less working program, that did 80% of everything it was supposed to do. It wasn't done, but it was starting to get close.&lt;/p&gt;

&lt;p&gt;And as I thought about how to add the next feature, I realized there were a lot of methods taking "start" and "end" date arguments, scattered around many different classes. And many of them needed to check whether a date was in a certain range, defaulting to certain behaviors if one or both of those boundaries were omitted.&lt;/p&gt;

&lt;p&gt;So I asked myself: how could I simplify the code? The code that already exists, as well as the remaining code I know I'm going to write?&lt;/p&gt;

&lt;p&gt;And in that moment, between my ears, DateInterval popped into being.&lt;/p&gt;

&lt;p&gt;This is what I mean by "emergent abstraction". The abstraction, DateInterval, wasn't part of any bottom-up design of the system. It wasn't something I realized was needed early on in the process. The need for it emerged.&lt;/p&gt;

&lt;p&gt;(In this case, it emerged as I was coding the application. But there's no reason it could not have emerged during the design phase, had I chosen to be detailed enough there. The point is that it emerged as the system became more completely specified.)&lt;/p&gt;

&lt;p&gt;Now, another question: what made it POSSIBLE for me to come up with DateInterval?&lt;/p&gt;

&lt;p&gt;To recognize the situation where it would help, then actually write it to behave the way it's supposed to?&lt;/p&gt;

&lt;p&gt;DateInterval is not "hello world" level stuff. It uses class methods, the iterator protocol, generator functions, magic methods, and a couple of important subtle design tradeoffs that aren't obvious until you stare really hard.&lt;/p&gt;

&lt;p&gt;In most courses, books, etc., you learn about features of Python in isolation.&lt;/p&gt;

&lt;p&gt;But real code isn't like that. In real code, you're ALWAYS using MANY language features, interlocked together, all the time. Like DateInterval.&lt;/p&gt;

&lt;p&gt;And you can reach a level that lets you SEE a DateInterval-shaped hole in your code, and then suddenly, magically, know how to code the perfect piece to fill that hole...&lt;/p&gt;

&lt;p&gt;And you do it again, and again, and again. Until you end up with a program that seems so beautiful and amazing, you can hardly believe it came out of you.&lt;/p&gt;

&lt;p&gt;Your homework, if you choose:&lt;/p&gt;

&lt;p&gt;Look over the code you wrote in the past week. Or the code that you're writing today.&lt;/p&gt;

&lt;p&gt;And pay attention to anything that seems repetitive. Especially when you look just beneath the code, if you catch my meaning...&lt;/p&gt;

&lt;p&gt;And ask yourself:&lt;/p&gt;

&lt;p&gt;"What emergent abstractions can I see? What Something-shaped hole can I perceive, when I look at the code, in my mind's eye?"&lt;/p&gt;

&lt;p&gt;Because when you truly SEE your code, you don't see it with your eyes. You see it with your mind.&lt;/p&gt;

&lt;p&gt;In that space where you can gaze upon it inside of you, where the code REALLY lives.&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>coding</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>What To Optimize For With Coding Agents</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Wed, 06 May 2026 13:45:00 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/what-to-optimize-for-with-coding-agents-4jei</link>
      <guid>https://dev.to/aaronmaxwell/what-to-optimize-for-with-coding-agents-4jei</guid>
      <description>&lt;p&gt;When you start to use agentic coding tools - like Claude Code, or OpenAI Codex, or OpenCode - it can be overwhelming at first.&lt;/p&gt;

&lt;p&gt;Coding agents like these are overpowered Swiss-army chainsaws. They have a great deal of leverage, and that leverage is strange; it can be hard to know how to work with them in a way that doesn't cause problems later.&lt;/p&gt;

&lt;p&gt;Let me suggest a good approach:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Optimize for understandability.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In other words, as you start using coding agents in new ways, experimenting with what works, the way you decide "what works" is that what the agent creates is understandable to you.&lt;/p&gt;

&lt;p&gt;Because at the end of the day, you are responsible for what that coding agent produces. Whether it's creating new code, refactoring a mature codebase, adding a new feature, or fixing a bug.&lt;/p&gt;

&lt;p&gt;And since you are held responsible for it, the only way to stay sane is to make that agent create changes that you can understand.&lt;/p&gt;

&lt;p&gt;The great thing is that this aligns with normal best practices anyway.&lt;/p&gt;

&lt;p&gt;Readability, maintainability, good code documentation, intuitive naming, a well-organized and comprehensive suite of unit tests, following SOLID principles and proven architecture patterns...&lt;/p&gt;

&lt;p&gt;All of these things, it turns out, make the system easier for you to confidently understand.&lt;/p&gt;

&lt;p&gt;And when you do, it's much more relaxing.&lt;/p&gt;

&lt;p&gt;If you use the coding agent in a way that produces something you don't really understand.... well, that's kind of nerve-wracking, isn't it?  Especially since, once again, you are responsible for what it does once it's deployed.&lt;/p&gt;

&lt;p&gt;But if you learn to use the coding agent in a way that it produces changes you can understand well, that gives you a lot more confidence in what you are creating using this tool.&lt;/p&gt;

&lt;p&gt;And as a result, you'll sleep better at night.&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>Levels of Python type annotations</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Mon, 04 May 2026 16:30:00 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/levels-of-python-type-annotations-1bd3</link>
      <guid>https://dev.to/aaronmaxwell/levels-of-python-type-annotations-1bd3</guid>
      <description>&lt;p&gt;Python has optional type annotations - also called "type hints". Like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;entry_to_dict&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;title&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;num_likes&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;num_likes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;url&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The annotations here being "Entry" as the type for the "entry" argument, and "dict" as the return type.&lt;/p&gt;

&lt;p&gt;In fact, there are at least 3 ways type annotations can be used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;documentation&lt;/li&gt;
&lt;li&gt;to configure libraries and tools&lt;/li&gt;
&lt;li&gt;static type checking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are so different, asking "do you use type annotations?" is really too vague. It's three separate questions.&lt;/p&gt;

&lt;p&gt;The first is demonstrated by entry_to_dict() above. You are reading the code, and just by reading it, you know that entry should be an instance of a class called Entry, and entry_to_dict() should return a dictionary.&lt;/p&gt;

&lt;p&gt;This by itself is really useful. And part of what makes it useful is how easy it is to include when you write the code. There's very little "friction" to dropping these types in as you bang out the method definition... And you can just skip them when they are too complex (or unknown) to specify.&lt;/p&gt;

&lt;p&gt;(Bonus: if you're the type of developer who uses autocomplete in IDEs, type hints can improve its capabilities in some cases.)&lt;/p&gt;

&lt;p&gt;The second case - configuring libraries and tools - is demonstrated in data classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;from_csv_row&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Customer email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parse_scheduleonce_date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Meeting date and time in Owner&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;s time zone&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__hash__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;when&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See the "email: str" and "when: str"? @dataclass uses those annotations to do its magic.&lt;/p&gt;

&lt;p&gt;The third use case, static type checking, is a different animal.&lt;/p&gt;

&lt;p&gt;Because statically typed languages (like Java) have an advantage over Python: the type of every variable and expression is predefined, so the compiler can catch many errors at compile time that Python cannot...&lt;/p&gt;

&lt;p&gt;In fact, Python itself cannot catch those until the line of code is actually executed...&lt;/p&gt;

&lt;p&gt;And the promise of "static type checking" is to fix that. Using a tool called mypy.&lt;/p&gt;

&lt;p&gt;To get the full benefits, though, requires an ongoing tax on your time.&lt;/p&gt;

&lt;p&gt;You must essentially learn a new mini-language to specify types, with constructs like Optional[List[str]] and Tuple[_T, _T] that just look weird until you learn how they work. Then invest effort with every function, class, and method you write, to specify the annotations correctly, consistently, and thoroughly.&lt;/p&gt;

&lt;p&gt;Which takes more effort than you would like, frankly. It becomes an ongoing tax on your codebase, paid in your attention while coding.&lt;/p&gt;

&lt;p&gt;But the larger the Python application, the greater the payoff. And especially for larger, enterprise-grade software systems, the benefits start to greatly outweigh the costs.&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>coding</category>
      <category>documentation</category>
      <category>programming</category>
      <category>python</category>
    </item>
    <item>
      <title>Pandas' secret mini-language</title>
      <dc:creator>Aaron Maxwell</dc:creator>
      <pubDate>Sun, 03 May 2026 12:45:00 +0000</pubDate>
      <link>https://dev.to/aaronmaxwell/pandas-secret-mini-language-3h96</link>
      <guid>https://dev.to/aaronmaxwell/pandas-secret-mini-language-3h96</guid>
      <description>&lt;p&gt;The DataFrame class (from Pandas) is a work of art. Even if you never "do data", priceless lessons can be gleaned by studying this class.&lt;/p&gt;

&lt;p&gt;It starts simple enough. Usually you will create a DataFrame by ingesting from a CSV file or database table or something. But you can whip up a small one like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pandas&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;

&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DataFrame&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;A&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;137&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;B&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;121&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;C&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;91&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you a DataFrame with three columns, labeled A, B and C. With rows of data, like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; print(df)
     A    B   C
0 -137   10   3
1   22   11   6
2   -3  121  91
3    4   13  12
4    5   14  15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first thing to notice is that DataFrame is a class. Once upon a time, there was no such thing as a DataFrame. Someone imagined it, and then coded it up. And just look how it changed the world.&lt;/p&gt;

&lt;p&gt;If that is not an argument for learning OOP, I do not know what is.&lt;/p&gt;

&lt;p&gt;But this article is about something else. Because once you have a DataFrame, you can 'filter' out rows that match certain criteria, by typing magick chars inside square brackets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; positive_a = df[df.A &amp;gt; 0]
&amp;gt;&amp;gt;&amp;gt; print(positive_a)
    A   B   C
1  22  11   6
3   4  13  12
4   5  14  15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breaking this down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;You can refer to column A of the DataFrame "df" by this handle: df.A&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can use square brackets, e.g. "df[...]", to say: "give me a new DataFrame with only certain rows, skipping others."&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What rows are kept? Well, that gets defined by an expression like "df.A &amp;gt; 0" in the brackets. Meaning, in this case: keep those rows where the 'A' value is positive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And it is interesting that you can go much more complex:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Relationships between multiple columns:
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;19&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Logical "and" and "or":
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;

&lt;span class="c1"&gt;# Equation-like filters, e.g.:
&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;B&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is super cool.&lt;/p&gt;

&lt;p&gt;But it also makes no sense, when you think about it...&lt;/p&gt;

&lt;p&gt;Because "df.A &amp;gt; 0" evals as boolean True or False. Right? Exactly one bit of information. So how in the name of Guido does this work?&lt;/p&gt;

&lt;p&gt;It works because "df.A &amp;gt; 0" is not boolean. It sneakily does not return True, nor False. It evaluates to something else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; comparison = (df.A &amp;gt; 0)
&amp;gt;&amp;gt;&amp;gt; type(comparison)
&amp;lt;class 'pandas.core.series.Series'&amp;gt;
&amp;gt;&amp;gt;&amp;gt; print(comparison)
0    False
1     True
2    False
3     True
4     True
Name: A, dtype: bool
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well how about that. Rather than bool, its type is something called Series. Which is kinda like a list of bool's, one for each row. Now it makes more sense, doesn't it.&lt;/p&gt;

&lt;p&gt;This is the core principle which allows DataFrame's square bracket trick to work.&lt;/p&gt;

&lt;p&gt;And while I do not have room in this little essay to fully explain the details...&lt;/p&gt;

&lt;p&gt;I will point out that it relies on Python's particular object model. Meaning, it relies on OOP. But also on details of how Python uniquely does OOP. And when you invest in mastering OOP in Python, it helps you make powerful classes like DataFrame too.&lt;/p&gt;

&lt;p&gt;Something to think about.&lt;/p&gt;

&lt;p&gt;Of course, this is an advanced technique. But see what good ideas all this sparks for you. How can you apply what you learned today in your own code?&lt;/p&gt;

&lt;p&gt;(To get a hint to how &lt;code&gt;(df.A &amp;gt; 0)&lt;/code&gt; "returns" something other than a bool, search Python's docs for this magic method name: &lt;code&gt;__gt__()&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;If you liked this, you will enjoy the &lt;a href="https://powerfulpython.com/newsletter-devto/" rel="noopener noreferrer"&gt;Powerful Python Newsletter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>programming</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
