<?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: Bruno Teixeira Lopes</title>
    <description>The latest articles on DEV Community by Bruno Teixeira Lopes (@brunotlps).</description>
    <link>https://dev.to/brunotlps</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3608752%2F1fa577b3-7b7d-4a25-ad20-f06e2c9ac4d4.jpeg</url>
      <title>DEV Community: Bruno Teixeira Lopes</title>
      <link>https://dev.to/brunotlps</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/brunotlps"/>
    <language>en</language>
    <item>
      <title>[Boost]</title>
      <dc:creator>Bruno Teixeira Lopes</dc:creator>
      <pubDate>Fri, 14 Aug 2026 18:54:24 +0000</pubDate>
      <link>https://dev.to/brunotlps/-ee5</link>
      <guid>https://dev.to/brunotlps/-ee5</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/brunotlps/python-data-model-part-2-protocols-and-special-methods-1k60" class="crayons-story__hidden-navigation-link"&gt;Python Data Model - Part 2: Protocols and Special Methods&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/brunotlps" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3608752%2F1fa577b3-7b7d-4a25-ad20-f06e2c9ac4d4.jpeg" alt="brunotlps profile" class="crayons-avatar__image" width="800" height="946"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/brunotlps" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Bruno Teixeira Lopes
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Bruno Teixeira Lopes
                
                
              
              &lt;div id="story-author-preview-content-4398786" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/brunotlps" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3608752%2F1fa577b3-7b7d-4a25-ad20-f06e2c9ac4d4.jpeg" class="crayons-avatar__image" alt="" width="800" height="946"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Bruno Teixeira Lopes&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/brunotlps/python-data-model-part-2-protocols-and-special-methods-1k60" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 14&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/brunotlps/python-data-model-part-2-protocols-and-special-methods-1k60" id="article-link-4398786"&gt;
          Python Data Model - Part 2: Protocols and Special Methods
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/beginners"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;beginners&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/brunotlps/python-data-model-part-2-protocols-and-special-methods-1k60" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/brunotlps/python-data-model-part-2-protocols-and-special-methods-1k60#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            19 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
    </item>
    <item>
      <title>Python Data Model - Part 2: Protocols and Special Methods</title>
      <dc:creator>Bruno Teixeira Lopes</dc:creator>
      <pubDate>Fri, 14 Aug 2026 18:54:19 +0000</pubDate>
      <link>https://dev.to/brunotlps/python-data-model-part-2-protocols-and-special-methods-1k60</link>
      <guid>https://dev.to/brunotlps/python-data-model-part-2-protocols-and-special-methods-1k60</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🌐 &lt;a href="https://dev.to/brunotlps/modelo-de-dados-python-parte-2-protocolos-e-metodos-especiais-2e7n"&gt;Leia a versão em português deste artigo aqui&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. From Part One to Language Protocols
&lt;/h2&gt;

&lt;p&gt;In &lt;a href="https://dev.to/brunotlps/modelo-de-dados-python-parte-1-3ela"&gt;Part 1&lt;/a&gt;, we established the foundation of Python's data model: objects possess identity, type, and value; names hold references to those objects; mutability determines what changes can occur without replacing the object; and containers store references to other objects.&lt;/p&gt;

&lt;p&gt;Now we advance another layer.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;type&lt;/strong&gt; of an object does not merely determine what values it can represent. It also determines &lt;strong&gt;which operations that object supports&lt;/strong&gt;: whether it has a size, whether it can be traversed, compared, indexed, called as a function, used in a &lt;code&gt;with&lt;/code&gt; statement, and so forth (PYTHON SOFTWARE FOUNDATION, 2026a).&lt;/p&gt;

&lt;p&gt;This is where &lt;strong&gt;special methods&lt;/strong&gt; come in.&lt;/p&gt;

&lt;p&gt;An important observation before we continue: in Part 1 we used memory address as a mental model for identity. More rigorously, Python guarantees that an object's identity remains stable during its existence. In &lt;strong&gt;CPython&lt;/strong&gt; specifically, &lt;code&gt;id(obj)&lt;/code&gt; corresponds to the memory address of the object; this is a detail of the reference implementation, not a language guarantee (PYTHON SOFTWARE FOUNDATION, 2026a).&lt;/p&gt;

&lt;p&gt;The same distinction will be important when we discuss garbage collection and finalization: &lt;strong&gt;Python specifies the language's behavior; CPython is one implementation of that behavior&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Reference Version&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The behaviors and references in this article were reviewed based on the official documentation of &lt;strong&gt;Python 3.14.7&lt;/strong&gt;. CPython-specific details will be explicitly identified.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. What Are Special Methods
&lt;/h2&gt;

&lt;p&gt;In the official documentation, names like &lt;code&gt;__len__&lt;/code&gt;, &lt;code&gt;__iter__&lt;/code&gt;, and &lt;code&gt;__add__&lt;/code&gt; are called &lt;strong&gt;special methods&lt;/strong&gt;. In the community, you will also commonly find the terms &lt;strong&gt;magic methods&lt;/strong&gt; or &lt;strong&gt;dunder methods&lt;/strong&gt; (&lt;em&gt;dunder&lt;/em&gt; comes from &lt;em&gt;double underscore&lt;/em&gt; because of the &lt;code&gt;__name__&lt;/code&gt; pattern).&lt;/p&gt;

