<?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: Anton Shcherbatov</title>
    <description>The latest articles on DEV Community by Anton Shcherbatov (@storvus).</description>
    <link>https://dev.to/storvus</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%2F1091925%2F1235b56d-8d46-4677-abc4-2e8aa9670d6b.jpeg</url>
      <title>DEV Community: Anton Shcherbatov</title>
      <link>https://dev.to/storvus</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/storvus"/>
    <language>en</language>
    <item>
      <title>Why Does `+=` Sometimes Create a New Object and Sometimes Not?</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Mon, 20 Jul 2026 18:41:04 +0000</pubDate>
      <link>https://dev.to/storvus/why-does-sometimes-create-a-new-object-and-sometimes-not-i6</link>
      <guid>https://dev.to/storvus/why-does-sometimes-create-a-new-object-and-sometimes-not-i6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article assumes you're already comfortable writing simple Python programs and know the basics (&lt;code&gt;if&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;, functions, and lists). Here we're not learning &lt;strong&gt;how&lt;/strong&gt; to use Python - we're learning &lt;strong&gt;why&lt;/strong&gt; it behaves the way it does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Try to guess what this code prints.&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="mi"&gt;10&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Many people expect &lt;code&gt;+=&lt;/code&gt; to simply change the value of the variable.&lt;/p&gt;

&lt;p&gt;But if you look at the result of &lt;code&gt;id()&lt;/code&gt;, you'll find that it's now a different object.&lt;/p&gt;

&lt;p&gt;It seems as though &lt;code&gt;+=&lt;/code&gt; created a brand-new object.&lt;/p&gt;

&lt;p&gt;Now consider a very similar 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;numbers&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This time, &lt;code&gt;id()&lt;/code&gt; stays exactly the same.&lt;/p&gt;

&lt;p&gt;Now the behavior is the complete opposite.&lt;/p&gt;

&lt;p&gt;In one case, a new object appears.&lt;/p&gt;

&lt;p&gt;In the other, the existing object is reused.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;




&lt;p&gt;If you've followed the previous articles, the answer is already within reach.&lt;/p&gt;

&lt;p&gt;We know two important things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a name doesn't store an object - it simply refers to one;&lt;/li&gt;
&lt;li&gt;Python has both mutable and immutable objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second point turns out to be the key.&lt;/p&gt;




&lt;p&gt;Let's start with a number.&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="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The name &lt;code&gt;x&lt;/code&gt; refers to the object &lt;code&gt;10&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x ───► 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;/div&gt;



&lt;p&gt;At first glance, it looks like the number itself has changed.&lt;/p&gt;

&lt;p&gt;But numbers are immutable objects.&lt;/p&gt;

&lt;p&gt;We've already learned that immutable objects cannot be modified.&lt;/p&gt;

&lt;p&gt;So Python does something else instead.&lt;/p&gt;

&lt;p&gt;First, it computes:&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;10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then it creates a new object whose value is &lt;code&gt;15&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, the name &lt;code&gt;x&lt;/code&gt; is rebound to that object.&lt;/p&gt;

&lt;p&gt;Conceptually, the process looks 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;x ───► 10

↓

create object 15

↓

x ───► 15
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The original object is never modified.&lt;/p&gt;

&lt;p&gt;That's why &lt;code&gt;id()&lt;/code&gt; changes.&lt;/p&gt;




&lt;p&gt;Now let's look at a list.&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;numbers&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we execute:&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;numbers&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many people expect this to behave just like the previous example.&lt;/p&gt;

&lt;p&gt;But lists are mutable objects.&lt;/p&gt;

&lt;p&gt;That means Python can modify the existing object instead of creating a new one.&lt;/p&gt;

&lt;p&gt;Conceptually, it's very similar to writing:&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;numbers&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="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;Or, when multiple elements are involved:&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;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&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;The list itself remains the same object.&lt;/p&gt;

&lt;p&gt;Only its contents change.&lt;/p&gt;

&lt;p&gt;That's why &lt;code&gt;id()&lt;/code&gt; stays the same.&lt;/p&gt;




&lt;p&gt;Let's compare the two cases side by side.&lt;/p&gt;

&lt;p&gt;With numbers:&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="mi"&gt;10&lt;/span&gt;

&lt;span class="n"&gt;before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;

&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&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;before&lt;/code&gt; and &lt;code&gt;after&lt;/code&gt; will be different.&lt;/p&gt;

&lt;p&gt;With lists:&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;numbers&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="n"&gt;before&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, &lt;code&gt;before&lt;/code&gt; and &lt;code&gt;after&lt;/code&gt; are identical.&lt;/p&gt;




&lt;p&gt;This reveals an important principle.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;+=&lt;/code&gt; operator doesn't, by itself, determine whether a new object will be created.&lt;/p&gt;

&lt;p&gt;Instead, it asks the object to perform an in-place addition &lt;strong&gt;if possible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;What happens next depends entirely on the object itself.&lt;/p&gt;

&lt;p&gt;If the object can be modified, Python modifies it.&lt;/p&gt;

&lt;p&gt;If it can't, Python creates a new object instead.&lt;/p&gt;

&lt;p&gt;That's why the exact same operator behaves differently in different situations.&lt;/p&gt;




&lt;p&gt;There's one more interesting example.&lt;/p&gt;

&lt;p&gt;Consider this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;numbers&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="n"&gt;other&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt;

&lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="nf"&gt;print&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What do you think it prints?&lt;/p&gt;

&lt;p&gt;If you've been following the previous articles, you already know the answer:&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;+=&lt;/code&gt; modified the existing list.&lt;/p&gt;

&lt;p&gt;Both names continued to refer to the same object.&lt;/p&gt;

&lt;p&gt;Now compare that with numbers:&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="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;5&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;y&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 python"&gt;&lt;code&gt;&lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, a new object was created.&lt;/p&gt;

&lt;p&gt;The name &lt;code&gt;x&lt;/code&gt; now refers to the new object, while &lt;code&gt;y&lt;/code&gt; continues referring to the original one.&lt;/p&gt;




&lt;p&gt;We can now summarize the rule.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;+=&lt;/code&gt; operator does &lt;strong&gt;not&lt;/strong&gt; guarantee that an existing object will be modified.&lt;/p&gt;

&lt;p&gt;Nor does it guarantee that a new object will be created.&lt;/p&gt;

&lt;p&gt;It simply invokes the behavior defined by the object itself.&lt;/p&gt;

&lt;p&gt;For mutable objects, that usually means modifying the object in place.&lt;/p&gt;

&lt;p&gt;For immutable objects, it means creating a new object instead.&lt;/p&gt;




&lt;p&gt;If this still feels a little magical, don't worry.&lt;/p&gt;

