avatarYang Zhou

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

3164

Abstract

nding-the-singleton-pattern-in-python-4bf429a10438">singletons</a> and they’ve been already saved in the memory. We cannot create a new integer object in this range.</p><p id="c859">Therefore, the explanations of the first example are obvious:</p><ul><li>When the variables <code>a</code> and <code>b</code> were assigned to 256, they were referenced to the same memory location where the 256 was stored. They pointed to the same object.</li><li>When the variables <code>a</code> and <code>b</code> were assigned to 257, they were two different objects in different memory locations because the 257 is not on the small integers caching range.</li></ul><p id="d456">Since the <code>is</code> operator is to compare the memory locations of two variables, the <code>a is b</code> should output <code>True</code>, and the <code>x is y</code> should output <code>False</code>.</p><p id="5601">We can also use the <code>id()</code> function, which prints the memory location of a variable, to confirm the above explanations:</p><div id="c42e"><pre><span class="hljs-meta prompt_">>>></span> <span class="language-python">a=<span class="hljs-number">256</span></span> <span class="hljs-meta prompt_">>>></span> <span class="language-python">b=<span class="hljs-number">256</span></span> <span class="hljs-meta prompt_">>>></span> <span class="language-python"><span class="hljs-built_in">id</span>(a)==<span class="hljs-built_in">id</span>(b)</span> True <span class="hljs-meta prompt_">>>></span> <span class="language-python">x=<span class="hljs-number">257</span></span> <span class="hljs-meta prompt_">>>></span> <span class="language-python">y=<span class="hljs-number">257</span></span> <span class="hljs-meta prompt_">>>></span> <span class="language-python"><span class="hljs-built_in">id</span>(x)==<span class="hljs-built_in">id</span>(y)</span> False</pre></div><h1 id="2a03">2. The Results Are Different if the Python Compiler Can See the Whole Picture</h1><p id="dca3">As shown previously, if we run the same code as a Python script, the <code>x is y</code> will output <code>True</code>. This of course is not an accident.</p><p id="6500">In fact, the Python compiler is very smart and will do many optimisations for us under the hood. If we run our code as a whole script, the Python compiler can “see” the whole program at once and do the corresponding optimisations.</p><p id="25d1">As to our example, since the Python compiler saw the whole program, it knew there are two variables <code>x</code> and <code>y</code> and they are equal to the same integer 257. Therefore, it was reasonable to create one integer object and reference the two variables into it. This optimisation can save time and memory costs.</p><p id="575b"><b>However, if we run the code line by line in the interactive Python shell, the compiler can only see one line of code each time.</b></p><p id="0ba2">It means when we input <code>y=257</code>, the compiler just sees this line of code, and cannot remember the previous code <code>x=257</code>. Because the 257 is not in the special range, which is [-5, 256], a new integer o

Options

bject is created.</p><p id="acb0">Since we know this character of the Python compiler, we can use a trick to make the <code>x is y</code> output <code>True</code> on the interactive shell as well:</p><div id="5388"><pre><span class="hljs-meta prompt_">>>></span> <span class="language-python">x=<span class="hljs-number">257</span>; y=<span class="hljs-number">257</span></span> <span class="hljs-meta prompt_">>>></span> <span class="language-python">x <span class="hljs-keyword">is</span> y</span> True</pre></div><p id="100a">As shown above, we can put the two assignments into one line. Since the interactive Python interpreter can see the two variables at once now, the optimisation works again.</p><h1 id="8342">3. The Implementations and Versions of Python Affect the Integer Caching Feature</h1><p id="ec69">All the above examples and explanations are based on CPython, which is the standard implementation of Python. In fact, there are some alternative implementations, such as PyPy, IronPython and Jython, and some mechanisms of them may be different from CPython.</p><p id="7716">For example, the small integers caching feature is disabled in PyPy by default. If we would like to turn on this feature, we should enable it at first. For more details, we can check out the <a href="https://doc.pypy.org/en/latest/interpreter-optimizations.html#caching-small-integers">corresponding documents</a> of PyPy.</p><p id="a11e">Besides, the version of Python also matters. What we used in this article is Python 3.8. Since Python is continuously updated and evolved, no one can make sure that one special feature won’t be changed in future versions.</p><h1 id="349b">Conclusion</h1><p id="c602">Python has many optimization mechanisms internally, we should understand how it works and affects our code. The integer caching feature is useful and necessary to reduce time and memory costs. There are three facts under the hood:</p><ol><li>The integers in the range of [-5, 256] are singletons in Python and can’t be recreated again.</li><li>If the Python compiler can see the whole code, more optimisations may apply to the code.</li><li>Different implementations and versions of Python may have different mechanisms for the same feature.</li></ol><p id="a463"><b><i>Thanks for reading. If you like it, don’t forget to follow <a href="https://yangzhou1993.medium.com/follow">me</a> to get more great articles about programming and technologies!</i></b></p><p id="bd2e"><b><i>Relative articles:</i></b></p><div id="4dee" class="link-block"> <a href="https://readmedium.com/3-levels-of-understanding-the-singleton-pattern-in-python-4bf429a10438"> <div> <div> <h2>3 Levels of Understanding the Singleton Pattern in Python</h2> <div><h3>The most controversial design pattern</h3></div> <div><p>medium.com</p></div> </div> <div> <div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*w8PFx_Go7LyicdcM)"></div> </div> </div> </a> </div></article></body>