&lt;p&gt;They allow classes defined by us to participate in operations that are part of the language's own syntax and built-in functions.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You write&lt;/th&gt;
&lt;th&gt;Behavior Python must resolve&lt;/th&gt;
&lt;th&gt;Related methods&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;repr(obj)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;official representation&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__repr__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;str(obj)&lt;/code&gt; / &lt;code&gt;print(obj)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;informal representation&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__str__&lt;/code&gt;, with fallback to &lt;code&gt;__repr__&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;len(obj)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;size&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__len__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;obj[key]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;subscription&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__getitem__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;obj[key] = value&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;subscription assignment&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__setitem__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for item in obj&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iteration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__iter__&lt;/code&gt;, &lt;code&gt;__next__&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a == b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;equality comparison&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__eq__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a + b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;arithmetic operation&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__add__&lt;/code&gt;, possibly &lt;code&gt;__radd__&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;obj(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;call&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__call__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;with obj:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;context management&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__enter__&lt;/code&gt;, &lt;code&gt;__exit__&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This table is a &lt;strong&gt;conceptual map&lt;/strong&gt;, not a literal line-by-line translation of what the interpreter executes. It is precisely this difference that we need to understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1. Operation First, Method Second
&lt;/h3&gt;

&lt;p&gt;Consider &lt;code&gt;len()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When we 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="nf"&gt;len&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;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we get:&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="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same happens with a string:&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But &lt;code&gt;len()&lt;/code&gt; does not need to possess a large sequence of checks like:&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;# model that DOES NOT represent how len() works
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A class created by us can also participate in this behavior:&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;Box&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;__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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&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;3&lt;/span&gt;


&lt;span class="n"&gt;box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;()&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;box&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Box&lt;/code&gt; does not inherit from &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, or &lt;code&gt;str&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What matters is that its &lt;strong&gt;type offers the behavior expected by the size operation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We can think about the path conceptually 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;len(box)
    ↓
size operation
    ↓
corresponding protocol
    ↓
__len__
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This kind of behavioral contract is what we will call a &lt;strong&gt;protocol&lt;/strong&gt; throughout the article.&lt;/p&gt;

&lt;p&gt;Python does not need to know in advance all the classes that might exist. The class informs the language which operations it supports through the appropriate special methods.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2. Special Method Lookup Is Different
&lt;/h3&gt;

&lt;p&gt;There is, however, a fundamental nuance.&lt;/p&gt;

&lt;p&gt;A useful first approximation is to imagine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;len(obj) ≈ type(obj).__len__(obj)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The symbol &lt;code&gt;≈&lt;/code&gt; is intentional. This is a &lt;strong&gt;mental model&lt;/strong&gt;, not a literal rewrite of the code executed by the interpreter.&lt;/p&gt;

&lt;p&gt;Implicit invocations of special methods have their own lookup rules. For user-defined classes, Python looks for these methods in the &lt;strong&gt;type of the object&lt;/strong&gt;, not simply in the attribute dictionary of the instance (PYTHON SOFTWARE FOUNDATION, 2026b).&lt;/p&gt;

&lt;p&gt;See the difference:&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;Box&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;__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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&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;3&lt;/span&gt;


&lt;span class="n"&gt;box&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__len__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we have:&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;box&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__len__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# 99
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The call above is &lt;strong&gt;explicit&lt;/strong&gt;. We are accessing the &lt;code&gt;__len__&lt;/code&gt; attribute of the instance normally.&lt;/p&gt;

&lt;p&gt;But:&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;still uses the method defined in &lt;code&gt;Box&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can observe the approximate model:&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="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="p"&gt;).&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;box&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Therefore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;box.__len__()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;len(box)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;do not have exactly the same resolution mechanism.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important Detail&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Implicit lookup of special methods generally ignores attributes defined directly on the instance and also avoids part of the normal &lt;code&gt;__getattribute__&lt;/code&gt; mechanism.&lt;/p&gt;

&lt;p&gt;For this reason, so that operations like &lt;code&gt;len(obj)&lt;/code&gt; work consistently, the corresponding special method must be defined &lt;strong&gt;on the class&lt;/strong&gt;, that is, on the object's type (PYTHON SOFTWARE FOUNDATION, 2026b).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This rule explains why &lt;strong&gt;dunder methods&lt;/strong&gt; should not be viewed simply as ordinary methods with strange names. &lt;strong&gt;They are points of integration between our types and the language's data model&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.3. A Map of Main Groups
&lt;/h3&gt;

&lt;p&gt;We do not need to memorize all existing special methods. It is more useful to group them by the behavior they allow implementing:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Main Methods&lt;/th&gt;
&lt;th&gt;Official Documentation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Creation and initialization&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__new__&lt;/code&gt;, &lt;code&gt;__init__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#basic-customization" rel="noopener noreferrer"&gt;Basic customization&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finalization&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__del__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#object.__del__" rel="noopener noreferrer"&gt;object.&lt;strong&gt;del&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Representation&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__repr__&lt;/code&gt;, &lt;code&gt;__str__&lt;/code&gt;, &lt;code&gt;__format__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#basic-customization" rel="noopener noreferrer"&gt;Basic customization&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attribute access&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__getattribute__&lt;/code&gt;, &lt;code&gt;__getattr__&lt;/code&gt;, &lt;code&gt;__setattr__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#customizing-attribute-access" rel="noopener noreferrer"&gt;Customizing attribute access&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Descriptors&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__get__&lt;/code&gt;, &lt;code&gt;__set__&lt;/code&gt;, &lt;code&gt;__delete__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#implementing-descriptors" rel="noopener noreferrer"&gt;Implementing Descriptors&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Containers and sequences&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__len__&lt;/code&gt;, &lt;code&gt;__getitem__&lt;/code&gt;, &lt;code&gt;__setitem__&lt;/code&gt;, &lt;code&gt;__contains__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#emulating-container-types" rel="noopener noreferrer"&gt;Emulating container types&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iteration&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__iter__&lt;/code&gt;, &lt;code&gt;__next__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/library/stdtypes.html#iterator-types" rel="noopener noreferrer"&gt;Iterator Types&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comparisons&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__eq__&lt;/code&gt;, &lt;code&gt;__lt__&lt;/code&gt;, &lt;code&gt;__gt__&lt;/code&gt; etc.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#object.__lt__" rel="noopener noreferrer"&gt;Basic customization&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Numeric operations&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__add__&lt;/code&gt;, &lt;code&gt;__mul__&lt;/code&gt;, &lt;code&gt;__rmul__&lt;/code&gt;, &lt;code&gt;__abs__&lt;/code&gt; etc.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#emulating-numeric-types" rel="noopener noreferrer"&gt;Emulating numeric types&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Callability&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__call__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#emulating-callable-objects" rel="noopener noreferrer"&gt;Emulating callable objects&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Context managers&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__enter__&lt;/code&gt;, &lt;code&gt;__exit__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#with-statement-context-managers" rel="noopener noreferrer"&gt;With Statement Context Managers&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table is deliberately incomplete. The goal is not to transform this part of the series into a catalog of dunders, but to understand &lt;strong&gt;why they exist and how different methods form coherent behaviors&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.4. Creation: &lt;code&gt;__new__&lt;/code&gt; and &lt;code&gt;__init__&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;One of the first important distinctions appears in object creation itself.&lt;/p&gt;

&lt;p&gt;It is common to say that "&lt;code&gt;__init__&lt;/code&gt; creates the object", but that is not exactly what happens.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Class(...)
    ↓
__new__(cls, ...)
    ↓
new instance
    ↓
__init__(instance, ...)
    ↓
object ready for the caller
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;__new__&lt;/code&gt; is called to &lt;strong&gt;create and return the new instance&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__init__&lt;/code&gt; receives an instance that already exists and performs its &lt;strong&gt;initialization or customization&lt;/strong&gt; (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;Consider:&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;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Self&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Connection&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;__new__&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;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Self&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1. __new__ created the instance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__new__&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="n"&gt;instance&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;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2. __init__ initialized the instance&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;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;


&lt;span class="nc"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;db.local&lt;/span&gt;&lt;span class="sh"&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 result is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. __new__ created the instance
2. __init__ initialized the instance

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that &lt;code&gt;__new__&lt;/code&gt; receives &lt;code&gt;cls&lt;/code&gt;, not &lt;code&gt;self&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This occurs because &lt;strong&gt;the instance is still being created&lt;/strong&gt;. The &lt;code&gt;cls&lt;/code&gt; argument informs which class was requested, allowing the method to return an appropriate instance even when inheritance is involved.&lt;/p&gt;

&lt;p&gt;In the most common implementation:&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="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__new__&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we delegate the actual creation to the method of the base class.&lt;/p&gt;

&lt;p&gt;It is tempting to summarize this process by saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"&lt;code&gt;__new__&lt;/code&gt; allocates memory."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But this formulation mixes different levels.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__new__&lt;/code&gt; is the &lt;strong&gt;instance creation hook exposed by Python's data model&lt;/strong&gt;. The low-level work necessary to produce the object, including allocation details, belongs to the runtime and the implementation used. Therefore, it is more precise to say that &lt;code&gt;__new__&lt;/code&gt; &lt;strong&gt;controls the creation and the object that will be returned&lt;/strong&gt;, rather than treating it as synonymous with the memory allocator.&lt;/p&gt;

&lt;p&gt;There is another important rule.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__init__&lt;/code&gt; is only called automatically if &lt;code&gt;__new__&lt;/code&gt; returns an instance of the requested class — or of a subclass of it (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;For example:&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;Factory&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;__new__&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;already exists&lt;/span&gt;&lt;span class="sh"&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;this line will not be executed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Factory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;result&lt;/span&gt;
&lt;span class="c1"&gt;# 'already exists'
&lt;/span&gt;
&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;lt;class 'str'&amp;gt;
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since &lt;code&gt;__new__&lt;/code&gt; returned a &lt;code&gt;str&lt;/code&gt;, not an instance of &lt;code&gt;Factory&lt;/code&gt;, &lt;code&gt;Factory&lt;/code&gt;'s &lt;code&gt;__init__&lt;/code&gt; is not executed.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__new__&lt;/code&gt; gains special importance when creating subclasses of &lt;strong&gt;immutable&lt;/strong&gt; types, such as &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;str&lt;/code&gt;, and &lt;code&gt;tuple&lt;/code&gt;. Since the immutable object cannot have its value changed after creation, changes that affect its value often need to happen during the instance's own creation (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;For ordinary classes, however, &lt;code&gt;__init__&lt;/code&gt; remains the customization point necessary in the great majority of cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.5. Finalization: &lt;code&gt;__del__&lt;/code&gt; Is Not a Resource Manager
&lt;/h3&gt;

&lt;p&gt;At the other end of the lifecycle there is:&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;__del__&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The documentation calls it a &lt;strong&gt;finalizer&lt;/strong&gt;. The term "destructor" is used informally, but can lead to an incorrect mental model (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;To understand the problem, we need to separate some concepts.&lt;/p&gt;

&lt;p&gt;An object can cease to be &lt;strong&gt;reachable&lt;/strong&gt; by the program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;object
↓
no path accessible from the program reaches it
↓
object has become unreachable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does not mean, as a general language rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unreachable = destroyed immediately
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Python allows an implementation to defer garbage collection or even omit it in certain situations&lt;/strong&gt;. What the language guarantees is that objects still reachable are not collected (PYTHON SOFTWARE FOUNDATION, 2026a).&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;CPython&lt;/strong&gt; specifically, there is a scheme based primarily on &lt;strong&gt;reference counting&lt;/strong&gt;, supplemented by a garbage collector capable of detecting cycles. For this reason, many objects are freed quickly when they no longer have references. This behavior, however, is a &lt;strong&gt;CPython detail&lt;/strong&gt;, not a universal Python contract (PYTHON SOFTWARE FOUNDATION, 2026a).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__del__&lt;/code&gt; also has other difficulties:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it may be executed during interpreter shutdown;&lt;/li&gt;
&lt;li&gt;other global objects on which it depends may already be unavailable;&lt;/li&gt;
&lt;li&gt;exceptions raised within &lt;code&gt;__del__&lt;/code&gt; are not propagated normally;&lt;/li&gt;
&lt;li&gt;its execution may occur in delicate circumstances, making blocking operations — such as acquiring a lock — particularly dangerous (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes &lt;code&gt;__del__&lt;/code&gt; a poor choice to be the &lt;strong&gt;sole responsible party&lt;/strong&gt; for the release of important external resources.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;files;&lt;/li&gt;
&lt;li&gt;sockets;&lt;/li&gt;
&lt;li&gt;locks;&lt;/li&gt;
&lt;li&gt;database connections;&lt;/li&gt;
&lt;li&gt;transactions;&lt;/li&gt;
&lt;li&gt;handles provided by the operating system.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These resources typically need a &lt;strong&gt;deterministic&lt;/strong&gt; moment of release.&lt;/p&gt;

&lt;p&gt;This is precisely where &lt;code&gt;with&lt;/code&gt; comes in. For example:&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;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The block has a well-defined point of entry and exit.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;with resource:
      ↓
__enter__()
      ↓
execute the block
      ↓
__exit__()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even when an exception occurs within the block, the context manager protocol provides an appropriate point to execute exit logic (PYTHON SOFTWARE FOUNDATION, 2026d).&lt;/p&gt;

&lt;p&gt;This difference is fundamental:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;__del__
→ finalization tied to the object's lifecycle

with / context manager
→ explicit management of a resource's lifecycle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For resources that need to be released at a predictable moment, prefer context managers or explicit APIs, do not rely exclusively on &lt;code&gt;__del__&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.6. Arithmetic: &lt;code&gt;NotImplemented&lt;/code&gt; and Reflected Operations
&lt;/h3&gt;

&lt;p&gt;Special methods also allow objects to participate in operators.&lt;/p&gt;

&lt;p&gt;Some examples:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a + b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__add__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a - b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__sub__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a * b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__mul__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a / b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__truediv__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a ** b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__pow__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__neg__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;abs(a)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__abs__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;But implementing operators correctly requires more than simply writing the calculation.&lt;/p&gt;

&lt;p&gt;Consider a duration stored in minutes:&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;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NotImplementedType&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&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;Duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__add__&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;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NotImplementedType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NotImplemented&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Duration&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;minutes&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minutes&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;__mul__&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;factor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Duration&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NotImplementedType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NotImplemented&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Duration&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;minutes&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;__rmul__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;__mul__&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;divmod&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;minutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;h&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now:&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="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Duration(minutes=135)
&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Duration(minutes=150)
&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;135&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# 2h15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But:&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="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;
&lt;span class="c1"&gt;# TypeError
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The central point is in this line:&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;return&lt;/span&gt; &lt;span class="nb"&gt;NotImplemented&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;NotImplemented&lt;/code&gt; is a special singleton object used by numeric methods and comparisons when &lt;strong&gt;that method does not implement the operation for the pair of operands received&lt;/strong&gt; (PYTHON SOFTWARE FOUNDATION, 2026e).&lt;/p&gt;

&lt;p&gt;This is different from saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Never raise an exception inside an operator."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This rule would be too broad.&lt;/p&gt;

&lt;p&gt;If the problem is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"My &lt;code&gt;__add__&lt;/code&gt; does not know how to add &lt;code&gt;Duration&lt;/code&gt; with this type of object."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;then &lt;code&gt;NotImplemented&lt;/code&gt; is normally the appropriate response.&lt;/p&gt;

&lt;p&gt;If the operation is supported, but a received value violates some legitimate domain rule, an appropriate exception can still make sense.&lt;/p&gt;

&lt;h4&gt;
  
  
  And Why Does &lt;code&gt;__rmul__&lt;/code&gt; Exist?
&lt;/h4&gt;

&lt;p&gt;Consider:&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="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this specific case, &lt;code&gt;int&lt;/code&gt; is on the left.&lt;/p&gt;

&lt;p&gt;For this pair of types:&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="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__mul__&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="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;does not know how to produce a result and returns:&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="nb"&gt;NotImplemented&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows Python to try the &lt;strong&gt;reflected&lt;/strong&gt; form of the operation on the other operand:&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;Duration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__rmul__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our method accepts the integer factor and returns:&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="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simplified model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a * b
  ↓
appropriate method supports the operation?
  ↓ no
NotImplemented
  ↓
reflected attempt
  ↓
supports?
  ├─ yes → result
  └─ no → TypeError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is an important nuance: this is not always a rigid rule of "left side first, right side second".&lt;/p&gt;

&lt;p&gt;When operands have different types and the type on the right is a subclass of the type on the left, the reflected method of the subclass may receive priority. This allows the more specific implementation to have the opportunity to control the result (PYTHON SOFTWARE FOUNDATION, 2026f).&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;Duration&lt;/code&gt;, however, there is no such inheritance relationship, and the flow described above correctly represents:&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="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example:&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;__rmul__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;__mul__&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is valid because multiplying a duration by a scalar has the same logic regardless of the syntactic order.&lt;/p&gt;

&lt;p&gt;This should not be copied automatically to any operator: operations like subtraction and division are not commutative.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;NotImplemented&lt;/code&gt; is NOT &lt;code&gt;NotImplementedError&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NotImplemented&lt;/code&gt; is a &lt;strong&gt;returned value&lt;/strong&gt; by protocols like numeric operations and comparisons to indicate that this combination of operands is not supported.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NotImplementedError&lt;/code&gt; is an &lt;strong&gt;exception&lt;/strong&gt;, normally used when an API or implementation deliberately leaves a particular operation unimplemented.&lt;/p&gt;

&lt;p&gt;The official documentation makes explicit that the two are not interchangeable (PYTHON SOFTWARE FOUNDATION, 2026g).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2.7. Attributes: &lt;code&gt;__getattr__&lt;/code&gt; and &lt;code&gt;__setattr__&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The access:&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;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;also goes through the data model.&lt;/p&gt;

&lt;p&gt;Before reaching &lt;code&gt;__getattr__&lt;/code&gt;, Python performs the normal attribute lookup mechanism, which involves the instance, its class, the class hierarchy, and, when applicable, descriptors.&lt;/p&gt;

&lt;p&gt;Only when this lookup ends in &lt;code&gt;AttributeError&lt;/code&gt; does &lt;code&gt;__getattr__&lt;/code&gt; function as a fallback (PYTHON SOFTWARE FOUNDATION, 2026h).&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;obj.name
   ↓
normal attribute lookup
   ↓
found?
├─ yes → returns the value
└─ no
    ↓
__getattr__(obj, "name")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is important because &lt;code&gt;__getattr__&lt;/code&gt; &lt;strong&gt;does not participate in every attribute read&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There is another method:&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;__getattribute__&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;that participates unconditionally in the access to instance attributes and allows controlling the process much more broadly.&lt;/p&gt;

&lt;p&gt;We will not delve into it here, but the distinction is important:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;__getattribute__
→ participates in every normal read

__getattr__
→ fallback when lookup fails
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can build a read-only configuration:&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;Config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;_data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&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="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__setattr__&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_data&lt;/span&gt;&lt;span class="sh"&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__getattr__&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&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;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&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;_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyError&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;AttributeError&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; does not exist in config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__setattr__&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;raise&lt;/span&gt; &lt;span class="nc"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Config is read-only&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage:&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;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432&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="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;
&lt;span class="c1"&gt;# 'localhost'
&lt;/span&gt;
&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;
&lt;span class="c1"&gt;# '5432'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;host&lt;/code&gt; and &lt;code&gt;port&lt;/code&gt; do not exist as normal attributes of the instance.&lt;/p&gt;

&lt;p&gt;When:&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;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is not found by normal lookup, &lt;code&gt;__getattr__&lt;/code&gt; receives:&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;name&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and looks up the information in:&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Why Does &lt;code&gt;_data&lt;/code&gt; Start With an Underscore?
&lt;/h4&gt;

&lt;p&gt;A single leading underscore is a &lt;strong&gt;internal use convention&lt;/strong&gt; used to communicate:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"This name is part of the internal implementation and should not be treated as public API."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It does not create true access control.&lt;/p&gt;

&lt;p&gt;It is still possible to 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="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python does not block this access.&lt;/p&gt;

&lt;p&gt;This is different from:&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;__data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two leading underscores activate a mechanism called &lt;strong&gt;name mangling&lt;/strong&gt;, which transforms the name internally to reduce accidental collisions, mainly in inheritance scenarios.&lt;/p&gt;

&lt;p&gt;For our example, &lt;code&gt;_data&lt;/code&gt; communicates exactly what we want: it is a non-public implementation detail.&lt;/p&gt;

&lt;h4&gt;
  
  
  And Why Do We Use &lt;code&gt;object.__setattr__&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Now observe:&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;__setattr__&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;raise&lt;/span&gt; &lt;span class="nc"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Config is read-only&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;__setattr__&lt;/code&gt; is called when we attempt to perform an attribute assignment (PYTHON SOFTWARE FOUNDATION, 2026h).&lt;/p&gt;

&lt;p&gt;Therefore:&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;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;other&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;results in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AttributeError: Config is read-only
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same would happen inside &lt;code&gt;__init__&lt;/code&gt; itself if we 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="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This instruction is also an attribute assignment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;self._data = values
        ↓
self.__setattr__("_data", values)
        ↓
AttributeError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For this reason we do:&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="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__setattr__&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_data&lt;/span&gt;&lt;span class="sh"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We are not "turning off" the entire attribute model. We are calling directly the implementation of the base class and, with that, &lt;strong&gt;avoiding our custom &lt;code&gt;Config.__setattr__&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The documentation itself recommends this pattern when a &lt;code&gt;__setattr__&lt;/code&gt; needs to perform an actual assignment on the instance (PYTHON SOFTWARE FOUNDATION, 2026h).&lt;/p&gt;

&lt;h5&gt;
  
  
  Recursion Pitfall
&lt;/h5&gt;

&lt;p&gt;An implementation like:&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;__setattr__&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;would call &lt;code&gt;__setattr__&lt;/code&gt; again, which would execute another assignment, which would call &lt;code&gt;__setattr__&lt;/code&gt; again...&lt;/p&gt;

&lt;p&gt;When it is necessary to delegate to the base behavior, explicitly use &lt;code&gt;object.__setattr__&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Why Transform &lt;code&gt;KeyError&lt;/code&gt; Into &lt;code&gt;AttributeError&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Inside &lt;code&gt;__getattr__&lt;/code&gt; we have:&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="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;_data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyError&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;AttributeError&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; does not exist in config&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The dictionary expresses absence through:&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="nb"&gt;KeyError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we are implementing &lt;strong&gt;attribute access&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this protocol, absence must be communicated through:&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="nb"&gt;AttributeError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is important because other Python mechanisms also depend on this exception to determine if an attribute exists. &lt;code&gt;from None&lt;/code&gt; suppresses the automatic display of the context with the previous &lt;code&gt;KeyError&lt;/code&gt; in the traceback, leaving visible only the exception that correctly represents the class's public abstraction (PYTHON SOFTWARE FOUNDATION, 2026j). Without &lt;code&gt;from None&lt;/code&gt;, Python would also show the context of the previous exception.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Next Layer: Descriptors
&lt;/h4&gt;

&lt;p&gt;Up to this point we have customized operations directly on the instance.&lt;/p&gt;

&lt;p&gt;Descriptors solve another problem: they allow an &lt;strong&gt;attribute stored on the class to control what happens when it is read, written, or removed&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The protocol uses:&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;__get__&lt;/span&gt;
&lt;span class="n"&gt;__set__&lt;/span&gt;
&lt;span class="n"&gt;__delete__&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;obj.attribute
    ↓
Python finds a descriptor object on the class
    ↓
__get__(...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or, during write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;obj.attribute = value
        ↓
__set__(...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This mechanism is behind fundamental language features, including &lt;code&gt;property&lt;/code&gt;, bound methods, and &lt;code&gt;classmethod&lt;/code&gt; (PYTHON SOFTWARE FOUNDATION, 2026k).&lt;/p&gt;

&lt;p&gt;For example:&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;Person&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;name&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&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;_name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The object created by &lt;code&gt;property&lt;/code&gt; participates in the descriptors protocol.&lt;/p&gt;

&lt;p&gt;We do not need to delve into the entire mechanics now. The important point is to realize that &lt;strong&gt;attribute access is also extensible through data model protocols&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.8. Protocols Are More Than Method Names
&lt;/h3&gt;

&lt;p&gt;We can now refine the definition.&lt;/p&gt;

&lt;p&gt;A protocol does not merely mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"There is a method with a particular name."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It also involves the &lt;strong&gt;semantic contract expected of that method&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;__len__&lt;/code&gt; should represent size and return a non-negative integer;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__getitem__&lt;/code&gt; of a sequence should use appropriate exceptions for invalid indices;&lt;/li&gt;
&lt;li&gt;an iterator should signal its end through &lt;code&gt;StopIteration&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__eq__&lt;/code&gt; can return &lt;code&gt;NotImplemented&lt;/code&gt; for operands it does not know how to compare;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__hash__&lt;/code&gt; must remain coherent with equality.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is possible to write a method with the correct name and still implement the protocol poorly.&lt;/p&gt;

&lt;p&gt;For this reason, we are going to start by applying this principle to a single class, which will continue evolving in the next part of the series.&lt;/p&gt;

&lt;p&gt;Our base will be an &lt;strong&gt;N-dimensional&lt;/strong&gt; vector:&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;Vector&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can create:&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="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;Vector&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;2&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="nc"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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="mi"&gt;8&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The components are stored in an internal collection:&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;_components&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;Vector&lt;/code&gt; in this article will have two important design decisions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The values of the components can be changed;&lt;/li&gt;
&lt;li&gt;The number of components will remain fixed after construction.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Therefore, it will be &lt;strong&gt;mutable as to values&lt;/strong&gt;, but will not offer operations that add or remove dimensions.&lt;/p&gt;

&lt;p&gt;For didactic purposes we will also allow:&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="nc"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;representing a vector without components. A real domain might reject this construction if it did not make sense.&lt;/p&gt;

&lt;p&gt;From here on, each new method must respect these same decisions. In this part, we will start with textual representation; in the next, we will continue evolving the same &lt;code&gt;Vector&lt;/code&gt; through the protocols of size, indexing, iteration, and comparison.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Representation: &lt;code&gt;__repr__&lt;/code&gt; and &lt;code&gt;__str__&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Let us start with the most visible behavior.&lt;/p&gt;

&lt;p&gt;Without customized &lt;code&gt;__repr__&lt;/code&gt; or &lt;code&gt;__str__&lt;/code&gt;:&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;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in CPython normally produces something 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;lt;__main__.Vector object at 0x...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact format of this default representation should not be treated as part of our class's contract.&lt;/p&gt;

&lt;p&gt;What we want to answer is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How should a &lt;code&gt;Vector&lt;/code&gt; represent itself textually?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Python offers two main methods for this.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;&lt;code&gt;__repr__&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;__str__&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Role in documentation&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;official&lt;/strong&gt; representation&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;informal&lt;/strong&gt; or easily printable representation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Common purpose&lt;/td&gt;
&lt;td&gt;rich in information and unambiguous&lt;/td&gt;
&lt;td&gt;convenient and readable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical use&lt;/td&gt;
&lt;td&gt;REPL, debugging, technical logs&lt;/td&gt;
&lt;td&gt;presentation for human reading&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Triggered by&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;repr(v)&lt;/code&gt;, &lt;code&gt;f"{v!r}"&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;str(v)&lt;/code&gt;, &lt;code&gt;print(v)&lt;/code&gt;, &lt;code&gt;f"{v}"&lt;/code&gt;, &lt;code&gt;f"{v!s}"&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The "developer versus end user" distinction can be a useful analogy, but it is not the normative definition.&lt;/p&gt;

&lt;p&gt;The documentation defines &lt;code&gt;__repr__&lt;/code&gt; as responsible for the "official" representation and recommends, when possible, a form resembling a Python expression capable of recreating an equivalent object. &lt;code&gt;__str__&lt;/code&gt;, on the other hand, can produce a more convenient or concise representation (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;Let us start with &lt;code&gt;__repr__&lt;/code&gt;:&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;Vector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ... __init__ from the previous section
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__repr__&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;component&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;component&lt;/span&gt; &lt;span class="ow"&gt;in&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;_components&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&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;Vector(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now:&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;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 'Vector(3, 4)'
&lt;/span&gt;
&lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="c1"&gt;# Vector(3, 4)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for different dimensions:&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="nc"&gt;Vector&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;2&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="c1"&gt;# Vector(1, 2, 3)
&lt;/span&gt;
&lt;span class="nc"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Vector()
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The representation accompanies the data actually stored. There is no longer any hardcoded assumption that a vector must have only &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now we add a more compact form for &lt;code&gt;__str__&lt;/code&gt;:&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;Vector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ...
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;components&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;component&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;component&lt;/span&gt; &lt;span class="ow"&gt;in&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;_components&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&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;(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that:&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;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 'Vector(3, 4)'
&lt;/span&gt;
&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# '(3, 4)'
&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;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# (3, 4)
&lt;/span&gt;
&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# '(3, 4)'
&lt;/span&gt;
&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;!s}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# '(3, 4)'
&lt;/span&gt;
&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# 'Vector(3, 4)'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Fallback of &lt;code&gt;__str__&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;There is still an important relationship between the two methods.&lt;/p&gt;

&lt;p&gt;If we define &lt;code&gt;__repr__&lt;/code&gt;, but not &lt;code&gt;__str__&lt;/code&gt;, the official representation is also used when an informal representation is needed (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;For this reason, a class with only:&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;__repr__&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;already improves both:&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="nf"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&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="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&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;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The opposite does not have the same relationship: implementing only &lt;code&gt;__str__&lt;/code&gt; does not substitute for the need for an appropriate official representation.&lt;/p&gt;

&lt;h3&gt;
  
  
  And Containers?
&lt;/h3&gt;

&lt;p&gt;Observe:&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;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# [Vector(3, 4)]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though:&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="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;produces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(3, 4)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;a &lt;code&gt;list&lt;/code&gt;'s representation uses the official representation of its elements.&lt;/p&gt;

&lt;p&gt;This is useful for debugging:&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;vectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nc"&gt;Vector&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;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;vectors&lt;/span&gt;
&lt;span class="c1"&gt;# [Vector(1, 2), Vector(3, 4)]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The container can clearly show &lt;strong&gt;which objects it contains&lt;/strong&gt;, without depending on the more informal version produced by &lt;code&gt;__str__&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Conclusion
&lt;/h2&gt;

&lt;p&gt;Throughout this part, we moved beyond the idea that methods like &lt;code&gt;__len__&lt;/code&gt;, &lt;code&gt;__repr__&lt;/code&gt;, or &lt;code&gt;__add__&lt;/code&gt; are simply special names that Python calls automatically. The broader point is that they are &lt;strong&gt;points of integration between our types and the language's protocols&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When we 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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&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;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or even:&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;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we are not merely calling isolated functions or operators. We are &lt;strong&gt;triggering behaviors defined by the data model, each with its own resolution rules and its own contracts&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For this reason, throughout the article, we saw that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;len(obj)&lt;/code&gt; is not equivalent to an ordinary call to &lt;code&gt;obj.__len__()&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__new__&lt;/code&gt; and &lt;code&gt;__init__&lt;/code&gt; participate in different moments of instance creation;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__del__&lt;/code&gt; should not be confused with deterministic resource management;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NotImplemented&lt;/code&gt; is part of the negotiation between operands;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__getattr__&lt;/code&gt; functions as a fallback in attribute access;&lt;/li&gt;
&lt;li&gt;descriptors form another protocol behind mechanisms like &lt;code&gt;property&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__repr__&lt;/code&gt; and &lt;code&gt;__str__&lt;/code&gt; represent different contracts for the textual representation of an object.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These examples also show why &lt;strong&gt;implementing a dunder method does not merely mean using the correct name&lt;/strong&gt;. To properly participate in a protocol, the class must respect the expected semantics of that operation.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Vector&lt;/code&gt; introduced at the end of this part is our point of continuity.&lt;/p&gt;

&lt;p&gt;So far, we have defined how it stores its components and how it should represent itself:&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="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or, in its informal form:&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="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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the next part, the question changes.&lt;/p&gt;

&lt;p&gt;Instead of observing protocols in isolation, we will see what happens when &lt;strong&gt;several of them need to coexist in the same type&lt;/strong&gt;. We will decide, among other things:&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;should represent what?&lt;/p&gt;

&lt;p&gt;How should:&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;v&lt;/span&gt;&lt;span class="p"&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;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&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;v&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;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;behave?&lt;/p&gt;

&lt;p&gt;What makes:&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;for&lt;/span&gt; &lt;span class="n"&gt;component&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;possible?&lt;/p&gt;

&lt;p&gt;And if the &lt;code&gt;Vector&lt;/code&gt; is mutable, how does that affect:&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;v1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and its ability to be used in a &lt;code&gt;set&lt;/code&gt; or as a &lt;code&gt;dict&lt;/code&gt; key?&lt;/p&gt;

&lt;p&gt;It is at this point that protocols cease to seem like independent features and begin to reveal something even more important about the data model: &lt;strong&gt;behavioral decisions in one part of the class can impose consequences on several others&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In Part 3, we will continue precisely from there, evolving the same &lt;code&gt;Vector&lt;/code&gt; through the protocols of size, indexing, iteration, equality, and hashing.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.1. Objects, values and types&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026a. Available at: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#objects-values-and-types" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#objects-values-and-types&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.3.13. Special method lookup&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026b. Available at: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#special-method-lookup" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#special-method-lookup&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.3.1. Basic customization&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026c. Available at: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#basic-customization" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#basic-customization&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.3.9. With Statement Context Managers&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026d. Available at: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#with-statement-context-managers" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#with-statement-context-managers&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.2.2. NotImplemented&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026e. Available at: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#notimplemented" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#notimplemented&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.3.8. Emulating numeric types&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026f. Available at: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#emulating-numeric-types" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#emulating-numeric-types&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;NotImplementedError&lt;/strong&gt;. In: &lt;em&gt;Built-in Exceptions — Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026g. Available at: &lt;a href="https://docs.python.org/3.14/library/exceptions.html#NotImplementedError" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/library/exceptions.html#NotImplementedError&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.3.2. Customizing attribute access&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026h. Available at: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#customizing-attribute-access" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#customizing-attribute-access&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;9.6. Private Variables&lt;/strong&gt;. In: &lt;em&gt;The Python Tutorial — Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026i. Available at: &lt;a href="https://docs.python.org/3.14/tutorial/classes.html#private-variables" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/tutorial/classes.html#private-variables&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;7.8. The raise statement&lt;/strong&gt;. In: &lt;em&gt;Python Language Reference — Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026j. Available at: &lt;a href="https://docs.python.org/3.14/reference/simple_stmts.html#the-raise-statement" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/simple_stmts.html#the-raise-statement&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;Descriptor Guide — Descriptor protocol&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026k. Available at: &lt;a href="https://docs.python.org/3.14/howto/descriptor.html#descriptor-protocol" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/howto/descriptor.html#descriptor-protocol&lt;/a&gt;. Accessed on: Aug. 14, 2026.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Editorial note:&lt;/strong&gt; This article was developed and reviewed by the author with AI assistance during research, technical auditing, and editorial review. Technical claims were verified against the official sources listed in the references.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>beginners</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Quem puder dar uma força na parte 2 da série, to aprendendo e curtindo muito produzir estes conteúdos!</title>
      <dc:creator>Bruno Teixeira Lopes</dc:creator>
      <pubDate>Fri, 14 Aug 2026 18:48:41 +0000</pubDate>
      <link>https://dev.to/brunotlps/quem-puder-dar-uma-forca-na-parte-2-da-serie-to-aprendendo-e-curtindo-muito-produzir-estes-4b5a</link>
      <guid>https://dev.to/brunotlps/quem-puder-dar-uma-forca-na-parte-2-da-serie-to-aprendendo-e-curtindo-muito-produzir-estes-4b5a</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/brunotlps/modelo-de-dados-python-parte-2-protocolos-e-metodos-especiais-2e7n" class="crayons-story__hidden-navigation-link"&gt;Modelo de Dados Python - Parte 2: Protocolos e métodos especiais&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/brunotlps" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3608752%2F1fa577b3-7b7d-4a25-ad20-f06e2c9ac4d4.jpeg" alt="brunotlps profile" class="crayons-avatar__image" width="800" height="946"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/brunotlps" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Bruno Teixeira Lopes
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Bruno Teixeira Lopes
                
                
              
              &lt;div id="story-author-preview-content-4398768" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/brunotlps" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3608752%2F1fa577b3-7b7d-4a25-ad20-f06e2c9ac4d4.jpeg" class="crayons-avatar__image" alt="" width="800" height="946"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Bruno Teixeira Lopes&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/brunotlps/modelo-de-dados-python-parte-2-protocolos-e-metodos-especiais-2e7n" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 14&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/brunotlps/modelo-de-dados-python-parte-2-protocolos-e-metodos-especiais-2e7n" id="article-link-4398768"&gt;
          Modelo de Dados Python - Parte 2: Protocolos e métodos especiais
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/python"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;python&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/beginners"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;beginners&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/brunotlps/modelo-de-dados-python-parte-2-protocolos-e-metodos-especiais-2e7n" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/brunotlps/modelo-de-dados-python-parte-2-protocolos-e-metodos-especiais-2e7n#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              &lt;span class="hidden s:inline"&gt;Add&amp;nbsp;Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            20 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>beginners</category>
      <category>learning</category>
      <category>python</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Modelo de Dados Python - Parte 2: Protocolos e métodos especiais</title>
      <dc:creator>Bruno Teixeira Lopes</dc:creator>
      <pubDate>Fri, 14 Aug 2026 18:47:41 +0000</pubDate>
      <link>https://dev.to/brunotlps/modelo-de-dados-python-parte-2-protocolos-e-metodos-especiais-2e7n</link>
      <guid>https://dev.to/brunotlps/modelo-de-dados-python-parte-2-protocolos-e-metodos-especiais-2e7n</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;🌐 &lt;a href="https://dev.to/brunotlps/modelo-de-dados-python-parte-2-protocolos-e-metodos-especiais-2e7n"&gt;Read this article in English here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  1. Da primeira parte aos protocolos da linguagem
&lt;/h2&gt;

&lt;p&gt;Na &lt;a href="https://dev.to/brunotlps/modelo-de-dados-python-parte-1-3ela"&gt;Parte 1&lt;/a&gt;, construímos a base do modelo de dados do Python: objetos possuem identidade, tipo e valor; nomes guardam referências para esses objetos; mutabilidade determina quais mudanças podem acontecer sem substituir o objeto; e containers armazenam referências para outros objetos.&lt;/p&gt;

&lt;p&gt;Agora vamos avançar uma camada.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;tipo&lt;/strong&gt; de um objeto não determina apenas quais valores ele pode representar. Ele também determina &lt;strong&gt;quais operações aquele objeto suporta&lt;/strong&gt;: se possui tamanho, se pode ser percorrido, comparado, indexado, chamado como função, usado em um &lt;code&gt;with&lt;/code&gt; e assim por diante (PYTHON SOFTWARE FOUNDATION, 2026a).&lt;/p&gt;

&lt;p&gt;É aqui que entram os &lt;strong&gt;métodos especiais&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Uma observação importante antes de continuar: na Parte 1 usamos o endereço de memória como modelo mental para identidade. De forma mais rigorosa, Python garante que a identidade de um objeto é estável durante sua existência. No &lt;strong&gt;CPython&lt;/strong&gt;, especificamente, &lt;code&gt;id(obj)&lt;/code&gt; corresponde ao endereço de memória do objeto; isso é um detalhe da implementação de referência, não uma garantia da linguagem (PYTHON SOFTWARE FOUNDATION, 2026a).&lt;/p&gt;

&lt;p&gt;A mesma distinção será importante quando falarmos sobre garbage collection e finalização: &lt;strong&gt;Python especifica o comportamento da linguagem; CPython é uma implementação desse comportamento&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Versão de referência&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Os comportamentos e referências deste artigo foram revisados com base na documentação oficial do &lt;strong&gt;Python 3.14.7&lt;/strong&gt;. Detalhes exclusivos do CPython serão identificados explicitamente.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. O que são métodos especiais
&lt;/h2&gt;

&lt;p&gt;Na documentação oficial, nomes como &lt;code&gt;__len__&lt;/code&gt;, &lt;code&gt;__iter__&lt;/code&gt; e &lt;code&gt;__add__&lt;/code&gt; são chamados de &lt;strong&gt;special methods&lt;/strong&gt;, ou métodos especiais, na comunidade também é comum encontrar os termos &lt;strong&gt;métodos mágicos&lt;/strong&gt; ou &lt;strong&gt;dunder methods&lt;/strong&gt; (&lt;em&gt;dunder&lt;/em&gt; vem de &lt;em&gt;double underscore&lt;/em&gt; por causa do padrão &lt;code&gt;__nome__&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Eles permitem que classes definidas por nós participem de operações que fazem parte da própria sintaxe e das funções embutidas da linguagem.&lt;/p&gt;

&lt;p&gt;Por exemplo:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Você escreve&lt;/th&gt;
&lt;th&gt;Comportamento que Python precisa resolver&lt;/th&gt;
&lt;th&gt;Métodos relacionados&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;repr(obj)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;representação oficial&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__repr__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;str(obj)&lt;/code&gt; / &lt;code&gt;print(obj)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;representação informal&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__str__&lt;/code&gt;, com fallback para &lt;code&gt;__repr__&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;len(obj)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;tamanho&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__len__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;obj[chave]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;subscrição&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__getitem__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;obj[chave] = valor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;atribuição por subscrição&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__setitem__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for item in obj&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;iteração&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__iter__&lt;/code&gt;, &lt;code&gt;__next__&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a == b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;comparação de igualdade&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__eq__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a + b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;operação aritmética&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__add__&lt;/code&gt;, possivelmente &lt;code&gt;__radd__&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;obj(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;chamada&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__call__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;with obj:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;gerenciamento de contexto&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__enter__&lt;/code&gt;, &lt;code&gt;__exit__&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Essa tabela é um &lt;strong&gt;mapa conceitual&lt;/strong&gt;, não uma tradução literal linha por linha do que o interpretador executa. É justamente essa diferença que precisamos entender.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.1. Operação primeiro, método depois
&lt;/h3&gt;

&lt;p&gt;Considere &lt;code&gt;len()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Quando escrevemos:&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="nf"&gt;len&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;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;obtemos:&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="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O mesmo acontece com uma string:&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas &lt;code&gt;len()&lt;/code&gt; não precisa possuir uma grande sequência de verificações como:&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;# modelo que NÃO representa o funcionamento de len()
&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma classe criada por nós também pode participar desse comportamento:&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;Caixa&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;__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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&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;3&lt;/span&gt;


&lt;span class="n"&gt;caixa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Caixa&lt;/span&gt;&lt;span class="p"&gt;()&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;caixa&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Caixa&lt;/code&gt; não herda de &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt; ou &lt;code&gt;str&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O que importa é que seu &lt;strong&gt;tipo oferece o comportamento esperado pela operação de tamanho&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Podemos pensar no caminho conceitualmente assim:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;len(caixa)
     ↓
operação de tamanho
     ↓
protocolo correspondente
     ↓
__len__
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;É esse tipo de contrato comportamental que chamaremos de &lt;strong&gt;protocolo&lt;/strong&gt; ao longo do artigo.&lt;/p&gt;

&lt;p&gt;Python não precisa conhecer antecipadamente todas as classes que poderão existir. A classe informa à linguagem quais operações suporta através dos métodos especiais apropriados.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.2. O lookup de métodos especiais é diferente
&lt;/h3&gt;

&lt;p&gt;Existe, porém, uma nuance fundamental.&lt;/p&gt;

&lt;p&gt;Uma primeira aproximação útil é imaginar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;len(obj) ≈ type(obj).__len__(obj)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O símbolo &lt;code&gt;≈&lt;/code&gt; é proposital. Isso é um &lt;strong&gt;modelo mental&lt;/strong&gt;, e não uma reescrita literal do código executado pelo interpretador.&lt;/p&gt;

&lt;p&gt;Invocações implícitas de métodos especiais possuem regras próprias de lookup. Para classes definidas pelo usuário, Python procura esses métodos no &lt;strong&gt;tipo do objeto&lt;/strong&gt;, e não simplesmente no dicionário de atributos da instância (PYTHON SOFTWARE FOUNDATION, 2026b).&lt;/p&gt;

&lt;p&gt;Veja a diferença:&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;Caixa&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;__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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&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;3&lt;/span&gt;


&lt;span class="n"&gt;caixa&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Caixa&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;caixa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__len__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora temos:&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;caixa&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__len__&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# 99
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A chamada acima é &lt;strong&gt;explícita&lt;/strong&gt;. Estamos acessando normalmente o atributo &lt;code&gt;__len__&lt;/code&gt; da instância.&lt;/p&gt;

&lt;p&gt;Mas:&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;caixa&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;continua usando o método definido em &lt;code&gt;Caixa&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Podemos observar o modelo aproximado:&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="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;caixa&lt;/span&gt;&lt;span class="p"&gt;).&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;caixa&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Portanto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;caixa.__len__()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;len(caixa)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;não possuem exatamente o mesmo mecanismo de resolução.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Detalhe importante&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O lookup implícito de métodos especiais geralmente ignora atributos definidos diretamente na instância e também evita parte do mecanismo normal de &lt;code&gt;__getattribute__&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Por isso, para que operações como &lt;code&gt;len(obj)&lt;/code&gt; funcionem consistentemente, o método especial correspondente deve ser definido &lt;strong&gt;na classe&lt;/strong&gt;, isto é, no tipo do objeto (PYTHON SOFTWARE FOUNDATION, 2026b).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essa regra explica por que &lt;strong&gt;dunder methods&lt;/strong&gt; não devem ser encarados simplesmente como métodos comuns com nomes estranhos. &lt;strong&gt;Eles são pontos de integração entre nossos tipos e o modelo de dados da linguagem&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.3. Um mapa dos principais grupos
&lt;/h3&gt;

&lt;p&gt;Não precisamos decorar todos os special methods existentes. É mais útil agrupá-los pelo comportamento que permitem implementar:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Categoria&lt;/th&gt;
&lt;th&gt;Métodos principais&lt;/th&gt;
&lt;th&gt;Documentação oficial&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Criação e inicialização&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__new__&lt;/code&gt;, &lt;code&gt;__init__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#basic-customization" rel="noopener noreferrer"&gt;Basic customization&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Finalização&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__del__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#object.__del__" rel="noopener noreferrer"&gt;object.&lt;strong&gt;del&lt;/strong&gt;&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Representação&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__repr__&lt;/code&gt;, &lt;code&gt;__str__&lt;/code&gt;, &lt;code&gt;__format__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#basic-customization" rel="noopener noreferrer"&gt;Basic customization&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Acesso a atributos&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__getattribute__&lt;/code&gt;, &lt;code&gt;__getattr__&lt;/code&gt;, &lt;code&gt;__setattr__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#customizing-attribute-access" rel="noopener noreferrer"&gt;Customizing attribute access&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Descritores&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__get__&lt;/code&gt;, &lt;code&gt;__set__&lt;/code&gt;, &lt;code&gt;__delete__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#implementing-descriptors" rel="noopener noreferrer"&gt;Implementing Descriptors&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Containers e sequências&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__len__&lt;/code&gt;, &lt;code&gt;__getitem__&lt;/code&gt;, &lt;code&gt;__setitem__&lt;/code&gt;, &lt;code&gt;__contains__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#emulating-container-types" rel="noopener noreferrer"&gt;Emulating container types&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Iteração&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__iter__&lt;/code&gt;, &lt;code&gt;__next__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/library/stdtypes.html#iterator-types" rel="noopener noreferrer"&gt;Iterator Types&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comparações&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__eq__&lt;/code&gt;, &lt;code&gt;__lt__&lt;/code&gt;, &lt;code&gt;__gt__&lt;/code&gt; etc.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#object.__lt__" rel="noopener noreferrer"&gt;Basic customization&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operações numéricas&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__add__&lt;/code&gt;, &lt;code&gt;__mul__&lt;/code&gt;, &lt;code&gt;__rmul__&lt;/code&gt;, &lt;code&gt;__abs__&lt;/code&gt; etc.&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#emulating-numeric-types" rel="noopener noreferrer"&gt;Emulating numeric types&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chamabilidade&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__call__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#emulating-callable-objects" rel="noopener noreferrer"&gt;Emulating callable objects&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gerenciadores de contexto&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;__enter__&lt;/code&gt;, &lt;code&gt;__exit__&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;a href="https://docs.python.org/3.14/reference/datamodel.html#with-statement-context-managers" rel="noopener noreferrer"&gt;With Statement Context Managers&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A tabela é deliberadamente incompleta. O objetivo não é transformar esta parte da série em um catálogo de dunders, mas entender &lt;strong&gt;por que eles existem e como diferentes métodos formam comportamentos coerentes&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.4. Criação: &lt;code&gt;__new__&lt;/code&gt; e &lt;code&gt;__init__&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Uma das primeiras distinções importantes aparece na própria criação de objetos.&lt;/p&gt;

&lt;p&gt;É comum dizer que "&lt;code&gt;__init__&lt;/code&gt; cria o objeto", mas isso não é exatamente o que acontece.&lt;/p&gt;

&lt;p&gt;Conceitualmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Classe(...)
    ↓
__new__(cls, ...)
    ↓
nova instância
    ↓
__init__(instância, ...)
    ↓
objeto pronto para o chamador
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;__new__&lt;/code&gt; é chamado para &lt;strong&gt;criar e retornar a nova instância&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__init__&lt;/code&gt; recebe uma instância que já existe e realiza sua &lt;strong&gt;inicialização ou customização&lt;/strong&gt; (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;Considere:&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;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Self&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Conexao&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;__new__&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;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Self&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1. __new__ criou a instância&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;instancia&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__new__&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="n"&gt;instancia&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;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2. __init__ inicializou a instância&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;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;


&lt;span class="nc"&gt;Conexao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;db.local&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O resultado é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. __new__ criou a instância
2. __init__ inicializou a instância

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observe que &lt;code&gt;__new__&lt;/code&gt; recebe &lt;code&gt;cls&lt;/code&gt;, e não &lt;code&gt;self&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Isso ocorre porque &lt;strong&gt;a instância ainda está sendo criada&lt;/strong&gt;. O argumento &lt;code&gt;cls&lt;/code&gt; informa qual classe foi solicitada, permitindo que o método devolva uma instância apropriada inclusive quando herança está envolvida.&lt;/p&gt;

&lt;p&gt;Na implementação mais comum:&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="nf"&gt;super&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;__new__&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;delegamos a criação efetiva para o método da classe base.&lt;/p&gt;

&lt;p&gt;É tentador resumir esse processo dizendo:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"&lt;code&gt;__new__&lt;/code&gt; aloca memória."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Mas essa formulação mistura níveis diferentes.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__new__&lt;/code&gt; é o &lt;strong&gt;hook de criação de instâncias exposto pelo modelo de dados Python&lt;/strong&gt;. O trabalho de baixo nível necessário para produzir o objeto, incluindo detalhes de alocação, pertence ao runtime e à implementação utilizada. Portanto, é mais preciso dizer que &lt;code&gt;__new__&lt;/code&gt; &lt;strong&gt;controla a criação e o objeto que será retornado&lt;/strong&gt;, e não tratá-lo como sinônimo do allocator de memória.&lt;/p&gt;

&lt;p&gt;Existe outra regra importante.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__init__&lt;/code&gt; só é chamado automaticamente se &lt;code&gt;__new__&lt;/code&gt; retornar uma instância da classe solicitada — ou de uma subclasse dela (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;Por exemplo:&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;Fabrica&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;__new__&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;já existe&lt;/span&gt;&lt;span class="sh"&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;esta linha não será executada&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;resultado&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Fabrica&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;resultado&lt;/span&gt;
&lt;span class="c1"&gt;# 'já existe'
&lt;/span&gt;
&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resultado&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;lt;class 'str'&amp;gt;
&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como &lt;code&gt;__new__&lt;/code&gt; retornou uma &lt;code&gt;str&lt;/code&gt;, e não uma instância de &lt;code&gt;Fabrica&lt;/code&gt;, o &lt;code&gt;__init__&lt;/code&gt; de &lt;code&gt;Fabrica&lt;/code&gt; não é executado.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__new__&lt;/code&gt; ganha importância especial ao criar subclasses de tipos &lt;strong&gt;imutáveis&lt;/strong&gt;, como &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;str&lt;/code&gt; e &lt;code&gt;tuple&lt;/code&gt;. Como o objeto imutável não pode ter seu valor alterado depois de criado, mudanças que afetam seu valor frequentemente precisam acontecer durante a própria criação da instância (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;Para classes comuns, entretanto, &lt;code&gt;__init__&lt;/code&gt; continua sendo o ponto de customização necessário na grande maioria dos casos.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.5. Finalização: &lt;code&gt;__del__&lt;/code&gt; não é um gerenciador de recursos
&lt;/h3&gt;

&lt;p&gt;No outro extremo do ciclo de vida existe:&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;__del__&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A documentação o chama de &lt;strong&gt;finalizer&lt;/strong&gt;. O termo “destrutor” é usado informalmente, mas pode induzir a um modelo mental incorreto (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;Para entender o problema, precisamos separar alguns conceitos.&lt;/p&gt;

&lt;p&gt;Um objeto pode deixar de ser &lt;strong&gt;alcançável&lt;/strong&gt; pelo programa:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;objeto
↓
nenhum caminho acessível do programa chega até ele
↓
objeto tornou-se inalcançável
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso não significa, como regra geral da linguagem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;inalcançável = destruído imediatamente
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Python permite que uma implementação adie a coleta de lixo ou até deixe de realizá-la em determinadas situações&lt;/strong&gt;. O que a linguagem garante é que objetos ainda alcançáveis não sejam coletados (PYTHON SOFTWARE FOUNDATION, 2026a).&lt;/p&gt;

&lt;p&gt;No &lt;strong&gt;CPython&lt;/strong&gt;, especificamente, existe um esquema baseado principalmente em &lt;strong&gt;contagem de referências&lt;/strong&gt;, complementado por um garbage collector capaz de detectar ciclos. Por isso muitos objetos são liberados rapidamente quando deixam de possuir referências. Esse comportamento, porém, é um &lt;strong&gt;detalhe do CPython&lt;/strong&gt;, não um contrato universal de Python (PYTHON SOFTWARE FOUNDATION, 2026a).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;__del__&lt;/code&gt; também possui outras dificuldades:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pode ser executado durante o encerramento do interpretador;&lt;/li&gt;
&lt;li&gt;outros objetos globais dos quais ele depende podem já estar indisponíveis;&lt;/li&gt;
&lt;li&gt;exceções levantadas dentro de &lt;code&gt;__del__&lt;/code&gt; não são propagadas normalmente;&lt;/li&gt;
&lt;li&gt;sua execução pode ocorrer em circunstâncias delicadas, tornando operações bloqueantes — como adquirir um lock — particularmente perigosas (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Isso torna &lt;code&gt;__del__&lt;/code&gt; uma escolha ruim para ser o &lt;strong&gt;único responsável&lt;/strong&gt; pela liberação de recursos externos importantes.&lt;/p&gt;

&lt;p&gt;Exemplos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;arquivos;&lt;/li&gt;
&lt;li&gt;sockets;&lt;/li&gt;
&lt;li&gt;locks;&lt;/li&gt;
&lt;li&gt;conexões com bancos de dados;&lt;/li&gt;
&lt;li&gt;transações;&lt;/li&gt;
&lt;li&gt;handles fornecidos pelo sistema operacional.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esses recursos normalmente precisam de um momento &lt;strong&gt;determinístico&lt;/strong&gt; de liberação.&lt;/p&gt;

&lt;p&gt;É exatamente aqui que entra &lt;code&gt;with&lt;/code&gt;. Por exemplo:&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;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dados.txt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;r&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;conteudo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;arquivo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O bloco possui um ponto bem definido de entrada e saída.&lt;/p&gt;

&lt;p&gt;Conceitualmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;with recurso:
      ↓
__enter__()
      ↓
executa o bloco
      ↓
__exit__()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mesmo quando uma exceção ocorre dentro do bloco, o protocolo de context manager fornece um ponto apropriado para executar a lógica de saída (PYTHON SOFTWARE FOUNDATION, 2026d).&lt;/p&gt;

&lt;p&gt;Essa diferença é fundamental:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;__del__
→ finalização ligada ao ciclo de vida do objeto

with / context manager
→ gerenciamento explícito do ciclo de vida de um recurso
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para recursos que precisam ser liberados em um momento previsível, prefira context managers ou APIs explícitas, não dependa exclusivamente de &lt;code&gt;__del__&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.6. Aritmética: &lt;code&gt;NotImplemented&lt;/code&gt; e operações refletidas
&lt;/h3&gt;

&lt;p&gt;Métodos especiais também permitem que objetos participem de operadores.&lt;/p&gt;

&lt;p&gt;Alguns exemplos:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operação&lt;/th&gt;
&lt;th&gt;Método&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a + b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__add__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a - b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__sub__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a * b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__mul__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a / b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__truediv__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a ** b&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__pow__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;-a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__neg__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;abs(a)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;__abs__&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Mas implementar operadores corretamente exige mais do que simplesmente escrever o cálculo.&lt;/p&gt;

&lt;p&gt;Considere uma duração armazenada em minutos:&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;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;NotImplementedType&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&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;Duracao&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;minutos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__add__&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;outra&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Duracao&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NotImplementedType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outra&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NotImplemented&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Duracao&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;minutos&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;outra&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minutos&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;__mul__&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;fator&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Duracao&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;NotImplementedType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;NotImplemented&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Duracao&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;minutos&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;fator&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;__rmul__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;__mul__&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;horas&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;minutos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;divmod&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;minutos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;horas&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;h&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;minutos&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;02&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora:&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="nc"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Duracao(minutos=135)
&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Duracao(minutos=150)
&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;135&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="c1"&gt;# 2h15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas:&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="nc"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;45&lt;/span&gt;
&lt;span class="c1"&gt;# TypeError
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O ponto central está nesta linha:&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;return&lt;/span&gt; &lt;span class="nb"&gt;NotImplemented&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;NotImplemented&lt;/code&gt; é um objeto singleton especial utilizado pelos métodos numéricos e pelas comparações quando &lt;strong&gt;aquele método não implementa a operação para o par de operandos recebido&lt;/strong&gt; (PYTHON SOFTWARE FOUNDATION, 2026e).&lt;/p&gt;

&lt;p&gt;Isso é diferente de dizer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Nunca levante uma exceção dentro de um operador.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Essa regra seria excessivamente ampla.&lt;/p&gt;

&lt;p&gt;Se o problema é:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Meu &lt;code&gt;__add__&lt;/code&gt; não sabe somar &lt;code&gt;Duracao&lt;/code&gt; com esse tipo de objeto.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;então &lt;code&gt;NotImplemented&lt;/code&gt; é normalmente a resposta apropriada.&lt;/p&gt;

&lt;p&gt;Se a operação é suportada, mas um valor recebido viola alguma regra legítima do domínio, uma exceção adequada ainda pode fazer sentido.&lt;/p&gt;

&lt;h4&gt;
  
  
  E por que existe &lt;code&gt;__rmul__&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Considere:&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="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste caso específico, &lt;code&gt;int&lt;/code&gt; está à esquerda.&lt;/p&gt;

&lt;p&gt;Para esse par de tipos:&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="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__mul__&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="nc"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;não sabe produzir um resultado e devolve:&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="nb"&gt;NotImplemented&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso permite que Python tente a forma &lt;strong&gt;refletida&lt;/strong&gt; da operação no outro operando:&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;Duracao&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__rmul__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nosso método aceita o fator inteiro e devolve:&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="nc"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;150&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Um modelo simplificado é:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a * b
  ↓
método apropriado suporta a operação?
  ↓ não
NotImplemented
  ↓
tentativa refletida
  ↓
suporta?
  ├─ sim → resultado
  └─ não → TypeError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Há uma nuance importante: essa não é sempre uma regra rígida de “lado esquerdo primeiro, lado direito depois”.&lt;/p&gt;

&lt;p&gt;Quando os operandos possuem tipos diferentes e o tipo da direita é uma subclasse do tipo da esquerda, o método refletido da subclasse pode receber prioridade. Isso permite que a implementação mais específica tenha a oportunidade de controlar o resultado (PYTHON SOFTWARE FOUNDATION, 2026f).&lt;/p&gt;

&lt;p&gt;Para &lt;code&gt;int&lt;/code&gt; e &lt;code&gt;Duracao&lt;/code&gt;, entretanto, não existe essa relação de herança, e o fluxo descrito acima representa corretamente:&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="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nc"&gt;Duracao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Neste exemplo:&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;__rmul__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;__mul__&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;é válido porque multiplicar uma duração por um escalar possui a mesma lógica independentemente da ordem sintática.&lt;/p&gt;

&lt;p&gt;Isso não deve ser copiado automaticamente para qualquer operador: operações como subtração e divisão não são comutativas.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;NotImplemented&lt;/code&gt;&lt;/strong&gt; &lt;strong&gt;não é&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;NotImplementedError&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NotImplemented&lt;/code&gt; é um &lt;strong&gt;valor retornado&lt;/strong&gt; por protocolos como operações numéricas e comparações para indicar que aquela combinação de operandos não é suportada.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;NotImplementedError&lt;/code&gt; é uma &lt;strong&gt;exceção&lt;/strong&gt;, normalmente utilizada quando uma API ou implementação deliberadamente deixa determinada operação sem implementação.&lt;/p&gt;

&lt;p&gt;A documentação oficial explicita que os dois não são intercambiáveis (PYTHON SOFTWARE FOUNDATION, 2026g).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  2.7. Atributos: &lt;code&gt;__getattr__&lt;/code&gt; e &lt;code&gt;__setattr__&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;O acesso:&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;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;também passa pelo modelo de dados.&lt;/p&gt;

&lt;p&gt;Antes de chegar a &lt;code&gt;__getattr__&lt;/code&gt;, Python realiza o mecanismo normal de busca de atributos, que envolve a instância, sua classe, a hierarquia de classes e, quando aplicável, descriptors.&lt;/p&gt;

&lt;p&gt;Só quando essa busca termina em &lt;code&gt;AttributeError&lt;/code&gt;, &lt;code&gt;__getattr__&lt;/code&gt; funciona como fallback (PYTHON SOFTWARE FOUNDATION, 2026h).&lt;/p&gt;

&lt;p&gt;Conceitualmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;obj.nome
   ↓
busca normal de atributos
   ↓
encontrou?
├─ sim → devolve o valor
└─ não
    ↓
__getattr__(obj, "nome")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso é importante porque &lt;code&gt;__getattr__&lt;/code&gt; &lt;strong&gt;não participa de toda leitura de atributos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Existe outro método:&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;__getattribute__&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;que participa incondicionalmente do acesso a atributos de instâncias e permite controlar o processo de forma muito mais ampla.&lt;/p&gt;

&lt;p&gt;Não vamos aprofundá-lo aqui, mas a distinção é importante:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;__getattribute__
→ participa de toda leitura normal

__getattr__
→ fallback quando a busca falha
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora podemos construir uma configuração somente leitura:&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;Config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;_dados&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;str&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="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;valores&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__setattr__&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_dados&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;valores&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;__getattr__&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;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&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;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;try&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;_dados&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyError&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;AttributeError&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; não existe na configuração&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__setattr__&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;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;valor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;raise&lt;/span&gt; &lt;span class="nc"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Config é somente leitura&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uso:&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;cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;localhost&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;porta&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;5432&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="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;
&lt;span class="c1"&gt;# 'localhost'
&lt;/span&gt;
&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;porta&lt;/span&gt;
&lt;span class="c1"&gt;# '5432'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;host&lt;/code&gt; e &lt;code&gt;porta&lt;/code&gt; não existem como atributos normais da instância.&lt;/p&gt;

&lt;p&gt;Quando:&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;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;não é encontrado pela busca normal, &lt;code&gt;__getattr__&lt;/code&gt; recebe:&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;nome&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;host&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e procura a informação em:&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_dados&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Por que &lt;code&gt;_dados&lt;/code&gt; começa com underscore?
&lt;/h4&gt;

&lt;p&gt;Um único underscore inicial é uma &lt;strong&gt;convenção de uso interno&lt;/strong&gt; usada para comunicar:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Este nome faz parte da implementação interna e não deveria ser tratado como API pública.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ele não cria verdadeiro controle de acesso.&lt;/p&gt;

&lt;p&gt;Ainda é possível escrever:&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;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_dados&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python não bloqueia esse acesso.&lt;/p&gt;

&lt;p&gt;Isso é diferente de:&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;__dados&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dois underscores iniciais ativam um mecanismo chamado &lt;strong&gt;name mangling&lt;/strong&gt;, que transforma o nome internamente para reduzir colisões acidentais, principalmente em cenários de herança.&lt;/p&gt;

&lt;p&gt;Para nosso exemplo, &lt;code&gt;_dados&lt;/code&gt; comunica exatamente o que queremos: trata-se de um detalhe não público da implementação.&lt;/p&gt;

&lt;h4&gt;
  
  
  E por que usamos &lt;code&gt;object.__setattr__&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Agora observe:&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;__setattr__&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;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;valor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;raise&lt;/span&gt; &lt;span class="nc"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Config é somente leitura&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;__setattr__&lt;/code&gt; é chamado quando tentamos realizar uma atribuição de atributo (PYTHON SOFTWARE FOUNDATION, 2026h).&lt;/p&gt;

&lt;p&gt;Portanto:&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;cfg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outro&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;resulta em:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AttributeError: Config é somente leitura
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O mesmo aconteceria dentro do próprio &lt;code&gt;__init__&lt;/code&gt; se escrevêssemos:&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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_dados&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;valores&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Essa instrução também é uma atribuição de atributo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;self._dados = valores
        ↓
self.__setattr__("_dados", valores)
        ↓
AttributeError
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por isso fazemos:&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="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;__setattr__&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;_dados&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;valores&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não estamos “desligando” o modelo de atributos inteiro. Estamos chamando diretamente a implementação da classe base e, com isso, &lt;strong&gt;evitando nosso&lt;/strong&gt; &lt;strong&gt;&lt;code&gt;Config.__setattr__&lt;/code&gt;&lt;/strong&gt; &lt;strong&gt;customizado&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A própria documentação recomenda esse padrão quando um &lt;code&gt;__setattr__&lt;/code&gt; precisa realizar uma atribuição real na instância (PYTHON SOFTWARE FOUNDATION, 2026h).&lt;/p&gt;

&lt;h5&gt;
  
  
  Armadilha de recursão
&lt;/h5&gt;

&lt;p&gt;Uma implementação como:&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;__setattr__&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;nome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;valor&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;nome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;valor&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;chamaria novamente &lt;code&gt;__setattr__&lt;/code&gt;, que executaria outra atribuição, que chamaria &lt;code&gt;__setattr__&lt;/code&gt; outra vez...&lt;/p&gt;

&lt;p&gt;Quando é necessário delegar ao comportamento base, use explicitamente &lt;code&gt;object.__setattr__&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Por que transformar &lt;code&gt;KeyError&lt;/code&gt; em &lt;code&gt;AttributeError&lt;/code&gt;?
&lt;/h4&gt;

&lt;p&gt;Dentro de &lt;code&gt;__getattr__&lt;/code&gt; temos:&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="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;_dados&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;KeyError&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;AttributeError&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="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt; não existe na configuração&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O dicionário expressa ausência através de:&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="nb"&gt;KeyError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mas estamos implementando &lt;strong&gt;acesso a atributos&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Nesse protocolo, a ausência deve ser comunicada através de:&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="nb"&gt;AttributeError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso é importante porque outros mecanismos de Python também dependem dessa exceção para determinar se um atributo existe. &lt;code&gt;from None&lt;/code&gt; suprime a exibição automática do encadeamento com o &lt;code&gt;KeyError&lt;/code&gt; anterior no traceback, deixando visível apenas a exceção que representa corretamente a abstração pública da classe (PYTHON SOFTWARE FOUNDATION, 2026j). Sem &lt;code&gt;from None&lt;/code&gt;, Python mostraria também o contexto da exceção anterior.&lt;/p&gt;

&lt;h4&gt;
  
  
  A próxima camada: descriptors
&lt;/h4&gt;

&lt;p&gt;Até aqui customizamos operações diretamente sobre a instância.&lt;/p&gt;

&lt;p&gt;Descriptors resolvem outro problema: permitir que &lt;strong&gt;um atributo armazenado na classe controle o que acontece quando é lido, escrito ou removido&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;O protocolo utiliza:&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;__get__&lt;/span&gt;
&lt;span class="n"&gt;__set__&lt;/span&gt;
&lt;span class="n"&gt;__delete__&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conceitualmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;obj.atributo
    ↓
Python encontra um objeto descriptor na classe
    ↓
__get__(...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ou, durante escrita:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;obj.atributo = valor
        ↓
__set__(...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esse mecanismo está por trás de recursos fundamentais da própria linguagem, incluindo &lt;code&gt;property&lt;/code&gt;, métodos ligados e &lt;code&gt;classmethod&lt;/code&gt; (PYTHON SOFTWARE FOUNDATION, 2026k).&lt;/p&gt;

&lt;p&gt;Por exemplo:&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;Pessoa&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;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_nome&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nome&lt;/span&gt;

    &lt;span class="nd"&gt;@property&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;nome&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&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;_nome&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O objeto criado por &lt;code&gt;property&lt;/code&gt; participa do protocolo de descriptors.&lt;/p&gt;

&lt;p&gt;Não precisamos aprofundar a mecânica inteira agora. O ponto importante é perceber que &lt;strong&gt;acesso a atributos também é extensível através de protocolos do modelo de dados&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2.8. Protocolos são mais do que nomes de métodos
&lt;/h3&gt;

&lt;p&gt;Podemos agora refinar a definição.&lt;/p&gt;

&lt;p&gt;Um protocolo não significa apenas:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Existe um método com determinado nome.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ele também envolve o &lt;strong&gt;contrato semântico esperado daquele método&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Por exemplo:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;__len__&lt;/code&gt; deve representar tamanho e retornar um inteiro não negativo;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__getitem__&lt;/code&gt; de uma sequência deve usar exceções apropriadas para índices inválidos;&lt;/li&gt;
&lt;li&gt;um iterador deve sinalizar seu fim através de &lt;code&gt;StopIteration&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__eq__&lt;/code&gt; pode devolver &lt;code&gt;NotImplemented&lt;/code&gt; para operandos que não sabe comparar;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__hash__&lt;/code&gt; precisa permanecer coerente com igualdade.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;É possível escrever um método com o nome correto e ainda implementar o protocolo de maneira ruim.&lt;/p&gt;

&lt;p&gt;Por isso, vamos começar aplicando esse princípio a uma única classe, que continuará evoluindo na próxima parte da série.&lt;/p&gt;

&lt;p&gt;Nossa base será um vetor &lt;strong&gt;N-dimensional&lt;/strong&gt;:&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;Vector&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;componentes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;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;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_componentes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;componentes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora podemos criar:&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="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nc"&gt;Vector&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;2&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="nc"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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="mi"&gt;8&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Os componentes ficam armazenados em uma coleção interna:&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;_componentes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;Vector&lt;/code&gt; deste artigo terá duas decisões de projeto importantes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Os valores dos componentes poderão ser alterados;
&lt;/li&gt;
&lt;li&gt;A quantidade de componentes permanecerá fixa depois da construção.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Portanto, ele será &lt;strong&gt;mutável quanto aos valores&lt;/strong&gt;, mas não oferecerá operações que adicionem ou removam dimensões.&lt;/p&gt;

&lt;p&gt;Para fins didáticos também permitiremos:&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="nc"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;representando um vetor sem componentes. Um domínio real poderia rejeitar essa construção caso ela não fizesse sentido.&lt;/p&gt;

&lt;p&gt;A partir daqui, cada novo método deve respeitar essas mesmas decisões. Nesta parte, começaremos pela representação textual; na próxima, continuaremos evoluindo o mesmo &lt;code&gt;Vector&lt;/code&gt; através dos protocolos de tamanho, indexação, iteração e comparação.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Representação: &lt;code&gt;__repr__&lt;/code&gt; e &lt;code&gt;__str__&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Comecemos pelo comportamento mais visível.&lt;/p&gt;

&lt;p&gt;Sem &lt;code&gt;__repr__&lt;/code&gt; ou &lt;code&gt;__str__&lt;/code&gt; customizados:&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;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;no CPython normalmente produz algo parecido com:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;__main__.Vector object at 0x...&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O formato exato dessa representação padrão não deve ser tratado como parte do contrato da nossa classe.&lt;/p&gt;

&lt;p&gt;O que queremos responder é:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Como um &lt;code&gt;Vector&lt;/code&gt; deve se representar textualmente?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Python oferece dois métodos principais para isso.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspecto&lt;/th&gt;
&lt;th&gt;&lt;code&gt;__repr__&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;__str__&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Papel na documentação&lt;/td&gt;
&lt;td&gt;representação &lt;strong&gt;oficial&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;representação &lt;strong&gt;informal&lt;/strong&gt; ou facilmente imprimível&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Objetivo comum&lt;/td&gt;
&lt;td&gt;rica em informação e pouco ambígua&lt;/td&gt;
&lt;td&gt;conveniente e legível&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Uso típico&lt;/td&gt;
&lt;td&gt;REPL, debugging, logs técnicos&lt;/td&gt;
&lt;td&gt;apresentação para leitura humana&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Acionado por&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;repr(v)&lt;/code&gt;, &lt;code&gt;f"{v!r}"&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;str(v)&lt;/code&gt;, &lt;code&gt;print(v)&lt;/code&gt;, &lt;code&gt;f"{v}"&lt;/code&gt;, &lt;code&gt;f"{v!s}"&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A distinção “desenvolvedor versus usuário final” pode ser uma analogia útil, mas não é a definição normativa.&lt;/p&gt;

&lt;p&gt;A documentação define &lt;code&gt;__repr__&lt;/code&gt; como responsável pela representação “oficial” e recomenda, quando possível, uma forma parecida com uma expressão Python capaz de recriar um objeto equivalente. Já &lt;code&gt;__str__&lt;/code&gt; pode produzir uma representação mais conveniente ou concisa (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;Vamos começar por &lt;code&gt;__repr__&lt;/code&gt;:&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;Vector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ... __init__ da seção anterior
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__repr__&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;componentes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;componente&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;componente&lt;/span&gt; &lt;span class="ow"&gt;in&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;_componentes&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&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;Vector(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;componentes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora:&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;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 'Vector(3, 4)'
&lt;/span&gt;
&lt;span class="n"&gt;v&lt;/span&gt;
&lt;span class="c1"&gt;# Vector(3, 4)
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E para dimensões diferentes:&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="nc"&gt;Vector&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;2&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="c1"&gt;# Vector(1, 2, 3)
&lt;/span&gt;
&lt;span class="nc"&gt;Vector&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="c1"&gt;# Vector()
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A representação acompanha os dados realmente armazenados. Não existe mais nenhuma hipótese hardcoded de que um vetor precise possuir apenas &lt;code&gt;x&lt;/code&gt; e &lt;code&gt;y&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Agora adicionamos uma forma mais compacta para &lt;code&gt;__str__&lt;/code&gt;:&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;Vector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# ...
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__str__&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;componentes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;componente&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;componente&lt;/span&gt; &lt;span class="ow"&gt;in&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;_componentes&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&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;(&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;componentes&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso:&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;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# 'Vector(3, 4)'
&lt;/span&gt;
&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# '(3, 4)'
&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;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# (3, 4)
&lt;/span&gt;
&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# '(3, 4)'
&lt;/span&gt;
&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;!s}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# '(3, 4)'
&lt;/span&gt;
&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="si"&gt;!r}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;# 'Vector(3, 4)'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  O fallback de &lt;code&gt;__str__&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Existe ainda uma relação importante entre os dois métodos.&lt;/p&gt;

&lt;p&gt;Se definirmos &lt;code&gt;__repr__&lt;/code&gt;, mas não &lt;code&gt;__str__&lt;/code&gt;, a representação oficial também é utilizada quando uma representação informal é necessária (PYTHON SOFTWARE FOUNDATION, 2026c).&lt;/p&gt;

&lt;p&gt;Por isso, uma classe com apenas:&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;__repr__&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;já melhora tanto:&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="nf"&gt;repr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;quanto:&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="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&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;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O contrário não possui a mesma relação: implementar apenas &lt;code&gt;__str__&lt;/code&gt; não substitui a necessidade de uma representação oficial apropriada.&lt;/p&gt;

&lt;h3&gt;
  
  
  E os containers?
&lt;/h3&gt;

&lt;p&gt;Observe:&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;v&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="c1"&gt;# [Vector(3, 4)]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mesmo que:&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="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;produza:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(3, 4)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;a representação de uma &lt;code&gt;list&lt;/code&gt; utiliza a representação oficial de seus elementos.&lt;/p&gt;

&lt;p&gt;Isso é útil para debugging:&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;vetores&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nc"&gt;Vector&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;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;vetores&lt;/span&gt;
&lt;span class="c1"&gt;# [Vector(1, 2), Vector(3, 4)]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O container consegue mostrar claramente &lt;strong&gt;quais objetos contém&lt;/strong&gt;, sem depender da versão mais informal produzida por &lt;code&gt;__str__&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Conclusão
&lt;/h2&gt;

&lt;p&gt;Ao longo desta parte, saímos da ideia de que métodos como &lt;code&gt;__len__&lt;/code&gt;, &lt;code&gt;__repr__&lt;/code&gt; ou &lt;code&gt;__add__&lt;/code&gt; são apenas nomes especiais que Python chama automaticamente. O ponto central é mais amplo: eles são &lt;strong&gt;pontos de integração entre os nossos tipos e os protocolos da linguagem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Quando escrevemos:&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ou:&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;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ou ainda:&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;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nome&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;não estamos apenas chamando funções ou operadores isolados. Estamos** acionando comportamentos definidos pelo modelo de dados, cada um com suas próprias regras de resolução e seus próprios contratos**.&lt;/p&gt;

&lt;p&gt;Foi por isso que, ao longo do artigo, vimos que:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;len(obj)&lt;/code&gt; não é equivalente a uma chamada comum de &lt;code&gt;obj.__len__()&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__new__&lt;/code&gt; e &lt;code&gt;__init__&lt;/code&gt; participam de momentos diferentes da criação de uma instância;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__del__&lt;/code&gt; não deve ser confundido com gerenciamento determinístico de recursos;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NotImplemented&lt;/code&gt; faz parte da negociação entre operandos;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__getattr__&lt;/code&gt; funciona como fallback no acesso a atributos;&lt;/li&gt;
&lt;li&gt;descriptors formam outro protocolo por trás de mecanismos como &lt;code&gt;property&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;__repr__&lt;/code&gt; e &lt;code&gt;__str__&lt;/code&gt; representam contratos diferentes para a representação textual de um objeto.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esses exemplos também mostram por que &lt;strong&gt;implementar um dunder method não significa apenas usar o nome correto&lt;/strong&gt;. Para participar bem de um protocolo, a classe precisa respeitar a semântica esperada daquela operação.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;Vector&lt;/code&gt; introduzido no final desta parte será nosso ponto de continuidade.&lt;/p&gt;

&lt;p&gt;Até aqui, definimos como ele armazena seus componentes e como deve se representar:&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="nc"&gt;Vector&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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;ou, em sua forma informal:&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="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;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Na próxima parte, a pergunta muda.&lt;/p&gt;

&lt;p&gt;Em vez de observar protocolos de forma mais isolada, vamos acompanhar o que acontece quando &lt;strong&gt;vários deles precisam coexistir no mesmo tipo&lt;/strong&gt;. Vamos decidir, entre outras coisas:&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="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;deve representar o quê?&lt;/p&gt;

&lt;p&gt;Como:&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;v&lt;/span&gt;&lt;span class="p"&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;v&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&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;v&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;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;devem se comportar?&lt;/p&gt;

&lt;p&gt;O que torna:&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;for&lt;/span&gt; &lt;span class="n"&gt;componente&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;possível?&lt;/p&gt;

&lt;p&gt;E se o &lt;code&gt;Vector&lt;/code&gt; for mutável, como isso afeta:&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;v1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;e sua possibilidade de ser usado em um &lt;code&gt;set&lt;/code&gt; ou como chave de &lt;code&gt;dict&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;É nesse ponto que os protocolos deixam de parecer recursos independentes e passam a revelar algo ainda mais importante sobre o modelo de dados: &lt;strong&gt;decisões de comportamento em uma parte da classe podem impor consequências sobre várias outras&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Na Parte 3, continuaremos justamente daí, evoluindo o mesmo &lt;code&gt;Vector&lt;/code&gt; através dos protocolos de tamanho, indexação, iteração, igualdade e hashing.&lt;/p&gt;




&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.1. Objects, values and types&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026a. Disponível em: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#objects-values-and-types" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#objects-values-and-types&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.3.13. Special method lookup&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026b. Disponível em: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#special-method-lookup" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#special-method-lookup&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.3.1. Basic customization&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026c. Disponível em: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#basic-customization" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#basic-customization&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.3.9. With Statement Context Managers&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026d. Disponível em: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#with-statement-context-managers" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#with-statement-context-managers&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.2.2. NotImplemented&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026e. Disponível em: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#notimplemented" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#notimplemented&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.3.8. Emulating numeric types&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026f. Disponível em: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#emulating-numeric-types" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#emulating-numeric-types&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;NotImplementedError&lt;/strong&gt;. In: &lt;em&gt;Built-in Exceptions — Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026g. Disponível em: &lt;a href="https://docs.python.org/3.14/library/exceptions.html#NotImplementedError" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/library/exceptions.html#NotImplementedError&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3.3.2. Customizing attribute access&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026h. Disponível em: &lt;a href="https://docs.python.org/3.14/reference/datamodel.html#customizing-attribute-access" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/datamodel.html#customizing-attribute-access&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;9.6. Private Variables&lt;/strong&gt;. In: &lt;em&gt;The Python Tutorial — Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026i. Disponível em: &lt;a href="https://docs.python.org/3.14/tutorial/classes.html#private-variables" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/tutorial/classes.html#private-variables&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;7.8. The raise statement&lt;/strong&gt;. In: &lt;em&gt;Python Language Reference — Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026j. Disponível em: &lt;a href="https://docs.python.org/3.14/reference/simple_stmts.html#the-raise-statement" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/reference/simple_stmts.html#the-raise-statement&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;Descriptor Guide — Descriptor protocol&lt;/strong&gt;. In: &lt;em&gt;Python 3.14.7 documentation&lt;/em&gt;. [S. l.]: Python Software Foundation, 2026k. Disponível em: &lt;a href="https://docs.python.org/3.14/howto/descriptor.html#descriptor-protocol" rel="noopener noreferrer"&gt;https://docs.python.org/3.14/howto/descriptor.html#descriptor-protocol&lt;/a&gt;. Acesso em: 14 ago. 2026.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota editorial:&lt;/strong&gt; Este artigo foi desenvolvido e revisado pelo autor com apoio de IA nas etapas de pesquisa, auditoria técnica e revisão editorial. As afirmações técnicas foram verificadas com base nas fontes oficiais indicadas nas referências.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>python</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Python Data Model - Part 1</title>
      <dc:creator>Bruno Teixeira Lopes</dc:creator>
      <pubDate>Tue, 28 Jul 2026 22:54:43 +0000</pubDate>
      <link>https://dev.to/brunotlps/python-data-model-part-1-492k</link>
      <guid>https://dev.to/brunotlps/python-data-model-part-1-492k</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://dev.to/brunotlps/modelo-de-dados-python-parte-1-3ela"&gt;Leia a versão em português deste artigo aqui&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;Ever wondered why modifying a list inside a function changes the original list, but modifying a number doesn't? You've just run into one of the most fundamental — and most misunderstood — concepts in Python: its &lt;strong&gt;data model&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Understanding how Python represents, identifies, and compares objects isn't just theory: it's what saves you from subtle bugs related to aliasing, incorrect comparisons, and unexpected side effects in mutable containers.&lt;/p&gt;

&lt;p&gt;In this first article of the series, we'll build the foundation you need for that: what an object actually is in Python, the difference between identity and equality, what mutability really means, how an object is born and dies, and how all of this connects once objects live inside containers.&lt;/p&gt;

&lt;p&gt;This article assumes you're already comfortable with basic Python syntax (variables, lists, dictionaries, functions). If that's you, let's get straight to it.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Everything is an object
&lt;/h2&gt;

&lt;p&gt;The data model defines how values are represented and how they behave in Python. &lt;strong&gt;Every piece of data your program handles&lt;/strong&gt; is an &lt;strong&gt;object&lt;/strong&gt;: numbers, strings, lists, functions, classes, and even modules (PYTHON SOFTWARE FOUNDATION, 2026a).&lt;/p&gt;

&lt;p&gt;Every Python object has three essential characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity&lt;/strong&gt;: the object's address in memory. Checked with &lt;code&gt;id(object_name)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type&lt;/strong&gt;: defines which values and operations the object supports. Checked with &lt;code&gt;type(object_name)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value&lt;/strong&gt;: the content the object represents, which may or may not change depending on the object's &lt;strong&gt;mutability&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Type affects nearly every aspect of an object's behavior. That's even true for identity: some types have a single instance shared across the entire program, which is why the correct way to compare them is by identity (&lt;code&gt;is&lt;/code&gt;), not equality (&lt;code&gt;==&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;None&lt;/code&gt; represents the absence of a value;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NotImplemented&lt;/code&gt; signals that a special operation doesn't support the operands it received;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;...&lt;/code&gt;, also called &lt;code&gt;Ellipsis&lt;/code&gt;, can be used as a sentinel and in extended slicing operations.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;# &amp;lt;class 'NoneType'&amp;gt;
&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NotImplemented&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# &amp;lt;class 'NotImplementedType'&amp;gt;
&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;             &lt;span class="c1"&gt;# &amp;lt;class 'ellipsis'&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For single-instance types, &lt;code&gt;is&lt;/code&gt; is always the recommended way to check for absence of value:&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;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt;  &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;# WRONG
&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;# CORRECT
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Identity vs Equality
&lt;/h2&gt;

&lt;p&gt;As we just saw, an object's identity refers to its memory address: &lt;code&gt;id(x)&lt;/code&gt; returns an &lt;code&gt;int&lt;/code&gt; representing the memory location where &lt;code&gt;x&lt;/code&gt; is stored. Equality, on the other hand, checks whether the values of two objects are the same, using the &lt;strong&gt;magic method&lt;/strong&gt; &lt;code&gt;__eq__&lt;/code&gt; — we'll dig deeper into that method in upcoming chapters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;is&lt;/code&gt;: compares identity.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;==&lt;/code&gt;: compares content or value.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This distinction between identity and equality is the foundation for understanding &lt;strong&gt;mutability&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Mutable vs Immutable
&lt;/h2&gt;

&lt;p&gt;An object's mutability is determined by its type. A &lt;strong&gt;mutable&lt;/strong&gt; object can have its value changed after creation. An &lt;strong&gt;immutable&lt;/strong&gt; object cannot be modified; any operation on it produces a new object (PYTHON SOFTWARE FOUNDATION, 2026b).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Immutable&lt;/th&gt;
&lt;th&gt;Mutable&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NoneType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;list&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dict&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;complex&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;set&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;str&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;range&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bytearray&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;bytes&lt;/code&gt;, &lt;code&gt;frozenset&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Mutation&lt;/strong&gt; changes the object itself; &lt;strong&gt;reassignment&lt;/strong&gt; makes the name point to a new object.&lt;/p&gt;

&lt;p&gt;Example with a mutable object:&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;items&lt;/span&gt; &lt;span class="o"&gt;=&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="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="c1"&gt;# list is mutable
&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;
&lt;span class="n"&gt;items&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="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="n"&gt;items&lt;/span&gt;  &lt;span class="c1"&gt;# ['a', 'b', 'c']
&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;  &lt;span class="c1"&gt;# ['a', 'b', 'c']
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example with an immutable object:&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;  &lt;span class="c1"&gt;# int is immutable
&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="c1"&gt;# a new object with value 15 is created; total now points to it
&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;  &lt;span class="c1"&gt;# 15
&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;  &lt;span class="c1"&gt;# 10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Immutable objects can hold &lt;strong&gt;references&lt;/strong&gt; to mutable objects, because immutability in Python affects only the object's reference structure, not the content it points to.&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;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alyne&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;record&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="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SQL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;record&lt;/span&gt;  &lt;span class="c1"&gt;# ("Alyne", ["Python", "SQL"])
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tuple &lt;code&gt;record&lt;/code&gt; still points to the same references — only the inner list was changed.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Object life cycle
&lt;/h2&gt;

&lt;p&gt;An object's life cycle in Python has four main phases: creation and memory allocation, attribute initialization, active use throughout the program via references, and destruction with memory release controlled by reference counting and the garbage collector.&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;sys&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&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;2&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="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getrefcount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# number of active references to the object (includes getrefcount's own temporary reference)
&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;a&lt;/span&gt;  &lt;span class="c1"&gt;# new reference to the same object
&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getrefcount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# the count goes up, since 'a' and 'b' now point to the same object
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When an object becomes unreachable — that is, when its reference count reaches zero — it can be garbage collected by CPython through a reference-counting scheme with delayed detection of cyclically linked garbage. This cyclic collection is optional and doesn't guarantee that all garbage containing circular references will actually be collected.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Containers
&lt;/h2&gt;

&lt;p&gt;Container objects are data structures capable of holding other objects — in other words, objects that contain references to others.&lt;/p&gt;

&lt;p&gt;They can hold values of different types at the same time, support iteration through loops, and it's common to use the &lt;code&gt;in&lt;/code&gt; operator to efficiently check whether an item is present in a container — a check that, internally, relies on equality (&lt;code&gt;==&lt;/code&gt;), not identity.&lt;/p&gt;

&lt;p&gt;Main container types:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Lists (&lt;code&gt;list&lt;/code&gt;)&lt;/strong&gt;: ordered, mutable sequences, defined with square brackets &lt;code&gt;[]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tuples (&lt;code&gt;tuple&lt;/code&gt;)&lt;/strong&gt;: ordered, immutable sequences, defined with parentheses &lt;code&gt;()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dictionaries (&lt;code&gt;dict&lt;/code&gt;)&lt;/strong&gt;: collections of key-value pairs, defined with curly braces &lt;code&gt;{}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sets (&lt;code&gt;set&lt;/code&gt;)&lt;/strong&gt;: collections of unique, unordered elements, also defined with curly braces &lt;code&gt;{}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Watch out for a common gotcha: an empty &lt;code&gt;{}&lt;/code&gt; creates a &lt;code&gt;dict&lt;/code&gt;, not a &lt;code&gt;set&lt;/code&gt;. To create an empty set, you need to use &lt;code&gt;set()&lt;/code&gt; explicitly.&lt;/p&gt;

&lt;p&gt;Since containers hold &lt;strong&gt;references&lt;/strong&gt;, not copies, everything we've covered about identity, equality, and mutability applies directly here: modifying a mutable object inside a container affects every variable that references that same object — even if the container itself is immutable, as we saw with the tuple example in section 4.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Conclusion
&lt;/h2&gt;

&lt;p&gt;Identity, equality, mutability, life cycle, and containers aren't isolated topics — they're facets of the same core concept: in Python, variables are references to objects, not boxes holding values. Understanding that is what lets you predict, with confidence, when a change will propagate and when it will produce a brand-new object.&lt;/p&gt;

&lt;p&gt;That foundation is what the next step of the series builds on: &lt;strong&gt;magic methods&lt;/strong&gt; (dunder methods), the protocol Python uses behind seemingly simple operations like &lt;code&gt;len(obj)&lt;/code&gt;, &lt;code&gt;obj[key]&lt;/code&gt;, or &lt;code&gt;for item in obj&lt;/code&gt;. In Part 2, we'll see how these methods let objects you create behave just like the language's built-in types.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3. Data model&lt;/strong&gt;. In: &lt;strong&gt;Python 3.14.6 Documentation&lt;/strong&gt;. [S. l.]: Python Software Foundation, 2026a. Available at: &lt;a href="https://docs.python.org/3/reference/datamodel.html" rel="noopener noreferrer"&gt;https://docs.python.org/3/reference/datamodel.html&lt;/a&gt;. Accessed on: Jul. 28, 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;Built-in Types&lt;/strong&gt;. In: &lt;strong&gt;Python 3.14.6 Documentation&lt;/strong&gt;. [S. l.]: Python Software Foundation, 2026b. Available at: &lt;a href="https://docs.python.org/3/library/stdtypes.html" rel="noopener noreferrer"&gt;https://docs.python.org/3/library/stdtypes.html&lt;/a&gt;. Accessed on: Jul. 28, 2026.&lt;/p&gt;

</description>
      <category>python</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Modelo de Dados Python - Parte 1</title>
      <dc:creator>Bruno Teixeira Lopes</dc:creator>
      <pubDate>Tue, 28 Jul 2026 22:51:54 +0000</pubDate>
      <link>https://dev.to/brunotlps/modelo-de-dados-python-parte-1-3ela</link>
      <guid>https://dev.to/brunotlps/modelo-de-dados-python-parte-1-3ela</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;a href="https://claude.ai/chat/LINK_DO_ARTIGO_EM_EN" rel="noopener noreferrer"&gt;Read this article in English here&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Introdução
&lt;/h2&gt;

&lt;p&gt;Se você já se perguntou por que alterar uma lista dentro de uma função muda a lista original, mas alterar um número não, você esbarrou em um dos conceitos mais fundamentais (e mais mal compreendidos) de Python: o &lt;strong&gt;modelo de dados&lt;/strong&gt; da linguagem.&lt;/p&gt;

&lt;p&gt;Entender como Python representa, identifica e compara objetos não é só teoria: é o que evita bugs sutis relacionados a aliasing, comparações incorretas e efeitos colaterais inesperados em containers mutáveis.&lt;/p&gt;

&lt;p&gt;Neste primeiro artigo da série, vamos construir a base necessária para isso: o que é um objeto em Python, a diferença entre identidade e igualdade, o que realmente significa mutabilidade, como um objeto nasce e morre, e como tudo isso se conecta quando objetos são armazenados em containers.&lt;/p&gt;

&lt;p&gt;Este artigo assume que você já tem familiaridade com a sintaxe básica de Python (variáveis, listas, dicionários, funções). Se esse é o seu caso, vamos direto ao ponto.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Tudo é objeto
&lt;/h2&gt;

&lt;p&gt;O modelo de dados define como os valores são representados e como se comportam em Python. &lt;strong&gt;Todo dado manipulado pelo programa&lt;/strong&gt; é um &lt;strong&gt;objeto&lt;/strong&gt;: números, strings, listas, funções, classes e até módulos (PYTHON SOFTWARE FOUNDATION, 2026a).&lt;/p&gt;

&lt;p&gt;Um objeto Python conta com três características essenciais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identidade&lt;/strong&gt;: distingue um objeto de todos os outros e permanece a mesma durante toda a sua existência. Pode ser consultada com id(nome_objeto). No CPython, especificamente, id() corresponde ao endereço de memória do objeto.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tipo&lt;/strong&gt;: define quais valores e operações o objeto aceita. Consultado com &lt;code&gt;type(nome_objeto)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Valor&lt;/strong&gt;: conteúdo representado pelo objeto, podendo ou não ser alterado a depender da &lt;strong&gt;mutabilidade do objeto&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Os tipos afetam quase todos os aspectos do comportamento do objeto. Isso vale até para a identidade: alguns tipos possuem uma única instância em todo o programa, e por isso a forma correta de compará-los é por identidade (&lt;code&gt;is&lt;/code&gt;), não por igualdade (&lt;code&gt;==&lt;/code&gt;):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;None&lt;/code&gt; representa ausência de valor;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NotImplemented&lt;/code&gt; informa que uma operação especial não oferece suporte aos operandos recebidos;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;...&lt;/code&gt;, também chamado de &lt;code&gt;Ellipsis&lt;/code&gt;, pode ser usado como uma sentinela e em operações especiais de fatiamento.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c1"&gt;# &amp;lt;class 'NoneType'&amp;gt;
&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;NotImplemented&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# &amp;lt;class 'NotImplementedType'&amp;gt;
&lt;/span&gt;&lt;span class="nf"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;             &lt;span class="c1"&gt;# &amp;lt;class 'ellipsis'&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para instâncias únicas, o operador &lt;code&gt;is&lt;/code&gt; é sempre a forma recomendada de checar ausência de valor:&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;x&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt;  &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;# ERRADO
&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="c1"&gt;# CORRETO
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Identidade vs Igualdade
&lt;/h2&gt;

&lt;p&gt;Como vimos, a identidade distingue um objeto de todos os demais e permanece estável durante sua existência. id(x) retorna um inteiro que representa essa identidade; no CPython, especificamente, esse valor corresponde ao endereço de memória do objeto. Igualdade, por outro lado, verifica a relação de valor definida entre dois objetos através de == — comportamento que pode ser customizado por &lt;strong&gt;eq&lt;/strong&gt;, um dos métodos especiais que veremos nas próximas partes.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;is&lt;/code&gt;: compara identidades.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;==&lt;/code&gt;: compara conteúdo ou valores.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Essa distinção entre identidade e igualdade é a base para entender &lt;strong&gt;mutabilidade&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Mutável vs Imutável
&lt;/h2&gt;

&lt;p&gt;A mutabilidade de um objeto é determinada pelo seu tipo. Um objeto &lt;strong&gt;mutável&lt;/strong&gt; pode ter seu valor alterado depois de criado. Um objeto &lt;strong&gt;imutável&lt;/strong&gt; não pode ser modificado; uma operação sobre ele produz outro objeto (PYTHON SOFTWARE FOUNDATION, 2026b).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Imutáveis&lt;/th&gt;
&lt;th&gt;Mutáveis&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;NoneType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;list&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;dict&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;complex&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;set&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;str&lt;/code&gt;, &lt;code&gt;tuple&lt;/code&gt;, &lt;code&gt;range&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bytearray&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;bytes&lt;/code&gt;, &lt;code&gt;frozenset&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A &lt;strong&gt;mutação&lt;/strong&gt; altera o próprio objeto; a &lt;strong&gt;reatribuição&lt;/strong&gt; faz o nome apontar para um novo objeto.&lt;/p&gt;

&lt;p&gt;Exemplo com objeto mutável:&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;items&lt;/span&gt; &lt;span class="o"&gt;=&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="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="c1"&gt;# list é mutável
&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;
&lt;span class="n"&gt;items&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="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="n"&gt;items&lt;/span&gt;  &lt;span class="c1"&gt;# ['a', 'b', 'c']
&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;  &lt;span class="c1"&gt;# ['a', 'b', 'c']
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exemplo com objeto imutável:&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;  &lt;span class="c1"&gt;# int é imutável
&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;total&lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;  &lt;span class="c1"&gt;# um novo objeto com valor 15 é criado; total passa a apontar para ele
&lt;/span&gt;&lt;span class="n"&gt;total&lt;/span&gt;  &lt;span class="c1"&gt;# 15
&lt;/span&gt;&lt;span class="n"&gt;alias&lt;/span&gt;  &lt;span class="c1"&gt;# 10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Objetos imutáveis podem conter &lt;strong&gt;referências&lt;/strong&gt; a objetos mutáveis, pois a imutabilidade em Python afeta apenas a estrutura de referências do objeto, não o conteúdo interno ao qual ele aponta.&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;record&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alyne&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;record&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="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;SQL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;record&lt;/span&gt;  &lt;span class="c1"&gt;# ("Alyne", ["Python", "SQL"])
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A tupla &lt;code&gt;record&lt;/code&gt; continua apontando para as mesmas referências — apenas a lista interna foi alterada.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Ciclo de vida dos objetos
&lt;/h2&gt;

&lt;p&gt;O ciclo de vida de um objeto começa com sua criação e continua enquanto ele puder ser alcançado pelo programa através de referências. Quando um objeto deixa de ser alcançável, ele pode se tornar elegível para coleta, mas Python não garante que essa liberação aconteça imediatamente.&lt;/p&gt;

&lt;p&gt;No CPython, especificamente, o gerenciamento de memória utiliza principalmente contagem de referências, complementada por um garbage collector capaz de detectar ciclos de referências. Por isso, muitos objetos são liberados assim que deixam de possuir referências, enquanto ciclos podem exigir uma etapa adicional de coleta. Esse é um detalhe da implementação CPython, não uma garantia geral da linguagem.&lt;/p&gt;

&lt;p&gt;Podemos observar parte deste comportamento no CPython com:&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;sys&lt;/span&gt;

&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&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;2&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="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getrefcount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# número de referências ativas ao objeto (inclui a referência temporária do próprio getrefcount)
&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;a&lt;/span&gt;  &lt;span class="c1"&gt;# nova referência para o mesmo objeto
&lt;/span&gt;&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getrefcount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# o valor aumenta, pois agora 'a' e 'b' apontam para o mesmo objeto
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  6. Containers
&lt;/h2&gt;

&lt;p&gt;Objetos containers são estruturas de dados capazes de armazenar outros objetos, ou seja, são objetos que contêm referências a outros.&lt;/p&gt;

&lt;p&gt;Eles podem guardar dados de tipos diferentes ao mesmo tempo, permitem percorrer seus elementos usando laços de repetição, e é muito comum utilizar o operador in para verificar se um item está presente em um container. A forma exata dessa busca depende do tipo e dos protocolos que ele implementa (comportamento que aprofundaremos nas próximas partes).&lt;/p&gt;

&lt;p&gt;Tipos principais de containers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Listas (&lt;code&gt;list&lt;/code&gt;)&lt;/strong&gt;: sequências ordenadas e mutáveis, definidas por colchetes &lt;code&gt;[]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tuplas (&lt;code&gt;tuple&lt;/code&gt;)&lt;/strong&gt;: sequências ordenadas e imutáveis, definidas por parênteses &lt;code&gt;()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dicionários (&lt;code&gt;dict&lt;/code&gt;)&lt;/strong&gt;: coleções de pares chave-valor, definidos por chaves &lt;code&gt;{}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conjuntos (&lt;code&gt;set&lt;/code&gt;)&lt;/strong&gt;: coleções de elementos únicos e não ordenados, também definidos por chaves &lt;code&gt;{}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Atenção a uma pegadinha comum: &lt;code&gt;{}&lt;/code&gt; vazio cria um &lt;code&gt;dict&lt;/code&gt;, não um &lt;code&gt;set&lt;/code&gt;. Para criar um conjunto vazio, é preciso usar &lt;code&gt;set()&lt;/code&gt; explicitamente.&lt;/p&gt;

&lt;p&gt;Como containers guardam &lt;strong&gt;referências&lt;/strong&gt; e não cópias, tudo o que vimos sobre identidade, igualdade e mutabilidade se aplica de forma direta aqui: alterar um objeto mutável dentro de um container afeta todas as variáveis que referenciam esse mesmo objeto — mesmo que o container em si seja imutável, como vimos no exemplo da tupla na seção 4.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Conclusão
&lt;/h2&gt;

&lt;p&gt;Identidade, igualdade, mutabilidade, ciclo de vida e containers são faces do mesmo conceito central: em Python, variáveis são referências a objetos, não caixas que guardam valores. Entender isso é o que permite prever, com segurança, quando uma alteração vai se propagar e quando vai gerar um objeto novo.&lt;/p&gt;

&lt;p&gt;Essa base sustenta o próximo passo da série: entender como os métodos especiais permitem que nossos tipos participem dos protocolos da própria linguagem. Na Parte 2, veremos o que existe por trás de operações como len(obj), da criação e finalização de instâncias, da sobrecarga de operadores, do acesso a atributos e das representações produzidas por repr() e str().&lt;/p&gt;

&lt;h2&gt;
  
  
  Referências
&lt;/h2&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;3. Modelo de dados&lt;/strong&gt;. In: &lt;strong&gt;Documentação Python 3.14.6&lt;/strong&gt;. [S. l.]: Python Software Foundation, 2026a. Disponível em: &lt;a href="https://docs.python.org/pt-br/3/reference/datamodel.html" rel="noopener noreferrer"&gt;https://docs.python.org/pt-br/3/reference/datamodel.html&lt;/a&gt;. Acesso em: 28 jul. 2026.&lt;/p&gt;

&lt;p&gt;PYTHON SOFTWARE FOUNDATION. &lt;strong&gt;Tipos embutidos&lt;/strong&gt;. In: &lt;strong&gt;Documentação Python 3.14.6&lt;/strong&gt;. [S. l.]: Python Software Foundation, 2026b. Disponível em: &lt;a href="https://docs.python.org/pt-br/3/library/stdtypes.html" rel="noopener noreferrer"&gt;https://docs.python.org/pt-br/3/library/stdtypes.html&lt;/a&gt;. Acesso em: 28 jul. 2026.&lt;/p&gt;

</description>
      <category>python</category>
      <category>tutorial</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