&lt;p&gt;There's no magic involved.&lt;/p&gt;

&lt;p&gt;Every Python object defines how it responds to different operations.&lt;/p&gt;

&lt;p&gt;That's why the very same operator can produce completely different behavior depending on the object it's working with.&lt;/p&gt;




&lt;p&gt;This naturally leads to another interesting question.&lt;/p&gt;

&lt;p&gt;We already know that objects can be copied.&lt;/p&gt;

&lt;p&gt;But what does a "copy" actually mean?&lt;/p&gt;

&lt;p&gt;If you copy a list, are nested lists copied too?&lt;/p&gt;

&lt;p&gt;And why does modifying a copy sometimes seem to change the original?&lt;/p&gt;

&lt;p&gt;That's exactly what we'll explore in the next article.&lt;/p&gt;

</description>
      <category>python</category>
      <category>types</category>
      <category>immutable</category>
      <category>mutable</category>
    </item>
    <item>
      <title>Why You Shouldn't Use `def func(items=[])`</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Sun, 19 Jul 2026 09:31:29 +0000</pubDate>
      <link>https://dev.to/storvus/why-you-shouldnt-use-def-funcitems-278c</link>
      <guid>https://dev.to/storvus/why-you-shouldnt-use-def-funcitems-278c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;We assume you already know how to write simple Python programs and understand basic syntax (if, for, functions, lists). Here, we're not discussing how to use the language, but why it works the way it does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Try to guess what this code prints:&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;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&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="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="n"&gt;item&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;items&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&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;If you've never encountered this behavior before, you might expect something 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="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="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="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;Each function call looks independent from the previous one.&lt;/p&gt;

&lt;p&gt;However, Python produces a very different result:&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;1&lt;/span&gt;&lt;span class="p"&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks as if the list somehow "remembers" previous function calls.&lt;/p&gt;

&lt;p&gt;But why does this happen?&lt;/p&gt;




&lt;p&gt;If you look at this example in isolation, it might seem like Python functions have some kind of hidden memory.&lt;/p&gt;

&lt;p&gt;In reality, there is nothing magical going on.&lt;/p&gt;

&lt;p&gt;To understand this behavior, we only need to recall two ideas from previous articles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;variables don't store objects, they refer to them;&lt;/li&gt;
&lt;li&gt;lists are mutable objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, these two facts fully explain what's happening.&lt;/p&gt;




&lt;p&gt;When Python encounters a function definition:&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;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&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="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the default list is created &lt;strong&gt;exactly once&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not on every function call.&lt;/p&gt;

&lt;p&gt;Not each time &lt;code&gt;add()&lt;/code&gt; is executed.&lt;/p&gt;

&lt;p&gt;But at the moment the function is defined.&lt;/p&gt;

&lt;p&gt;We can think of it 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;add
 │
 └────► items ───► []
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function parameter &lt;code&gt;items&lt;/code&gt; is bound to a single list object.&lt;/p&gt;

&lt;p&gt;Now the first call happens:&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;add&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since no second argument is provided, Python uses the existing default list.&lt;/p&gt;

&lt;p&gt;After &lt;code&gt;append()&lt;/code&gt;, it looks 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;items ───► [1]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function finishes execution.&lt;/p&gt;

&lt;p&gt;But the list does not disappear.&lt;/p&gt;

&lt;p&gt;It continues to exist.&lt;/p&gt;




&lt;p&gt;Now the second call happens:&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;add&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One might expect Python to create a new empty list.&lt;/p&gt;

&lt;p&gt;But it doesn't.&lt;/p&gt;

&lt;p&gt;The same object is reused.&lt;/p&gt;

&lt;p&gt;Now the list becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;items ───► [1, 2]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The third call behaves the same way.&lt;/p&gt;

&lt;p&gt;The same list keeps being modified:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;items ───► [1, 2, 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why each call appears to "remember" previous results.&lt;/p&gt;




&lt;p&gt;It's important to notice that the issue is not with functions themselves.&lt;/p&gt;

&lt;p&gt;If we write the same logic without a function, nothing surprising happens:&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="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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&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="mi"&gt;3&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;items&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 python"&gt;&lt;code&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We already know why this happens.&lt;/p&gt;

&lt;p&gt;A list is a mutable object.&lt;/p&gt;

&lt;p&gt;Each &lt;code&gt;append()&lt;/code&gt; modifies the same object instead of creating a new one.&lt;/p&gt;

&lt;p&gt;The function behaves exactly the same way.&lt;/p&gt;

&lt;p&gt;The only difference is that the list was created earlier than many people expect.&lt;/p&gt;




&lt;p&gt;So how do we write this correctly?&lt;/p&gt;

&lt;p&gt;Python has a widely accepted pattern for this case.&lt;/p&gt;

&lt;p&gt;Instead of using a mutable default value, we use &lt;code&gt;None&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;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;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&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="n"&gt;item&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;items&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now each call without an explicit list creates a new one.&lt;/p&gt;

&lt;p&gt;The behavior becomes predictable:&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&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;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;add&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;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;1&lt;/span&gt;&lt;span class="p"&gt;]&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="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;You might wonder why Python behaves this way at all.&lt;/p&gt;

&lt;p&gt;Why not create a new list automatically for each function call?&lt;/p&gt;

&lt;p&gt;The reason is simple: default argument values are objects like everything else in Python.&lt;/p&gt;

&lt;p&gt;They are created once at function definition time and then reused.&lt;/p&gt;

&lt;p&gt;This makes the behavior consistent and efficient.&lt;/p&gt;

&lt;p&gt;For immutable objects like numbers or strings, this behavior is usually invisible.&lt;/p&gt;

&lt;p&gt;But once a mutable object like a list, dictionary, or set is used as a default value, the effect becomes observable.&lt;/p&gt;




&lt;p&gt;From everything we've learned so far, nothing new is actually happening here.&lt;/p&gt;

&lt;p&gt;There is an object.&lt;/p&gt;

&lt;p&gt;There is a reference to that object.&lt;/p&gt;

&lt;p&gt;The object is mutable.&lt;/p&gt;

&lt;p&gt;So every function call modifies the same shared list.&lt;/p&gt;

&lt;p&gt;This is why experienced Python developers almost never use mutable objects as default argument values.&lt;/p&gt;




&lt;p&gt;At this point, we know enough to move one step further.&lt;/p&gt;

&lt;p&gt;We've repeatedly said that lists can be modified in place.&lt;/p&gt;

&lt;p&gt;But is that always true?&lt;/p&gt;

&lt;p&gt;For example, what happens here?&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;numbers&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="n"&gt;numbers&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Is the existing list modified, or is a new list created?&lt;/p&gt;