3 Facts of the Integer Caching in Python

Understand some confusing results made by Python

Photo by Ben White on Unsplash

Python has a special feature called integer caching, or integer interning. Sometimes, it may make us confused. For example, if we run the following code on a Python shell, the results are surprising:

>>> a=256
>>> b=256
>>> a is b
True
>>> x=257
>>> y=257
>>> x is y
False

Why 256 is 256 but 257 is not 257? Anything wrong?

And this is not the weirdest part yet, if we put the same code into a file and run it as a Python script, the results will surprise us again!

We put all the code into the above script called “test.py”. Then open a terminal and run the script:

$ python test.py
True
True

😱 What? The statement x is y becomes True at this time.

If you are confused about these as well, no worries at all. This article will demystify how the integer caching feature works and summary it into three facts. After reading, you will not be confused about it anymore.

1. A Range of Small Integers Are Singletons in Python

Actually, in order to save time and memory costs, Python always pre-loads all the small integers in the range of [-5, 256]. When a new integer variable in this range is declared, Python just references the cached integer to it and won’t create any new object.

In other words, all the integers in [-5, 256] are singletons and they’ve been already saved in the memory. We cannot create a new integer object in this range.

Therefore, the explanations of the first example are obvious:

  • When the variables a and b were assigned to 256, they were referenced to the same memory location where the 256 was stored. They pointed to the same object.
  • When the variables a and b were assigned to 257, they were two different objects in different memory locations because the 257 is not on the small integers caching range.

Since the is operator is to compare the memory locations of two variables, the a is b should output True, and the x is y should output False.

We can also use the id() function, which prints the memory location of a variable, to confirm the above explanations:

>>> a=256
>>> b=256
>>> id(a)==id(b)
True
>>> x=257
>>> y=257
>>> id(x)==id(y)
False

2. The Results Are Different if the Python Compiler Can See the Whole Picture

As shown previously, if we run the same code as a Python script, the x is y will output True. This of course is not an accident.

In fact, the Python compiler is very smart and will do many optimisations for us under the hood. If we run our code as a whole script, the Python compiler can “see” the whole program at once and do the corresponding optimisations.

As to our example, since the Python compiler saw the whole program, it knew there are two variables x and y and they are equal to the same integer 257. Therefore, it was reasonable to create one integer object and reference the two variables into it. This optimisation can save time and memory costs.

However, if we run the code line by line in the interactive Python shell, the compiler can only see one line of code each time.

It means when we input y=257, the compiler just sees this line of code, and cannot remember the previous code x=257. Because the 257 is not in the special range, which is [-5, 256], a new integer object is created.

Since we know this character of the Python compiler, we can use a trick to make the x is y output True on the interactive shell as well:

>>> x=257; y=257
>>> x is y
True

As shown above, we can put the two assignments into one line. Since the interactive Python interpreter can see the two variables at once now, the optimisation works again.

3. The Implementations and Versions of Python Affect the Integer Caching Feature

All the above examples and explanations are based on CPython, which is the standard implementation of Python. In fact, there are some alternative implementations, such as PyPy, IronPython and Jython, and some mechanisms of them may be different from CPython.

For example, the small integers caching feature is disabled in PyPy by default. If we would like to turn on this feature, we should enable it at first. For more details, we can check out the corresponding documents of PyPy.

Besides, the version of Python also matters. What we used in this article is Python 3.8. Since Python is continuously updated and evolved, no one can make sure that one special feature won’t be changed in future versions.

Conclusion

Python has many optimization mechanisms internally, we should understand how it works and affects our code. The integer caching feature is useful and necessary to reduce time and memory costs. There are three facts under the hood:

  1. The integers in the range of [-5, 256] are singletons in Python and can’t be recreated again.
  2. If the Python compiler can see the whole code, more optimisations may apply to the code.
  3. Different implementations and versions of Python may have different mechanisms for the same feature.

Thanks for reading. If you like it, don’t forget to follow me to get more great articles about programming and technologies!

Relative articles:

Programming
Python
Technology
Data Science
Software Development
Recommended from ReadMedium