&lt;p&gt;And what if we replace the list with a number?&lt;/p&gt;

&lt;p&gt;On the surface, the operation looks the same - but the behavior can be very different.&lt;/p&gt;

&lt;p&gt;That's exactly what we'll explore in the next article.&lt;/p&gt;

</description>
      <category>python</category>
      <category>list</category>
      <category>function</category>
      <category>default</category>
    </item>
    <item>
      <title>Identity and Equality in Python</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Fri, 17 Jul 2026 10:06:33 +0000</pubDate>
      <link>https://dev.to/storvus/identity-and-equality-in-python-4o3m</link>
      <guid>https://dev.to/storvus/identity-and-equality-in-python-4o3m</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;We assume you already know how to write simple Python programs and understand basic syntax (if, for, functions, lists). Here, we're not discussing how to use the language, but why it works the way it does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you ask a beginner what the difference is between &lt;code&gt;is&lt;/code&gt; and &lt;code&gt;==&lt;/code&gt;, you'll often hear something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"&lt;code&gt;==&lt;/code&gt; compares values, while &lt;code&gt;is&lt;/code&gt; compares references."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It's a common explanation.&lt;/p&gt;

&lt;p&gt;And while it points in the right direction, it isn't quite accurate.&lt;/p&gt;

&lt;p&gt;Let's see what's really happening.&lt;/p&gt;

&lt;p&gt;We'll start with a simple 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;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;b&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="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;b&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;a&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;True
False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, that seems odd.&lt;/p&gt;

&lt;p&gt;If the lists are identical, why does one comparison return &lt;code&gt;True&lt;/code&gt; while the other returns &lt;code&gt;False&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;To answer that, let's recall what we've learned in the previous articles.&lt;/p&gt;

&lt;p&gt;In Python, variables don't contain objects.&lt;/p&gt;

&lt;p&gt;Names refer to objects.&lt;/p&gt;

&lt;p&gt;When we execute:&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python creates a list object.&lt;/p&gt;

&lt;p&gt;Then we execute:&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;b&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates &lt;strong&gt;another&lt;/strong&gt; list object.&lt;/p&gt;

&lt;p&gt;Even though both lists contain exactly the same values, they are two distinct objects.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a ───► [1, 2, 3]

b ───► [1, 2, 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the behavior of the two operators becomes much easier to understand.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;==&lt;/code&gt; operator asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Do these objects have the same value?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this case, they do.&lt;/p&gt;

&lt;p&gt;So:&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;returns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;is&lt;/code&gt; operator asks a completely different question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are these the very same object?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This time, the answer is no.&lt;/p&gt;

&lt;p&gt;So:&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="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;False
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In other words:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;==&lt;/code&gt; compares an object's value&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;is&lt;/code&gt; compares an object's identity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now consider a different 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;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;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&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;a&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;b&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;a&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, both comparisons return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;True
True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because no second list was ever created.&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;simply gives the existing object another name.&lt;/p&gt;

&lt;p&gt;Now the picture looks 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;a ─┐
   ├──► [1, 2, 3]
b ─┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since both names refer to the same object:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the values are equal&lt;/li&gt;
&lt;li&gt;and the identity is the same&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's why both operators return &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;At this point, you might wonder:&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;is&lt;/code&gt; only checks whether two names refer to the same object, why do we need it at all?&lt;/p&gt;

&lt;p&gt;Why not always use &lt;code&gt;==&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;Most of the time, &lt;code&gt;==&lt;/code&gt; is exactly what you want.&lt;/p&gt;

&lt;p&gt;Use it whenever you're comparing values - for example, numbers, strings, or lists.&lt;/p&gt;

&lt;p&gt;But sometimes the identity of an object matters more than its value.&lt;/p&gt;

&lt;p&gt;The best-known example is &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You've probably seen code like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that it uses &lt;code&gt;is&lt;/code&gt;, not &lt;code&gt;==&lt;/code&gt;. Why?&lt;/p&gt;

&lt;p&gt;Because there's only one &lt;code&gt;None&lt;/code&gt; object in a Python program.&lt;/p&gt;

&lt;p&gt;We're not asking whether another object happens to behave like &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We're asking whether this is the &lt;code&gt;None&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;That's why the Python community recommends writing:&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;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of:&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;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It clearly communicates your intent and is considered the idiomatic way to write the comparison.&lt;/p&gt;




&lt;p&gt;You may occasionally run into something even more surprising:&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="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&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;a&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On many Python implementations, this prints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;True
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But based on everything we've discussed so far, you might have expected &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Don't worry - this doesn't mean numbers behave differently.&lt;/p&gt;

&lt;p&gt;Python sometimes reuses certain small immutable objects as an internal optimization.&lt;/p&gt;

&lt;p&gt;Small integers are one example.&lt;/p&gt;

&lt;p&gt;The important thing is that your code should never rely on this behavior.&lt;/p&gt;

&lt;p&gt;If you're comparing values, use &lt;code&gt;==&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you're checking whether two names refer to the same object, use &lt;code&gt;is&lt;/code&gt;.&lt;/p&gt;




&lt;p&gt;We can now summarize the difference with one simple rule.&lt;/p&gt;

&lt;p&gt;If you're asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Do these objects have the same value?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;use &lt;code&gt;==&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you're asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Are these the same object?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;use &lt;code&gt;is&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's exactly why the previous articles in this series were so important.&lt;/p&gt;

&lt;p&gt;Without understanding objects and names, the difference between &lt;code&gt;is&lt;/code&gt; and &lt;code&gt;==&lt;/code&gt; feels like an arbitrary rule you have to memorize.&lt;/p&gt;

&lt;p&gt;Once you understand Python's object model, though, the distinction becomes completely natural.&lt;/p&gt;

</description>
      <category>python</category>
      <category>types</category>
      <category>is</category>
      <category>equal</category>
    </item>
    <item>
      <title>Mutable and Immutable Objects in Python</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Tue, 14 Jul 2026 13:01:10 +0000</pubDate>
      <link>https://dev.to/storvus/mutable-and-immutable-objects-in-python-1gkn</link>
      <guid>https://dev.to/storvus/mutable-and-immutable-objects-in-python-1gkn</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;We assume you already know how to write simple Python programs and understand basic syntax (if, for, functions, lists). Here, we're not discussing how to use the language, but why it works the way it does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the previous article, we discovered something interesting.&lt;/p&gt;

&lt;p&gt;Lists can be modified:&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;numbers&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="n"&gt;numbers&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="mi"&gt;3&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;numbers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output 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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Numbers, however, behave differently.&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="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the object &lt;code&gt;10&lt;/code&gt; doesn't somehow become &lt;code&gt;20&lt;/code&gt;. Instead, the name &lt;code&gt;x&lt;/code&gt; simply becomes bound to a different object.&lt;/p&gt;

&lt;p&gt;At first glance, these seem like two completely different behaviors.&lt;/p&gt;

&lt;p&gt;In reality, they come from one of Python's most fundamental ideas.&lt;/p&gt;

&lt;p&gt;Python divides its objects into two broad categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mutable objects&lt;/li&gt;
&lt;li&gt;immutable objects&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Let's start with mutable objects.&lt;/p&gt;

&lt;p&gt;A mutable object is one whose internal state can be changed after it's created.&lt;/p&gt;

&lt;p&gt;Lists are the classic example.&lt;/p&gt;

&lt;p&gt;Suppose we create a list:&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;numbers&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then add elements:&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;numbers&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="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;remove them:&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;numbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or replace existing values:&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;numbers&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="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In every case, Python is working with the same object.&lt;/p&gt;

&lt;p&gt;The object isn't replaced or recreated.&lt;/p&gt;

&lt;p&gt;Only its contents change.&lt;/p&gt;

&lt;p&gt;That's why multiple names referring to the same list all observe the same changes.&lt;/p&gt;




&lt;p&gt;Now let's look at immutable objects.&lt;/p&gt;

&lt;p&gt;Once an immutable object has been created, its state can never change.&lt;/p&gt;

&lt;p&gt;Take a number:&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="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now assign a different 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="mi"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may look as though the object changed.&lt;/p&gt;

&lt;p&gt;But that's not what happened.&lt;/p&gt;

&lt;p&gt;The object &lt;code&gt;10&lt;/code&gt; remains exactly as it was.&lt;/p&gt;

&lt;p&gt;The name &lt;code&gt;x&lt;/code&gt; simply stops referring to it and becomes bound to another object instead.&lt;/p&gt;

&lt;p&gt;The same idea applies to strings.&lt;/p&gt;

&lt;p&gt;Suppose 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="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;Python&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we "add" some text:&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="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; 3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks like the string has been modified.&lt;/p&gt;

&lt;p&gt;In reality, Python creates an entirely new 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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Python 3&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and rebinds the name &lt;code&gt;name&lt;/code&gt; to it.&lt;/p&gt;

&lt;p&gt;The original string &lt;code&gt;"Python"&lt;/code&gt; never changes.&lt;/p&gt;




&lt;p&gt;At this point, it's worth emphasizing one important idea.&lt;/p&gt;

&lt;p&gt;When we describe an object as mutable or immutable, we're talking about the object itself.&lt;/p&gt;

&lt;p&gt;Not the variable.&lt;/p&gt;

&lt;p&gt;Not the name.&lt;/p&gt;

&lt;p&gt;Not the assignment statement.&lt;/p&gt;

&lt;p&gt;The property belongs to the object that exists in memory.&lt;/p&gt;

&lt;p&gt;This distinction may seem subtle now, but it'll help us avoid many common mistakes later on.&lt;/p&gt;




&lt;p&gt;So which built-in objects are immutable?&lt;/p&gt;

&lt;p&gt;Some of the most common examples are:&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;10&lt;/span&gt;
&lt;span class="mf"&gt;3.14&lt;/span&gt;
&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hello&lt;/span&gt;&lt;span class="sh"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;integers;&lt;/li&gt;
&lt;li&gt;floating-point numbers;&lt;/li&gt;
&lt;li&gt;booleans;&lt;/li&gt;
&lt;li&gt;strings;&lt;/li&gt;
&lt;li&gt;tuples.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once created, none of these objects can be modified.&lt;/p&gt;

&lt;p&gt;Common mutable objects include:&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;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="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&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;Anton&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;java&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;These are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;lists;&lt;/li&gt;
&lt;li&gt;dictionaries;&lt;/li&gt;
&lt;li&gt;sets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Their contents can be changed after they're created.&lt;/p&gt;




&lt;p&gt;At this point, you might be wondering:&lt;/p&gt;

&lt;p&gt;If mutable objects are so flexible, why isn't everything mutable?&lt;/p&gt;

&lt;p&gt;The answer is that immutable objects offer several important advantages.&lt;/p&gt;

&lt;p&gt;Since they can never change, Python can safely share and reuse them in many situations, compare them efficiently, and make certain internal optimizations.&lt;/p&gt;

&lt;p&gt;They're also easier to reason about.&lt;/p&gt;

&lt;p&gt;If an object is immutable, you never have to worry that some other part of your program has modified it behind your back.&lt;/p&gt;

&lt;p&gt;That's why Python includes both mutable and immutable objects.&lt;/p&gt;

&lt;p&gt;Each serves a different purpose.&lt;/p&gt;




&lt;p&gt;We can now summarize Python's object model a little more precisely.&lt;/p&gt;

&lt;p&gt;When you 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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;something&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python doesn't store a value inside a variable.&lt;/p&gt;

&lt;p&gt;It binds a name to an object.&lt;/p&gt;

&lt;p&gt;What happens next depends on the object itself.&lt;/p&gt;

&lt;p&gt;If the object is mutable, its state can be modified in place.&lt;/p&gt;

&lt;p&gt;If it's immutable, any apparent "change" results in a different object, with the name simply being rebound to it.&lt;/p&gt;




&lt;p&gt;Now we're finally ready for another interesting question.&lt;/p&gt;

&lt;p&gt;Suppose we have two lists containing exactly the same values:&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="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;b&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Are they actually the same object?&lt;/p&gt;

&lt;p&gt;Or are they merely equal?&lt;/p&gt;

&lt;p&gt;And why does Python sometimes use &lt;code&gt;==&lt;/code&gt;, while other times &lt;code&gt;is&lt;/code&gt; is the right choice?&lt;/p&gt;

&lt;p&gt;That's exactly what we'll explore in the next article. 🚀&lt;/p&gt;

</description>
      <category>python</category>
      <category>types</category>
      <category>immutable</category>
      <category>mutable</category>
    </item>
    <item>
      <title>Why Numbers Behave Differently from Lists</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Sun, 12 Jul 2026 19:49:18 +0000</pubDate>
      <link>https://dev.to/storvus/why-numbers-behave-differently-from-lists-1n6c</link>
      <guid>https://dev.to/storvus/why-numbers-behave-differently-from-lists-1n6c</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;We assume you already know how to write simple Python programs and understand basic syntax (if, for, functions, lists). Here, we're not discussing how to use the language, but why it works the way it does. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The previous article, we saw something that can seem quite surprising at first:&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="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="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="n"&gt;a&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="mi"&gt;3&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;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# [1, 2, 3]
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It almost looks as if Python somehow "links" variables together.&lt;/p&gt;

&lt;p&gt;But that's not what's happening.&lt;/p&gt;

&lt;p&gt;The variables aren't connected to each other - they simply refer to the same object.&lt;/p&gt;

&lt;p&gt;That naturally leads to another question.&lt;/p&gt;

&lt;p&gt;If a list can be modified &lt;em&gt;in place&lt;/em&gt;, why don't numbers behave the same way?&lt;/p&gt;

&lt;p&gt;Consider 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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&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;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This time, the output 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="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;y&lt;/code&gt; still refers to &lt;code&gt;10&lt;/code&gt;, even though we reassigned &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;The answer lies in one subtle but fundamental idea.&lt;/p&gt;

&lt;p&gt;Not all Python objects behave the same way when you try to "change" them.&lt;/p&gt;

&lt;p&gt;Let's start with numbers.&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="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python creates the object &lt;code&gt;10&lt;/code&gt;, and the name &lt;code&gt;x&lt;/code&gt; becomes bound to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;x ───► 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;/div&gt;



&lt;p&gt;This is where it's important to separate &lt;strong&gt;rebinding a name&lt;/strong&gt; from &lt;strong&gt;modifying an object&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The object &lt;code&gt;10&lt;/code&gt; does &lt;strong&gt;not&lt;/strong&gt; turn into &lt;code&gt;20&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In fact, the object &lt;code&gt;10&lt;/code&gt; doesn't change at all.&lt;/p&gt;

&lt;p&gt;Instead, Python creates (or reuses) the object &lt;code&gt;20&lt;/code&gt;, and the name &lt;code&gt;x&lt;/code&gt; is simply rebound to it.&lt;/p&gt;

&lt;p&gt;Now the picture looks 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;x ───► 20

y ───► 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The object &lt;code&gt;10&lt;/code&gt; still exists because &lt;code&gt;y&lt;/code&gt; continues to refer to it.&lt;/p&gt;

&lt;p&gt;Now let's compare that to a list.&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a single list object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a ───► [1, 2]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now comes the important part:&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="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="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;Unlike assignment, &lt;code&gt;append()&lt;/code&gt; does &lt;strong&gt;not&lt;/strong&gt; create a new list.&lt;/p&gt;

&lt;p&gt;Instead, it modifies the existing object in place.&lt;/p&gt;

&lt;p&gt;After the call, we have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a ───► [1, 2, 3]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we originally had two names:&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="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="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the picture looked 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;a ─┐
   ├──► [1, 2]
b ─┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling:&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="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="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;doesn't change the names.&lt;/p&gt;

&lt;p&gt;It changes the object itself.&lt;/p&gt;

&lt;p&gt;As a result, both names still refer to the same list-but that list now has different contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a ─┐
   ├──► [1, 2, 3]
b ─┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This brings us to the key difference.&lt;/p&gt;

&lt;p&gt;The number &lt;code&gt;10&lt;/code&gt; cannot be modified.&lt;/p&gt;

&lt;p&gt;A list can.&lt;/p&gt;

&lt;p&gt;This isn't a special rule for numbers or lists, and it isn't a quirk of Python's syntax.&lt;/p&gt;

&lt;p&gt;It's a fundamental property of Python objects.&lt;/p&gt;

&lt;p&gt;Some objects can never change after they're created.&lt;/p&gt;

&lt;p&gt;Whenever they appear to "change," Python actually creates a different object and rebinds the name.&lt;/p&gt;

&lt;p&gt;Other objects allow their internal state to be modified without creating a new object.&lt;/p&gt;

&lt;p&gt;That's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;numbers behave as &lt;strong&gt;unchangeable&lt;/strong&gt; objects;&lt;/li&gt;
&lt;li&gt;lists behave as &lt;strong&gt;changeable&lt;/strong&gt; objects.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a useful way to think about it.&lt;/p&gt;

&lt;p&gt;An unchangeable object is frozen once it's created.&lt;/p&gt;

&lt;p&gt;If you need a different value, you need a different object.&lt;/p&gt;

&lt;p&gt;A changeable object, on the other hand, remains the same object even though its contents can change.&lt;/p&gt;

&lt;p&gt;Now the difference between numbers and lists becomes much easier to understand.&lt;/p&gt;

&lt;p&gt;With numbers, changing the value always means referring to a different object.&lt;/p&gt;

&lt;p&gt;With lists, you're usually modifying the existing object instead.&lt;/p&gt;

&lt;p&gt;This leads to an important principle that we'll keep coming back to throughout this series:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In Python, a program's behavior is determined not by what's "stored in a variable," but by whether you're modifying an object or simply rebinding a name.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now we can finally introduce the official terminology.&lt;/p&gt;

&lt;p&gt;The kinds of objects we've been talking about are called:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;mutable objects&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;immutable objects&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By now, though, these shouldn't feel like abstract definitions.&lt;/p&gt;

&lt;p&gt;They're simply names for the behaviors we've already observed.&lt;/p&gt;

&lt;p&gt;In the next article, we'll take a closer look at mutable and immutable objects, see which built-in types belong to each category, and understand why this distinction is so fundamental to Python itself.&lt;/p&gt;

</description>
      <category>python</category>
      <category>types</category>
      <category>immutable</category>
      <category>mutable</category>
    </item>
    <item>
      <title>Why Does a List Change in Two Variables?</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Fri, 03 Jul 2026 12:45:05 +0000</pubDate>
      <link>https://dev.to/storvus/why-does-a-list-change-in-two-variables-288f</link>
      <guid>https://dev.to/storvus/why-does-a-list-change-in-two-variables-288f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;We assume you already know how to write simple Python programs and understand basic syntax (if, for, functions, lists). Here, we're not discussing how to use the language, but why it works the way it does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the previous article, we learned that variables in Python don't store data themselves. Instead, a name simply refers to an object.&lt;/p&gt;

&lt;p&gt;With numbers, this feels quite intuitive:&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="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both names refer to the same object whose value is &lt;code&gt;10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So far, everything seems straightforward.&lt;/p&gt;

&lt;p&gt;But as soon as we start working with lists, Python's behavior often surprises people.&lt;/p&gt;

&lt;p&gt;Consider 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;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="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="n"&gt;a&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="mi"&gt;3&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;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many beginners expect the output to be:&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After all, we modified &lt;code&gt;a&lt;/code&gt;, not &lt;code&gt;b&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Instead, Python prints:&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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks as if changing one variable somehow changed the other.&lt;/p&gt;

&lt;p&gt;At first glance, it may seem like Python is keeping the two variables synchronized behind the scenes.&lt;/p&gt;

&lt;p&gt;In reality, the explanation is much simpler.&lt;/p&gt;

&lt;p&gt;Let's go back to the idea from the previous article.&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python creates a list object, and the name &lt;code&gt;a&lt;/code&gt; becomes bound to it.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a ───► [1, 2]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;/div&gt;



&lt;p&gt;This is the crucial part.&lt;/p&gt;

&lt;p&gt;Python does &lt;strong&gt;not&lt;/strong&gt; create a second list.&lt;/p&gt;

&lt;p&gt;No copy is made.&lt;/p&gt;

&lt;p&gt;Instead, the name &lt;code&gt;b&lt;/code&gt; is bound to exactly the same object.&lt;/p&gt;

&lt;p&gt;Now the picture looks 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;a ─┐
   ├──► [1, 2]
b ─┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that there's still only one list.&lt;/p&gt;

&lt;p&gt;The only thing that changed is that there are now two names referring to it.&lt;/p&gt;

&lt;p&gt;That's why the next 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="n"&gt;a&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="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;doesn't create a new list.&lt;/p&gt;

&lt;p&gt;It modifies the existing object.&lt;/p&gt;

&lt;p&gt;After the call to &lt;code&gt;append()&lt;/code&gt;, the picture becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a ─┐
   ├──► [1, 2, 3]
b ─┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since both names refer to the same object, the change is visible through both of them.&lt;/p&gt;

&lt;p&gt;In other words, Python didn't modify two different lists.&lt;/p&gt;

&lt;p&gt;It modified one list that simply has two names.&lt;/p&gt;

&lt;p&gt;This behavior is one of the most common sources of confusion for beginners.&lt;/p&gt;

&lt;p&gt;For example, you might write a function that modifies a list passed as an argument, only to discover later that the original list outside the function has changed as well.&lt;/p&gt;

&lt;p&gt;From Python's point of view, though, there's nothing mysterious happening.&lt;/p&gt;

&lt;p&gt;If multiple names refer to the same object, they all see the object's current state.&lt;/p&gt;

&lt;p&gt;At this point, you may be wondering something else.&lt;/p&gt;

&lt;p&gt;If a list can be modified without creating a new object, why doesn't the same thing happen with numbers?&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="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;

&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this code runs, &lt;code&gt;y&lt;/code&gt; still refers to &lt;code&gt;10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Why can a list be modified in place, while a number cannot?&lt;/p&gt;

&lt;p&gt;That's exactly the question we'll answer in the next article.&lt;/p&gt;

</description>
      <category>python</category>
      <category>list</category>
    </item>
    <item>
      <title>What Really Happens When You Write x = 10</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Tue, 30 Jun 2026 19:20:16 +0000</pubDate>
      <link>https://dev.to/storvus/what-really-happens-when-you-write-x-10-p0b</link>
      <guid>https://dev.to/storvus/what-really-happens-when-you-write-x-10-p0b</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;We assume you already know how to write simple Python programs and understand basic syntax (if, for, functions, lists). Here, we're not discussing how to use the language, but why it works the way it does.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you ask a beginner what this line of code does:&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="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the answer is usually something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The number 10 is stored in the variable x."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;At first glance, that sounds perfectly reasonable. We're used to thinking of a variable as a box or a memory cell that can hold a value. First the box is empty, then we put a number, a string, or a list into it.&lt;/p&gt;

&lt;p&gt;The problem is that Python doesn't actually work that way.&lt;/p&gt;

&lt;p&gt;To understand many of Python's behaviors, it's helpful to stop thinking of variables as containers for data. Instead, think of a variable as a &lt;strong&gt;name&lt;/strong&gt; that refers to an &lt;strong&gt;object&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When Python executes:&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="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;it doesn't start with the variable - it starts with the object &lt;code&gt;10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The number &lt;code&gt;10&lt;/code&gt; is an object. Once that object exists, the name &lt;code&gt;x&lt;/code&gt; is bound to it.&lt;/p&gt;

&lt;p&gt;Visually, you can think of it 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;x ───► 10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The arrow indicates that the name &lt;code&gt;x&lt;/code&gt; refers to the object whose value is &lt;code&gt;10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;At first, this distinction may seem unimportant. What difference does it make whether the number is stored inside the variable or the variable simply points to it?&lt;/p&gt;

&lt;p&gt;As it turns out, the difference is enormous, and it explains many of Python's most important behaviors.&lt;/p&gt;

&lt;p&gt;Now suppose we add another 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="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Many people expect Python to create a second copy of the number and store it in another variable.&lt;/p&gt;

&lt;p&gt;That's not what happens.&lt;/p&gt;

&lt;p&gt;Instead, the name &lt;code&gt;y&lt;/code&gt; is simply bound to the very same object that &lt;code&gt;x&lt;/code&gt; already refers to.&lt;/p&gt;

&lt;p&gt;Now the picture looks 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;x ─┐
   ├──► 10
y ─┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's still only one object, but now there are two names that refer to it.&lt;/p&gt;

&lt;p&gt;That's why Python makes a clear distinction between &lt;strong&gt;objects&lt;/strong&gt; and &lt;strong&gt;names&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Objects hold data.&lt;/p&gt;

&lt;p&gt;Names allow you to access those objects.&lt;/p&gt;

&lt;p&gt;Things become even more interesting when a variable appears to "change."&lt;/p&gt;

&lt;p&gt;Consider this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you think of variables as boxes, it's natural to imagine that the number &lt;code&gt;10&lt;/code&gt; inside the box has somehow been replaced with &lt;code&gt;20&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But that's not what Python does.&lt;/p&gt;

&lt;p&gt;Initially, the name &lt;code&gt;x&lt;/code&gt; refers to the object &lt;code&gt;10&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;x&lt;/span&gt; &lt;span class="err"&gt;───►&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the second assignment, the name refers to a different 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;x&lt;/span&gt; &lt;span class="err"&gt;───►&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The object &lt;code&gt;10&lt;/code&gt; hasn't changed, disappeared, or turned into &lt;code&gt;20&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The name &lt;code&gt;x&lt;/code&gt; has simply been rebound to another object.&lt;/p&gt;

&lt;p&gt;This may seem like a subtle detail, but it's one of the fundamental ideas behind Python's execution model.&lt;/p&gt;

&lt;p&gt;Later, we'll see that it explains many things that often confuse beginners:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;why modifying a list can unexpectedly affect another variable;&lt;/li&gt;
&lt;li&gt;why &lt;code&gt;is&lt;/code&gt; and &lt;code&gt;==&lt;/code&gt; are not the same;&lt;/li&gt;
&lt;li&gt;why strings behave differently from lists;&lt;/li&gt;
&lt;li&gt;and how Python passes arguments to functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For now, remember just one idea.&lt;/p&gt;

&lt;p&gt;When you 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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python doesn't put the number into a variable.&lt;/p&gt;

&lt;p&gt;It binds the name &lt;code&gt;x&lt;/code&gt; to the object &lt;code&gt;10&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That's why experienced Python developers usually don't say that &lt;em&gt;a variable stores a value&lt;/em&gt;. Instead, they say that &lt;em&gt;a name refers to an object&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;It may sound a little less intuitive at first, but it's much closer to how Python actually works.&lt;/p&gt;

</description>
      <category>python</category>
      <category>objects</category>
      <category>types</category>
    </item>
    <item>
      <title>More abbreviations to the abbreviation's God</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Sun, 11 Jun 2023 19:54:17 +0000</pubDate>
      <link>https://dev.to/storvus/more-abbreviations-to-the-abbreviations-god-1lek</link>
      <guid>https://dev.to/storvus/more-abbreviations-to-the-abbreviations-god-1lek</guid>
      <description>&lt;p&gt;At the work I meet a lot of different abbreviations. Some of them are insignificant, some of them are pretty useful, but most of them you're already know. Nevertheless, they describe the developing process in a way it should be and can help to build a real robust applications. There is a list of the most common of them. Which ones would you like to add?&lt;/p&gt;

&lt;p&gt;SOLID Principles&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;S (Single Responsibility)&lt;/strong&gt; Every class is responsible for the on operation only.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;O (Open Closed)&lt;/strong&gt; The classes have to be open for extending and closed for modification&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L (Liskov substitution)&lt;/strong&gt; It should be possible to use a child class (type) instead of a parent without negative consequences&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;I (Interface Segregation)&lt;/strong&gt; You shouldn't force a class to implement an interface, which doesn't relate to the class&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;D (Dependency Inversion)&lt;/strong&gt; Abstractions don't depend on the details, but details do depend on the abstractions&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;YAGNI (You're not gonna need it)&lt;/strong&gt; If you're writing the code, ensure you're gonna use it. &lt;strong&gt;Don't&lt;/strong&gt; add the code if you think it'll be useful later&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DRY (Don't repeat yourself)&lt;/strong&gt; Pretty obvious. Don't hurry to write the code - look around. Likely, someone already wrote it. This is why I love pull requests for - somebody can remember that your functional already exists and we don't actually need. Seriously?! Where have you been during the sprint planning?!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KISS (Keep it simple, stupid)&lt;/strong&gt; Well, just be simpler. The simpler code, the better it works. If a task doesn't require over-complicated solution, just use the solution. It supposes that you have multiple solution of the task. Haha :\&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;BDUF (Big design up front)&lt;/strong&gt; This is what I'm lack in. No time to think, just write the &lt;del&gt;f..&lt;/del&gt; code. It's incorrect. Before starting coding, ensure that everything is well thought out&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;APO (Avoid Premature Optimization)&lt;/strong&gt; Don't force the code optimization until it's really necessary.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;There are much more abbreviations in a programming world. Which one is your favourite? My favourite is LGTM in the comments of pull requests!&lt;/p&gt;

</description>
      <category>solidity</category>
      <category>learning</category>
      <category>yagni</category>
      <category>dry</category>
    </item>
    <item>
      <title>Bottle+Sqlite</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Thu, 01 Jun 2023 19:10:50 +0000</pubDate>
      <link>https://dev.to/storvus/bottlesqlite-4off</link>
      <guid>https://dev.to/storvus/bottlesqlite-4off</guid>
      <description>&lt;p&gt;A few more words about Bottle. After enabling a sqlite extension, you can easily include a specified keyword as a view argument. 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="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bottle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Bottle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;db_plugin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bottle_sqlite&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Plugin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dbfile&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./test.db&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;db&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;install&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db_plugin&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.route&lt;/span&gt;&lt;span class="p"&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;):&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;It works perfect... Until you decide to show the view for authorized users only. And this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@bottle.auth_basic&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;save_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&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;will cause&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeError("main() missing 1 required positional argument: 'db'")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a &lt;a href="https://github.com/bottlepy/bottle-sqlite/issues/21" rel="noopener noreferrer"&gt;known issue&lt;/a&gt;, which still wasn't solved on the plugin level. So, again &lt;a href="https://github.com/storvus/effective-pancake/blob/bottle/db/bottle_sqlite.py" rel="noopener noreferrer"&gt;workarounds&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only change here 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;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_callback&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;keyword&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;params&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;callback&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of&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;argspec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getargspec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_callback&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Bottle</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Tue, 30 May 2023 09:02:48 +0000</pubDate>
      <link>https://dev.to/storvus/bottle-4e33</link>
      <guid>https://dev.to/storvus/bottle-4e33</guid>
      <description>&lt;p&gt;Bottle is a really small python-based framework. The whole its code takes 1 file with ~4000 rows. Meanwhile, Bottle is pretty self-sufficient - it supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wsgi-server&lt;/li&gt;
&lt;li&gt;routing&lt;/li&gt;
&lt;li&gt;authorization&lt;/li&gt;
&lt;li&gt;plugins&lt;/li&gt;
&lt;li&gt;own templates language&lt;/li&gt;
&lt;li&gt;a lot of extensions (mostly one-paged too)&lt;/li&gt;
&lt;li&gt;custom error pages&lt;/li&gt;
&lt;li&gt;and much more!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was excited trying to write my blog using Bottle. The first issue I faced - you can login, but you can't logout :D&lt;/p&gt;

&lt;p&gt;Bottle supports basic auth mechanism, so you can do something 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;auth_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&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;user&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;  &lt;span class="c1"&gt;# or any check you want
&lt;/span&gt;
&lt;span class="nd"&gt;@bottle.auth_basic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;auth_callback&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;edit_post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;post_id&lt;/span&gt;&lt;span class="p"&gt;):&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;But there is no way to logout. The only workaround I found is to return 401 status as a response. It allows to force logout the user. It's not quite correct, because user doesn't expect to get 401Error on logout, but this is why it's called workaround.&lt;/p&gt;

&lt;p&gt;To make the solution to look more pretty I also customized 401 Error page, by adding an html-template with link to login.&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;logout&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;bottle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&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;error_401&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;error&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;bottle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;errors/401&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/logout/&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;GET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;logout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As alternative, there is an extension for bottle, called bottle-login, which has been archived few years ago.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/klen" rel="noopener noreferrer"&gt;
        klen
      &lt;/a&gt; / &lt;a href="https://github.com/klen/bottle-login" rel="noopener noreferrer"&gt;
        bottle-login
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Implement users' sessions in Bottle framework
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="rst"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Bottle Login&lt;/h1&gt;

&lt;/div&gt;

&lt;p id="user-content-description"&gt;Bottle Login -- Implement users' sessions in Bottle web framework.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://travis-ci.org/klen/bottle-login" id="user-content-badges" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Build Status" src="https://camo.githubusercontent.com/b6631928b2ef707bd7532d03bfa24c36c16f804f0bcea213aa2e1a9967b6c51d/687474703a2f2f696d672e736869656c64732e696f2f7472617669732f6b6c656e2f626f74746c652d6c6f67696e2e7376673f7374796c653d666c61742d737175617265"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://coveralls.io/r/klen/bottle-login" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Coverals" src="https://camo.githubusercontent.com/b2f5d575b13188b567aa56d46613baacaa9d015b8c15732a4cd8e79e0a1269c7/687474703a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f6b6c656e2f626f74746c652d6c6f67696e2e7376673f7374796c653d666c61742d737175617265"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pypi.python.org/pypi/bottle-login" rel="nofollow noopener noreferrer"&gt;&lt;img alt="http://img.shields.io/pypi/v/bottle-login.svg?style=flat-square" src="https://camo.githubusercontent.com/6feed94429eb82c2b8194d67888529018e24f29d994f867c371254288a29cb46/687474703a2f2f696d672e736869656c64732e696f2f707970692f762f626f74746c652d6c6f67696e2e7376673f7374796c653d666c61742d737175617265"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://pypi.python.org/pypi/bottle-login" rel="nofollow noopener noreferrer"&gt;&lt;img alt="http://img.shields.io/pypi/dm/bottle-login.svg?style=flat-square" src="https://camo.githubusercontent.com/ccb4f25b00c499f65a1bfad7d41adad8599fa06c9c873745d902e8c4c9e583c0/687474703a2f2f696d672e736869656c64732e696f2f707970692f646d2f626f74746c652d6c6f67696e2e7376673f7374796c653d666c61742d737175617265"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.gratipay.com/klen/" rel="nofollow noopener noreferrer"&gt;&lt;img alt="Donate" src="https://camo.githubusercontent.com/11eb7ecb0a50ebc5e95e6b7f2580c67924cf18a3ee900e0551fdd1307eb6d658/687474703a2f2f696d672e736869656c64732e696f2f67726174697061792f6b6c656e2e7376673f7374796c653d666c61742d737175617265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div id="user-content-id1"&gt;
&lt;p&gt;Contents&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/klen/bottle-login#id2" id="user-content-id7" rel="noopener noreferrer"&gt;Requirements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/klen/bottle-login#id3" id="user-content-id8" rel="noopener noreferrer"&gt;Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/klen/bottle-login#id4" id="user-content-id9" rel="noopener noreferrer"&gt;Usage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/klen/bottle-login#bug-tracker" id="user-content-id10" rel="noopener noreferrer"&gt;Bug tracker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/klen/bottle-login#id5" id="user-content-id11" rel="noopener noreferrer"&gt;Contributing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/klen/bottle-login#contributors" id="user-content-id12" rel="noopener noreferrer"&gt;Contributors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/klen/bottle-login#id6" id="user-content-id13" rel="noopener noreferrer"&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;&lt;a href="https://github.com/klen/bottle-login#id7" rel="noopener noreferrer"&gt;Requirements&lt;/a&gt;&lt;/h2&gt;

&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;python &amp;gt;= 2.6&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;&lt;a href="https://github.com/klen/bottle-login#id8" rel="noopener noreferrer"&gt;Installation&lt;/a&gt;&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Bottle Login&lt;/strong&gt; should be installed using pip:&lt;/p&gt;

&lt;pre&gt;pip install bottle-login
&lt;/pre&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;&lt;a href="https://github.com/klen/bottle-login#id9" rel="noopener noreferrer"&gt;Usage&lt;/a&gt;&lt;/h2&gt;

&lt;/div&gt;

&lt;pre&gt;from bottle import Bottle, request, redirect
from bottle_login import LoginPlugin

app = Bottle()
app.config['SECRET_KEY'] = 'secret'

login = app.install(LoginPlugin())

&lt;a class="mentioned-user" href="https://dev.to/login"&gt;@login&lt;/a&gt;.load_user
def load_user_by_id(user_id):
    # Load user by id here


# Some application views

@app.route('/')
def index():
    current_user = login.get_user()
    return current_user.name

@app.route('/signout')
def signout():
    # Implement logout
    login.logout_user()
    return redirect('/')

@app.route('/signin')
def signin():
    # Implement login (you can check passwords here or etc)
    user_id = int(request.GET.get('user_id'))
    login.login_user(user_id)
    return redirect('/')
&lt;/pre&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;&lt;a href="https://github.com/klen/bottle-login#id10" rel="noopener noreferrer"&gt;Bug tracker&lt;/a&gt;&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;If you have any suggestions, bug reports or
annoyances please report them to the issue tracker
at &lt;a href="https://github.com/klen/bottle-login/issues" rel="noopener noreferrer"&gt;https://github.com/klen/bottle-login/issues&lt;/a&gt;&lt;/p&gt;


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;&lt;a href="https://github.com/klen/bottle-login#id11" rel="noopener noreferrer"&gt;Contributing&lt;/a&gt;&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Development of Bottle Login happens at: &lt;a href="https://github.com/klen/bottle-login" rel="noopener noreferrer"&gt;https://github.com/klen/bottle-login&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;&lt;a href="https://github.com/klen/bottle-login#id12" rel="noopener noreferrer"&gt;Contributors&lt;/a&gt;&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/klen" rel="noopener noreferrer"&gt;klen&lt;/a&gt; (Kirill Klenov)&lt;/li&gt;
&lt;/ul&gt;


&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;&lt;a href="https://github.com/klen/bottle-login#id13" rel="noopener noreferrer"&gt;License&lt;/a&gt;&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Licensed under a &lt;a href="http://www.linfo.org/bsdlicense.html" rel="nofollow noopener noreferrer"&gt;BSD license&lt;/a&gt;.&lt;/p&gt;

&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/klen/bottle-login" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


</description>
      <category>bottle</category>
      <category>python</category>
      <category>auth</category>
    </item>
    <item>
      <title>First post</title>
      <dc:creator>Anton Shcherbatov</dc:creator>
      <pubDate>Mon, 29 May 2023 21:01:16 +0000</pubDate>
      <link>https://dev.to/storvus/first-post-4b6</link>
      <guid>https://dev.to/storvus/first-post-4b6</guid>
      <description>&lt;p&gt;Well, this is probably the first time when I use this title not for testing purposes. Although, this is still gonna be a part of experiment, where I'm trying different kind of frameworks, technologies, skills and share all the useful (for me) and interesting (again, for me) information.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
