<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>Real Python</title>
  <link href="https://realpython.com/atom.xml" rel="self"/>
  <link href="https://realpython.com/"/>
  <updated>2019-05-29T14:00:00+00:00</updated>
  <id>https://realpython.com/</id>
  <author>
    <name>Real Python</name>
  </author>

  
    <entry>
      <title>Pointers in Python: What&#39;s the Point?</title>
      <id>https://realpython.com/pointers-in-python/</id>
      <link href="https://realpython.com/pointers-in-python/"/>
      <updated>2019-05-29T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll get a clearer understanding of Python&#39;s object model and learn why pointers don&#39;t really exist in Python. You&#39;ll also cover ways to simulate pointers in Python without the memory-management nightmare.</summary>
      <content type="html">
        &lt;p&gt;If you&amp;rsquo;ve ever worked with lower level languages like C or C++, then you&amp;rsquo;ve probably heard of pointers. Pointers allow you to create great efficiency in parts of your code. They also cause confusion for beginners and can lead to various memory management bugs, even for experts. So where are they in Python, and how can you simulate pointers in Python?&lt;/p&gt;
&lt;p&gt;Pointers are widely used in C and C++. Essentially, they are variables that hold the memory address of another variable. For a refresher on pointers, you might consider checking out this &lt;a href=&quot;https://www.tutorialspoint.com/cprogramming/c_pointers.htm&quot;&gt;overview on C Pointers.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this article, you&amp;rsquo;ll gain a better understanding of Python&amp;rsquo;s object model and learn why pointers in Python don&amp;rsquo;t really exist. For the cases where you need to mimic pointer behavior, you&amp;rsquo;ll learn ways to simulate pointers in Python without the memory-management nightmare.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this article, you&amp;rsquo;ll:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Learn why pointers in Python don&amp;rsquo;t exist&lt;/li&gt;
&lt;li&gt;Explore the difference between C variables and Python names&lt;/li&gt;
&lt;li&gt;Simulate pointers in Python&lt;/li&gt;
&lt;li&gt;Experiment with real pointers using &lt;code&gt;ctypes&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In this article, &amp;ldquo;Python&amp;rdquo; will refer to the reference implementation of Python in C, otherwise known as CPython. As the article discusses some internals of the language, these notes are true for CPython 3.7 but may not be true in future or past iterations of the language.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-tricks-sample&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a chapter from Python Tricks: The Book&lt;/a&gt; that shows you Python&#39;s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;why-doesnt-python-have-pointers&quot;&gt;Why Doesn&amp;rsquo;t Python Have Pointers?&lt;/h2&gt;
&lt;p&gt;The truth is that I don&amp;rsquo;t know. Could pointers in Python exist natively? Probably, but pointers seem to go against the &lt;a href=&quot;https://www.python.org/dev/peps/pep-0020/#id3&quot;&gt;Zen of Python&lt;/a&gt;. Pointers encourage implicit changes rather than explicit. Often, they are complex instead of simple, especially for beginners. Even worse, they beg for ways to shoot yourself in the foot, or do something really dangerous like read from a section of memory you were not supposed to.&lt;/p&gt;
&lt;p&gt;Python tends to try to abstract away implementation details like memory addresses from its users. Python often focuses on usability instead of speed. As a result, pointers in Python doesn&amp;rsquo;t really make sense. Not to fear though, Python does, by default, give you some of the benefits of using pointers.&lt;/p&gt;
&lt;p&gt;Understanding pointers in Python requires a short detour into Python&amp;rsquo;s implementation details. Specifically, you&amp;rsquo;ll need to understand:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Immutable vs mutable objects&lt;/li&gt;
&lt;li&gt;Python variables/names&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hold onto your memory addresses, and let&amp;rsquo;s get started.&lt;/p&gt;
&lt;h2 id=&quot;objects-in-python&quot;&gt;Objects in Python&lt;/h2&gt;
&lt;p&gt;In Python, everything is an object. For proof, you can open up a REPL and explore using &lt;code&gt;isinstance()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code shows you that everything in Python is indeed an object. Each object contains at least three pieces of data:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reference count&lt;/li&gt;
&lt;li&gt;Type&lt;/li&gt;
&lt;li&gt;Value&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.python.org/3/library/sys.html#sys.getrefcount&quot;&gt;reference count&lt;/a&gt; is for memory management. For an in-depth look at the internals of memory management in Python, you can read &lt;a href=&quot;https://realpython.com/python-memory-management/&quot;&gt;Memory Management in Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The type is used at the CPython layer to ensure type safety during runtime. Finally, there&amp;rsquo;s the value, which is the actual value associated with the object.&lt;/p&gt;
&lt;p&gt;Not all objects are the same though. There is one other important distinction you&amp;rsquo;ll need to understand: immutable vs mutable objects. Understanding the difference between the types of objects really helps clarify the first layer of the onion that is pointers in Python.&lt;/p&gt;
&lt;h2 id=&quot;immutable-vs-mutable-objects&quot;&gt;Immutable vs Mutable Objects&lt;/h2&gt;
&lt;p&gt;In Python, there are two types of objects:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Immutable objects&lt;/strong&gt; can&amp;rsquo;t be changed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mutable objects&lt;/strong&gt; can be changed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Understanding this difference is the first key to navigating the landscape of pointers in Python. Here&amp;rsquo;s a breakdown of common types and whether or not they are mutable or immutable:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th class=&quot;text-center&quot;&gt;Type&lt;/th&gt;
&lt;th class=&quot;text-center&quot;&gt;Immutable?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;&lt;code&gt;float&lt;/code&gt;&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;&lt;code&gt;bool&lt;/code&gt;&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;&lt;code&gt;complex&lt;/code&gt;&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;&lt;code&gt;tuple&lt;/code&gt;&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;&lt;code&gt;frozenset&lt;/code&gt;&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;&lt;code&gt;list&lt;/code&gt;&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;&lt;code&gt;set&lt;/code&gt;&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;&lt;code&gt;dict&lt;/code&gt;&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;As you can see, lots of commonly used primitive types are immutable. You can prove this yourself by writing some Python. You&amp;rsquo;ll need a couple of tools from the Python standard library:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;id()&lt;/code&gt;&lt;/strong&gt; returns the object&amp;rsquo;s memory address.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;is&lt;/code&gt;&lt;/strong&gt; returns &lt;code&gt;True&lt;/code&gt; if and only if two objects have the same memory address.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Once again, you can use these in a REPL environment:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;94529957049376&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above code, you have assigned the value &lt;code&gt;5&lt;/code&gt; to &lt;code&gt;x&lt;/code&gt;. If you tried to modify this value with addition, then you&amp;rsquo;d get a new object:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;94529957049408&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Even though the above code appears to modify the value of &lt;code&gt;x&lt;/code&gt;, you&amp;rsquo;re getting a &lt;em&gt;new&lt;/em&gt; object as a response. &lt;/p&gt;
&lt;p&gt;The &lt;code&gt;str&lt;/code&gt; type is also immutable:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;real_python&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;140637819584048&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;_rocks&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;real_python_rocks&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;140637819609424&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Again, &lt;code&gt;s&lt;/code&gt; ends up with a &lt;em&gt;different&lt;/em&gt; memory addresses after the &lt;code&gt;+=&lt;/code&gt; operation.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Bonus:&lt;/strong&gt; The &lt;code&gt;+=&lt;/code&gt; operator translates to various method calls. &lt;/p&gt;
&lt;p&gt;For some objects like &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;+=&lt;/code&gt; will translate into &lt;code&gt;__iadd__()&lt;/code&gt; (in-place add). This will modify &lt;code&gt;self&lt;/code&gt; and return the same ID. However, &lt;code&gt;str&lt;/code&gt; and &lt;code&gt;int&lt;/code&gt; don&amp;rsquo;t have these methods and result in &lt;code&gt;__add__()&lt;/code&gt; calls instead of &lt;code&gt;__iadd__()&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;For more detailed information, check out the Python &lt;a href=&quot;https://docs.python.org/3/reference/datamodel.html#object.__iadd__&quot;&gt;data model docs.&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Trying to directly mutate the string &lt;code&gt;s&lt;/code&gt; results in an error:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;R&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;str&amp;#39; object does not support item assignment&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above code fails, and Python indicates that &lt;code&gt;str&lt;/code&gt; doesn&amp;rsquo;t support this mutation, which is in line with the definition that the &lt;code&gt;str&lt;/code&gt; type is immutable. &lt;/p&gt;
&lt;p&gt;Contrast that with a mutable object, like &lt;code&gt;list&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;140637819575368&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 2, 3, 4]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;140637819575368&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code shows a major difference in the two types of objects. &lt;code&gt;my_list&lt;/code&gt; has an id originally. Even after &lt;code&gt;4&lt;/code&gt; is appended to the list, &lt;code&gt;my_list&lt;/code&gt; has the &lt;em&gt;same&lt;/em&gt; id. This is because the &lt;code&gt;list&lt;/code&gt; type is mutable. &lt;/p&gt;
&lt;p&gt;Another way to demonstrate that the list is mutable is with assignment:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[0, 2, 3, 4]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;140637819575368&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you mutate &lt;code&gt;my_list&lt;/code&gt; and set its first element to &lt;code&gt;0&lt;/code&gt;. However, it maintains the same id even after this assignment. With mutable and immutable objects out of the way, the next step on your journey to &lt;a href=&quot;https://realpython.com/pycon-guide/#what-to-do-at-pycon&quot;&gt;Python enlightenment&lt;/a&gt; is understanding Python&amp;rsquo;s variable ecosystem.&lt;/p&gt;
&lt;h2 id=&quot;understanding-variables&quot;&gt;Understanding Variables&lt;/h2&gt;
&lt;p&gt;Python variables are fundamentally different than variables in C or C++. In fact, Python doesn&amp;rsquo;t even have variables. &lt;em&gt;Python has names, not variables.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This might seem pedantic, and for the most part, it is. Most of the time, it&amp;rsquo;s perfectly acceptable to think about Python names as variables, but understanding the difference is important. This is especially true when you&amp;rsquo;re navigating the tricky subject of pointers in Python.&lt;/p&gt;
&lt;p&gt;To help drive home the difference, you can take a look at how variables work in C, what they represent, and then contrast that with how names work in Python.&lt;/p&gt;
&lt;h3 id=&quot;variables-in-c&quot;&gt;Variables in C&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s say you had the following code that defines the variable &lt;code&gt;x&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2337&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This one line of code has several, distinct steps when executed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Allocate enough memory for an integer&lt;/li&gt;
&lt;li&gt;Assign the value &lt;code&gt;2337&lt;/code&gt; to that memory location&lt;/li&gt;
&lt;li&gt;Indicate that &lt;code&gt;x&lt;/code&gt; points to that value&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Shown in a simplified view of memory, it might look like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/c_memory1.334fe7c13e82.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-33&quot; src=&quot;https://files.realpython.com/media/c_memory1.334fe7c13e82.png&quot; width=&quot;311&quot; height=&quot;171&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/c_memory1.334fe7c13e82.png&amp;amp;w=77&amp;amp;sig=328835e6883ea9179c95d38b3412eb0427331b97 77w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/c_memory1.334fe7c13e82.png&amp;amp;w=155&amp;amp;sig=e77240f1416f137d8274b143a4479b575d696e59 155w, https://files.realpython.com/media/c_memory1.334fe7c13e82.png 311w&quot; sizes=&quot;75vw&quot; alt=&quot;In-Memory representation of X (2337)&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here, you can see that the variable &lt;code&gt;x&lt;/code&gt; has a fake memory location of &lt;code&gt;0x7f1&lt;/code&gt; and the value &lt;code&gt;2337&lt;/code&gt;. If, later in the program, you want to change the value of &lt;code&gt;x&lt;/code&gt;, you can do the following:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2338&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above code assigns a new value (&lt;code&gt;2338&lt;/code&gt;) to the variable &lt;code&gt;x&lt;/code&gt;, thereby &lt;em&gt;overwriting&lt;/em&gt; the previous value. This means that the variable &lt;code&gt;x&lt;/code&gt; is &lt;strong&gt;mutable&lt;/strong&gt;. The updated memory layout shows the new value:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/c_memory2.14d638daf718.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-33&quot; src=&quot;https://files.realpython.com/media/c_memory2.14d638daf718.png&quot; width=&quot;311&quot; height=&quot;171&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/c_memory2.14d638daf718.png&amp;amp;w=77&amp;amp;sig=6d8ccf15da8f01fb89c7c1383a5d270793715485 77w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/c_memory2.14d638daf718.png&amp;amp;w=155&amp;amp;sig=c94a488612806ae5f026838bbad0f9fa7533c8cc 155w, https://files.realpython.com/media/c_memory2.14d638daf718.png 311w&quot; sizes=&quot;75vw&quot; alt=&quot;New In-Memory representation of X (2338)&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notice that the location of &lt;code&gt;x&lt;/code&gt; didn&amp;rsquo;t change, just the value itself. This is a significant point. It means that &lt;code&gt;x&lt;/code&gt; &lt;em&gt;is the memory location&lt;/em&gt;, not just a name for it.&lt;/p&gt;
&lt;p&gt;Another way to think of this concept is in terms of ownership. In one sense, &lt;code&gt;x&lt;/code&gt; owns the memory location. &lt;code&gt;x&lt;/code&gt; is, at first, an empty box that can fit exactly one integer in which integer values can be stored.&lt;/p&gt;
&lt;p&gt;When you assign a value to &lt;code&gt;x&lt;/code&gt;, you&amp;rsquo;re placing a value in the box that &lt;code&gt;x&lt;/code&gt; owns. If you wanted to introduce a new variable (&lt;code&gt;y&lt;/code&gt;), you could add this line of code:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code creates a &lt;em&gt;new&lt;/em&gt; box called &lt;code&gt;y&lt;/code&gt; and copies the value from &lt;code&gt;x&lt;/code&gt; into the box. Now the memory layout will look like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/c_memory3.5afe110faf4d.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-66&quot; src=&quot;https://files.realpython.com/media/c_memory3.5afe110faf4d.png&quot; width=&quot;716&quot; height=&quot;171&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/c_memory3.5afe110faf4d.png&amp;amp;w=179&amp;amp;sig=82363e325cab6442d9ea5b3f18b80b2df78e17c0 179w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/c_memory3.5afe110faf4d.png&amp;amp;w=358&amp;amp;sig=35924366553307de961bbe1b5c8a91eb921c1fe6 358w, https://files.realpython.com/media/c_memory3.5afe110faf4d.png 716w&quot; sizes=&quot;75vw&quot; alt=&quot;In-Memory representation of X (2338) and Y (2338)&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notice the new location &lt;code&gt;0x7f5&lt;/code&gt; of &lt;code&gt;y&lt;/code&gt;. Even though the value of &lt;code&gt;x&lt;/code&gt; was copied to &lt;code&gt;y&lt;/code&gt;, the variable &lt;code&gt;y&lt;/code&gt; owns some new address in memory. Therefore, you could overwrite the value of &lt;code&gt;y&lt;/code&gt; without affecting &lt;code&gt;x&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2339&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the memory layout will look like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/c_memory4.45a45dbbfaab.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-66&quot; src=&quot;https://files.realpython.com/media/c_memory4.45a45dbbfaab.png&quot; width=&quot;716&quot; height=&quot;171&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/c_memory4.45a45dbbfaab.png&amp;amp;w=179&amp;amp;sig=05707263b0f1abc7d2dac59741264689a76cae9e 179w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/c_memory4.45a45dbbfaab.png&amp;amp;w=358&amp;amp;sig=a81deebb259727d91b96aa187177786681cda30a 358w, https://files.realpython.com/media/c_memory4.45a45dbbfaab.png 716w&quot; sizes=&quot;75vw&quot; alt=&quot;Updated representation of Y (2339)&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Again, you have modified the value at &lt;code&gt;y&lt;/code&gt;, but &lt;em&gt;not&lt;/em&gt; its location. In addition, you have not affected the original &lt;code&gt;x&lt;/code&gt; variable at all. This is in stark contrast with how Python names work.&lt;/p&gt;
&lt;h3 id=&quot;names-in-python&quot;&gt;Names in Python&lt;/h3&gt;
&lt;p&gt;Python does not have variables. It has names. Yes, this is a pedantic point, and you can certainly use the term variables as much as you like. It is important to know that there is a difference between variables and names.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take the equivalent code from the above C example and write it in Python:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2337&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Much like in C, the above code is broken down into several distinct steps during execution:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a &lt;code&gt;PyObject&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set the typecode to integer for the &lt;code&gt;PyObject&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Set the value to &lt;code&gt;2337&lt;/code&gt; for the &lt;code&gt;PyObject&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Create a name called &lt;code&gt;x&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Point &lt;code&gt;x&lt;/code&gt; to the new &lt;code&gt;PyObject&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Increase the refcount of the &lt;code&gt;PyObject&lt;/code&gt; by 1&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The &lt;a href=&quot;https://github.com/python/cpython/blob/v3.7.3/Include/object.h#L101&quot;&gt;&lt;code&gt;PyObject&lt;/code&gt;&lt;/a&gt; is not the same as Python&amp;rsquo;s &lt;code&gt;object&lt;/code&gt;. It&amp;rsquo;s specific to CPython and represents the base structure for all Python objects. &lt;/p&gt;
&lt;p&gt;&lt;code&gt;PyObject&lt;/code&gt; is defined as a C struct, so if you&amp;rsquo;re wondering why you can&amp;rsquo;t call &lt;code&gt;typecode&lt;/code&gt; or &lt;code&gt;refcount&lt;/code&gt; directly, its because you don&amp;rsquo;t have access to the structures directly. Method calls like &lt;a href=&quot;https://docs.python.org/3/library/sys.html#sys.getrefcount&quot;&gt;&lt;code&gt;sys.getrefcount()&lt;/code&gt;&lt;/a&gt; can help get some internals.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;In memory, it might looks something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/py_memory1.2b6e5f8e5bc9.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-66&quot; src=&quot;https://files.realpython.com/media/py_memory1.2b6e5f8e5bc9.png&quot; width=&quot;716&quot; height=&quot;291&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/py_memory1.2b6e5f8e5bc9.png&amp;amp;w=179&amp;amp;sig=aed50727b48c61e5f1c7b554297c7f83f610da00 179w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/py_memory1.2b6e5f8e5bc9.png&amp;amp;w=358&amp;amp;sig=ec24d415b50885917863ed52ed1360ff27f9ffaa 358w, https://files.realpython.com/media/py_memory1.2b6e5f8e5bc9.png 716w&quot; sizes=&quot;75vw&quot; alt=&quot;Python In-Memory representation of X (2337)&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see that the memory layout is vastly different than the C layout from before. Instead of &lt;code&gt;x&lt;/code&gt; owning the block of memory where the value &lt;code&gt;2337&lt;/code&gt; resides, the newly created Python object owns the memory where &lt;code&gt;2337&lt;/code&gt; lives. The Python name &lt;code&gt;x&lt;/code&gt; doesn&amp;rsquo;t directly own &lt;em&gt;any&lt;/em&gt; memory address in the way the C variable &lt;code&gt;x&lt;/code&gt; owned a static slot in memory.&lt;/p&gt;
&lt;p&gt;If you were to try to assign a new value to &lt;code&gt;x&lt;/code&gt;, you could try the following:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2338&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;What&amp;rsquo;s happening here is different than the C equivalent, but not too different from the original bind in Python.&lt;/p&gt;
&lt;p&gt;This code:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Creates a new &lt;code&gt;PyObject&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sets the typecode to integer for the &lt;code&gt;PyObject&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Sets the value to &lt;code&gt;2338&lt;/code&gt; for the &lt;code&gt;PyObject&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Points &lt;code&gt;x&lt;/code&gt; to the new &lt;code&gt;PyObject&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Increases the refcount of the new &lt;code&gt;PyObject&lt;/code&gt; by 1&lt;/li&gt;
&lt;li&gt;Decreases the refcount of the old &lt;code&gt;PyObject&lt;/code&gt; by 1&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now in memory, it would look something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/py_memory2.99bb432c3432.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-66&quot; src=&quot;https://files.realpython.com/media/py_memory2.99bb432c3432.png&quot; width=&quot;717&quot; height=&quot;611&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/py_memory2.99bb432c3432.png&amp;amp;w=179&amp;amp;sig=74dca4ec34742cefd1a1e26aeaadd7c4a1429f28 179w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/py_memory2.99bb432c3432.png&amp;amp;w=358&amp;amp;sig=db3dd657773d4adba7a2216f89a61fca83451ba8 358w, https://files.realpython.com/media/py_memory2.99bb432c3432.png 717w&quot; sizes=&quot;75vw&quot; alt=&quot;Python Name Pointing to new object (2338)&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This diagram helps illustrate that &lt;code&gt;x&lt;/code&gt; points to a reference to an object and doesn&amp;rsquo;t own the memory space as before. It also shows that the &lt;code&gt;x = 2338&lt;/code&gt; command is not an assignment, but rather binding the name &lt;code&gt;x&lt;/code&gt; to a reference.&lt;/p&gt;
&lt;p&gt;In addition, the previous object (which held the &lt;code&gt;2337&lt;/code&gt; value) is now sitting in memory with a ref count of 0 and will get cleaned up by the &lt;a href=&quot;https://docs.python.org/3/faq/design.html?highlight=garbage%20collect#how-does-python-manage-memory&quot;&gt;garbage collector&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You could introduce a new name, &lt;code&gt;y&lt;/code&gt;, to the mix as in the C example:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In memory, you would have a new name, but not necessarily a new object:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/py_memory3_1.ea43471d3bf6.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-66&quot; src=&quot;https://files.realpython.com/media/py_memory3_1.ea43471d3bf6.png&quot; width=&quot;716&quot; height=&quot;611&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/py_memory3_1.ea43471d3bf6.png&amp;amp;w=179&amp;amp;sig=9a66c72fce91dd9fe96231dcf82bea52ead4709b 179w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/py_memory3_1.ea43471d3bf6.png&amp;amp;w=358&amp;amp;sig=fd13efbbca2a7619cd87886ab6bb8fbe09904bf8 358w, https://files.realpython.com/media/py_memory3_1.ea43471d3bf6.png 716w&quot; sizes=&quot;75vw&quot; alt=&quot;X and Y Names pointing to 2338&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now you can see that a new Python object has &lt;em&gt;not&lt;/em&gt; been created, just a new name that points to the same object. Also, the object&amp;rsquo;s refcount has increased by one. You could check for object identity equality to confirm that they are the same:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above code indicates that &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; are the same object. Make no mistake though: &lt;code&gt;y&lt;/code&gt; is still immutable. &lt;/p&gt;
&lt;p&gt;For example, you could perform addition on &lt;code&gt;y&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After the addition call, you are returned with a new Python object. Now, the memory looks like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/py_memory4.0a15e8415a15.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/py_memory4.0a15e8415a15.png&quot; width=&quot;1141&quot; height=&quot;626&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/py_memory4.0a15e8415a15.png&amp;amp;w=285&amp;amp;sig=4f4b4fe32539f022b330468a28b28158692a81b7 285w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/py_memory4.0a15e8415a15.png&amp;amp;w=570&amp;amp;sig=eaf8c12475a6581941250f988c0151bec6abc776 570w, https://files.realpython.com/media/py_memory4.0a15e8415a15.png 1141w&quot; sizes=&quot;75vw&quot; alt=&quot;x name and y name different objects&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A new object has been created, and &lt;code&gt;y&lt;/code&gt; now points to the new object. Interestingly, this is the same end-state if you had bound &lt;code&gt;y&lt;/code&gt; to &lt;code&gt;2339&lt;/code&gt; directly:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2339&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above statement results in the same end-memory state as the addition. To recap, in Python, you don&amp;rsquo;t assign variables. Instead, you bind names to references.&lt;/p&gt;
&lt;h3 id=&quot;a-note-on-intern-objects-in-python&quot;&gt;A Note on Intern Objects in Python&lt;/h3&gt;
&lt;p&gt;Now that you understand how Python objects get created and names get bound to those objects, its time to throw a wrench in the machinery. That wrench goes by the name of interned objects.&lt;/p&gt;
&lt;p&gt;Suppose you have the following Python code:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As above, &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; are both names that point to the same Python object. But the Python object that holds the value &lt;code&gt;1000&lt;/code&gt; is not always guaranteed to have the same memory address. For example, if you were to add two numbers together to get &lt;code&gt;1000&lt;/code&gt;, you would end up with a different memory address:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;499&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;501&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This time, the line &lt;code&gt;x is y&lt;/code&gt; returns &lt;code&gt;False&lt;/code&gt;. If this is confusing, then don&amp;rsquo;t worry. Here are the steps that occur when this code is executed:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create Python object(&lt;code&gt;1000&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Assign the name &lt;code&gt;x&lt;/code&gt; to that object&lt;/li&gt;
&lt;li&gt;Create Python object (&lt;code&gt;499&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Create Python object (&lt;code&gt;501&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Add these two objects together&lt;/li&gt;
&lt;li&gt;Create a new Python object (&lt;code&gt;1000&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Assign the name &lt;code&gt;y&lt;/code&gt; to that object&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Technical Note:&lt;/strong&gt; The above steps occur only when this code is executed inside a REPL. If you were to take the example above, paste it into a file, and  run the file, then you would find that the &lt;code&gt;x is y&lt;/code&gt; line would return &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This occurs because compilers are smart. The CPython compiler attempts to make optimizations called &lt;a href=&quot;https://en.wikipedia.org/wiki/Peephole_optimization&quot;&gt;peephole optimizations&lt;/a&gt;, which help save execution steps whenever possible. For detailed information, you can check out &lt;a href=&quot;https://github.com/python/cpython/blob/master/Python/peephole.c&quot;&gt;CPython&amp;rsquo;s peephole optimizer source code&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Isn&amp;rsquo;t this wasteful? Well, yes it is, but that&amp;rsquo;s the price you pay for all of the great benefits of Python. You never have to worry about cleaning up these intermediate objects or even need to know that they exist! The joy is that these operations are relatively fast, and you never had to know any of those details until now.&lt;/p&gt;
&lt;p&gt;The core Python developers, in their wisdom, also noticed this waste and decided to make a few optimizations. These optimizations result in behavior that can be surprising to newcomers:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you see nearly the same code as before, except this time the result is &lt;code&gt;True&lt;/code&gt;. This is the result of interned objects. Python pre-creates a certain subset of objects in memory and keeps them in the global namespace for everyday use.&lt;/p&gt;
&lt;p&gt;Which objects depend on the implementation of Python. CPython 3.7 interns the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Integer numbers between &lt;code&gt;-5&lt;/code&gt; and &lt;code&gt;256&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Strings that contain ASCII letters, digits, or underscores only&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The reasoning behind this is that these variables are extremely likely to be used in many programs. By interning these objects, Python prevents memory allocation calls for consistently used objects.&lt;/p&gt;
&lt;p&gt;Strings that are less than 20 characters and contain ASCII letters, digits, or underscores will be interned. The reasoning behind this is that these are assumed to be some kind of identity:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;realpython&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;140696485006960&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;realpython&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;140696485006960&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here you can see that &lt;code&gt;s1&lt;/code&gt; and &lt;code&gt;s2&lt;/code&gt; both point to the same address in memory. If you were to introduce a non-ASCII letter, digit, or underscore, then you would get a different result:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Real Python!&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Real Python!&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because this example has an exclamation mark (&lt;code&gt;!&lt;/code&gt;) in it, these strings are not interned and are different objects in memory.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Bonus:&lt;/strong&gt; If you really want these objects to reference the same internal object, then you may want to check out &lt;code&gt;sys.intern()&lt;/code&gt;. One of the use cases for this function is outlined in the documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Interning strings is useful to gain a little performance on dictionary lookup&amp;mdash;if the keys in a dictionary are interned, and the lookup key is interned, the key comparisons (after hashing) can be done by a pointer compare instead of a string compare. (&lt;a href=&quot;https://docs.python.org/3/library/sys.html#sys.intern&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
&lt;p&gt;Interned objects are often a source of confusion. Just remember, if you&amp;rsquo;re ever in doubt, that you can always use &lt;code&gt;id()&lt;/code&gt; and &lt;code&gt;is&lt;/code&gt; to determine object equality.&lt;/p&gt;
&lt;h2 id=&quot;simulating-pointers-in-python&quot;&gt;Simulating Pointers in Python&lt;/h2&gt;
&lt;p&gt;Just because pointers in Python don&amp;rsquo;t exist natively doesn&amp;rsquo;t mean you can&amp;rsquo;t get the benefits of using pointers. In fact, there are multiple ways to simulate pointers in Python. You&amp;rsquo;ll learn two in this section:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Using mutable types as pointers&lt;/li&gt;
&lt;li&gt;Using custom Python objects&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Okay, let&amp;rsquo;s get to the point.&lt;/p&gt;
&lt;h3 id=&quot;using-mutable-types-as-pointers&quot;&gt;Using Mutable Types as Pointers&lt;/h3&gt;
&lt;p&gt;You&amp;rsquo;ve already learned about mutable types. Because these objects are mutable, you can treat them as if they were pointers to simulate pointer behavior. Suppose you wanted to replicate the following c code:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code takes a pointer to an integer (&lt;code&gt;*x&lt;/code&gt;) and then increments the value by one. Here is a main function to exercise the code:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;cpf&quot;&gt;&amp;lt;stdio.h&amp;gt;&lt;/span&gt;&lt;span class=&quot;cp&quot;&gt;&lt;/span&gt;

&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2337&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;y = %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;y = %d&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above code, you assign &lt;code&gt;2337&lt;/code&gt; to &lt;code&gt;y&lt;/code&gt;, print out the current value, increment the value by one, and then print out the modified value. The output of executing this code would be the following:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;y = 2337&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;y = 2338&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;One way to replicate this type of behavior in Python is by using a mutable type. Consider using a list and modifying the first element:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2337&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2338&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, &lt;code&gt;add_one(x)&lt;/code&gt; accesses the first element and increments its value by one. Using a &lt;code&gt;list&lt;/code&gt; means that the end result appears to have modified the value. So pointers in Python do exist? Well, no. This is only possible because &lt;code&gt;list&lt;/code&gt; is a mutable type. If you tried to use a &lt;code&gt;tuple&lt;/code&gt;, you would get an error:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2337&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;z&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;tuple&amp;#39; object does not support item assignment&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above code demonstrates that &lt;code&gt;tuple&lt;/code&gt; is immutable. Therefore, it does not support item assignment. &lt;code&gt;list&lt;/code&gt; is not the only mutable type. Another common approach to mimicking pointers in Python is to use a &lt;code&gt;dict&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say you had an application where you wanted to keep track of every time an interesting event happened. One way to achieve this would be to create a &lt;code&gt;dict&lt;/code&gt; and use one of the items as a counter:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;func_calls&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;counters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;func_calls&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;counters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;func_calls&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;counters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;func_calls&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, the &lt;code&gt;counters&lt;/code&gt; dictionary is used to keep track of the number of function calls. After you call &lt;code&gt;foo()&lt;/code&gt;, the counter has increased to &lt;code&gt;2&lt;/code&gt; as expected. All because &lt;code&gt;dict&lt;/code&gt; is mutable.&lt;/p&gt;
&lt;p&gt;Keep in mind, this is only &lt;em&gt;simulates&lt;/em&gt; pointer behavior and does not directly map to true pointers in C or C++. That is to say, these operations are more expensive than they would be in C or C++.&lt;/p&gt;
&lt;h3 id=&quot;using-python-objects&quot;&gt;Using Python Objects&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;dict&lt;/code&gt; option is a great way to emulate pointers in Python, but sometimes it gets tedious to remember the key name you used. This is especially true if you&amp;rsquo;re using the dictionary in various parts of your application. This is where a custom Python class can really help.&lt;/p&gt;
&lt;p&gt;To build on the last example, assume that you want to track metrics in your application. Creating a class is a great way to abstract the pesky details:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_metrics&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;func_calls&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;cat_pictures_served&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code defines a &lt;code&gt;Metrics&lt;/code&gt; class. This class still uses a &lt;code&gt;dict&lt;/code&gt; for holding the actual data, which is in the &lt;code&gt;_metrics&lt;/code&gt; member variable. This will give you the mutability you need. Now you just need to be able to access these values. One nice way to do this is with properties:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@property&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func_calls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;func_calls&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@property&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cat_pictures_served&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;cat_pictures_served&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code makes use of &lt;a href=&quot;https://docs.python.org/3/library/functions.html#property&quot;&gt;&lt;code&gt;@property&lt;/code&gt;&lt;/a&gt;. If you&amp;rsquo;re not familiar with decorators, you can check out this &lt;a href=&quot;https://realpython.com/primer-on-python-decorators/&quot;&gt;Primer on Python Decorators&lt;/a&gt;. The &lt;code&gt;@property&lt;/code&gt; decorator here allows you to access &lt;code&gt;func_calls&lt;/code&gt; and &lt;code&gt;cat_pictures_served&lt;/code&gt; as if they were attributes:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metrics&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func_calls&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cat_pictures_served&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The fact that you can access these names as attributes means that you abstracted the fact that these values are in a &lt;code&gt;dict&lt;/code&gt;. You also make it more explicit what the names of the attributes are. Of course, you need to be able to increment these values:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;inc_func_calls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;func_calls&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;inc_cat_pics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;cat_pictures_served&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You have introduced two new methods:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;inc_func_calls()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;inc_cat_pics()&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These methods modify the values in the metrics &lt;code&gt;dict&lt;/code&gt;. You now have a class that you modify as if you&amp;rsquo;re modifying a pointer:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metrics&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inc_func_calls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;inc_func_calls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metrics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func_calls&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you can access &lt;code&gt;func_calls&lt;/code&gt; and call &lt;code&gt;inc_func_calls()&lt;/code&gt; in various places in your applications and simulate pointers in Python. This is useful when you have something like metrics that need to be used and updated frequently in various parts of your applications.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In this class in particular, making &lt;code&gt;inc_func_calls()&lt;/code&gt; and &lt;code&gt;inc_cat_pics()&lt;/code&gt; explicit instead of using &lt;code&gt;@property.setter&lt;/code&gt; prevents users from setting these values to an arbitrary &lt;code&gt;int&lt;/code&gt; or an invalid value like a &lt;code&gt;dict&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Here&amp;rsquo;s the full source for the &lt;code&gt;Metrics&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_metrics&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;func_calls&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;cat_pictures_served&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@property&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func_calls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;func_calls&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@property&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;cat_pictures_served&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;cat_pictures_served&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;inc_func_calls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;func_calls&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;inc_cat_pics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_metrics&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;cat_pictures_served&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;real-pointers-with-ctypes&quot;&gt;Real Pointers With &lt;code&gt;ctypes&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Okay, so maybe there are pointers in Python, specifically CPython. Using the builtin &lt;code&gt;ctypes&lt;/code&gt; module, you can create real C-style pointers in Python. If you are unfamiliar with &lt;code&gt;ctypes&lt;/code&gt;, then you can take a look at &lt;a href=&quot;https://dbader.org/blog/python-ctypes-tutorial&quot;&gt;Extending Python With C Libraries and the &amp;ldquo;ctypes&amp;rdquo; Module&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The real reason you would use this is if you needed to make a function call to a C library that requires a pointer. Let&amp;rsquo;s go back to the &lt;code&gt;add_one()&lt;/code&gt; C-function from before:&lt;/p&gt;
&lt;div class=&quot;highlight c&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here again, this code is incrementing the value of &lt;code&gt;x&lt;/code&gt; by one. To use this, first compile it into a shared object. Assuming the above file is stored in &lt;code&gt;add.c&lt;/code&gt;, you could accomplish this with &lt;code&gt;gcc&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; gcc -c -Wall -Werror -fpic add.c
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; gcc -shared -o libadd1.so add.o
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first command compiles the C source file into an object called &lt;code&gt;add.o&lt;/code&gt;. The second command takes that unlinked object file and produces a shared object called &lt;code&gt;libadd1.so&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;&lt;code&gt;libadd1.so&lt;/code&gt; should be in your current directory. You can load it into Python using &lt;code&gt;ctypes&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ctypes&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_lib&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CDLL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;./libadd1.so&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_lib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;_FuncPtr object at 0x7f9f3b8852a0&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;ctypes.CDLL&lt;/code&gt; code returns an object that represents the &lt;code&gt;libadd1&lt;/code&gt; shared object. Because you defined &lt;code&gt;add_one()&lt;/code&gt; in this shared object, you can access it as if it were any other Python object. Before you call the function though, you should specify the function signature. This helps Python ensure that you pass the right type to the function.&lt;/p&gt;
&lt;p&gt;In this case, the function signature is a pointer to an integer. &lt;code&gt;ctypes&lt;/code&gt; will allow you to specify this using the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add_lib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argtypes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;POINTER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you&amp;rsquo;re setting the function signature to match what C is expecting. Now, if you were to try to call this code with the wrong type, then you would get a nice warning instead of undefined behavior:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;ctypes.ArgumentError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;argument 1: &amp;lt;class &amp;#39;TypeError&amp;#39;&amp;gt;: \&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;expected LP_c_int instance instead of int&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python throws an error, explaining that &lt;code&gt;add_one()&lt;/code&gt; wants a pointer instead of just an integer. Luckily, &lt;code&gt;ctypes&lt;/code&gt; has a way to pass pointers to these functions. First, declare a C-style integer:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ctypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c_int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;c_int(0)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above code creates a C-style integer &lt;code&gt;x&lt;/code&gt; with a value of &lt;code&gt;0&lt;/code&gt;. &lt;code&gt;ctypes&lt;/code&gt; provides the handy &lt;code&gt;byref()&lt;/code&gt; to allow passing a variable by reference.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The term &lt;strong&gt;by reference&lt;/strong&gt; is opposed to passing a variable &lt;strong&gt;by value&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;When passing by reference, you&amp;rsquo;re passing the reference to the original variable, and thus modifications will be reflected in the original variable. Passing by value results in a copy of the original variable, and modifications are not reflected in the original.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can use this to call &lt;code&gt;add_one()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_one&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctypes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;byref&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;998793640&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;c_int(1)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Nice! Your integer was incremented by one. Congratulations, you have successfully used real pointers in Python.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You now have a better understanding of the intersection between Python objects and pointers. Even though some of the distinctions between names and variables seem pedantic, fundamentally understanding these key terms expands your understanding of how Python handles variables.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve also learned some excellent ways to simulate pointers in Python:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Utilizing mutable objects as low-overhead pointers&lt;/li&gt;
&lt;li&gt;Creating custom Python objects for ease of use&lt;/li&gt;
&lt;li&gt;Unlocking real pointers with the &lt;code&gt;ctypes&lt;/code&gt; module&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These methods allow you to simulate pointers in Python without sacrificing the memory safety that Python provides.&lt;/p&gt;
&lt;p&gt;Thanks for reading. If you still have questions, feel free to reach out either in the comments section or on Twitter.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Continuous Integration With Python</title>
      <id>https://realpython.com/courses/python-continuous-integration/</id>
      <link href="https://realpython.com/courses/python-continuous-integration/"/>
      <updated>2019-05-28T14:00:00+00:00</updated>
      <summary>In this course, you&#39;ll learn the core concepts behind Continuous Integration (CI) and why they are essential for modern software engineering teams. Find out how to how set up Continuous Integration for your Python project to automatically create environments, install dependencies, and run tests.</summary>
      <content type="html">
        &lt;p&gt;In this course, you&amp;rsquo;ll learn the core concepts behind Continuous Integration (CI) and why they are essential for modern software engineering teams. &lt;/p&gt;
&lt;p&gt;Find out how to how set up Continuous Integration for your Python project to automatically create environments, install dependencies, and run tests.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>How to Iterate Through a Dictionary in Python</title>
      <id>https://realpython.com/iterate-through-dictionary-python/</id>
      <link href="https://realpython.com/iterate-through-dictionary-python/"/>
      <updated>2019-05-27T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll take a deep dive into how to iterate through a dictionary in Python. Dictionaries are a fundamental data structure, and you&#39;ll be able to solve a wide variety of programming problems by iterating through them.</summary>
      <content type="html">
        &lt;p&gt;Dictionaries are one of the most important and useful data structures in Python. They can help you solve a wide variety of programming problems. This tutorial will take you on a deep dive into how to iterate through a dictionary in Python.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this tutorial, you&amp;rsquo;ll know:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What dictionaries are, as well as some of their main features and implementation details&lt;/li&gt;
&lt;li&gt;How to iterate through a dictionary in Python by using the basic tools the language offers&lt;/li&gt;
&lt;li&gt;What kind of real-world tasks you can perform by iterating through a dictionary in Python&lt;/li&gt;
&lt;li&gt;How to use some more advanced techniques and strategies to iterate through a dictionary in Python&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more information on dictionaries, you can check out the following resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-dicts&quot;&gt;Dictionaries in Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-itertools&quot;&gt;Itertools in Python 3, By Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The documentation for &lt;a href=&quot;https://docs.python.org/3/library/functions.html#map&quot;&gt;&lt;code&gt;map()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://docs.python.org/3/library/functions.html#filter&quot;&gt;&lt;code&gt;filter()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ready? Let&amp;rsquo;s go!&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-tricks-sample&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a chapter from Python Tricks: The Book&lt;/a&gt; that shows you Python&#39;s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;a-few-words-on-dictionaries&quot;&gt;A Few Words on Dictionaries&lt;/h2&gt;
&lt;p&gt;Dictionaries are a cornerstone of Python. The language itself is built around dictionaries. Modules, classes, objects, &lt;code&gt;globals()&lt;/code&gt;, &lt;code&gt;locals()&lt;/code&gt;: all of these are dictionaries. Dictionaries have been central to Python from its very beginning.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.python.org/3/index.html&quot;&gt;Python&amp;rsquo;s official documentation&lt;/a&gt; defines a dictionary as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;An associative array, where arbitrary keys are mapped to values.  The keys can be any object with &lt;code&gt;__hash__()&lt;/code&gt; and &lt;code&gt;__eq__()&lt;/code&gt; methods. (&lt;a href=&quot;https://docs.python.org/3/glossary.html#term-dictionary&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There are a couple points to keep in mind:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Dictionaries map keys to values and store them in an array or collection.&lt;/li&gt;
&lt;li&gt;The keys must be of a &lt;a href=&quot;https://docs.python.org/3/glossary.html#term-hashable&quot;&gt;hashable&lt;/a&gt; type, which means that they must have a hash value that never changes during the key&amp;rsquo;s lifetime.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Dictionaries are frequently used for solving all kinds of programming problems, so they are a fundamental piece of your tool kit as a Python developer.&lt;/p&gt;
&lt;p&gt;Unlike &lt;strong&gt;&lt;a href=&quot;https://docs.python.org/3/glossary.html#term-sequence&quot;&gt;sequences&lt;/a&gt;&lt;/strong&gt;, which are &lt;a href=&quot;https://docs.python.org/3/glossary.html#term-iterable&quot;&gt;iterables&lt;/a&gt; that support element access using integer indices, dictionaries are indexed by keys.&lt;/p&gt;
&lt;p&gt;The keys in a dictionary are much like a &lt;a href=&quot;https://realpython.com/python-sets/&quot;&gt;&lt;code&gt;set&lt;/code&gt;&lt;/a&gt;, which is a collection of hashable and unique objects. Because the objects need to be hashable, &lt;a href=&quot;https://docs.python.org/3/glossary.html#term-mutable&quot;&gt;mutable&lt;/a&gt; objects can&amp;rsquo;t be used as dictionary keys.&lt;/p&gt;
&lt;p&gt;On the other hand, values can be of any Python type, whether they are hashable or not. There are literally no restrictions for values.&lt;/p&gt;
&lt;p&gt;In Python 3.6 and beyond, the keys and values of a dictionary are iterated over in the same order in which they were created. However, this behavior may vary across different Python versions, and it depends on the dictionary&amp;rsquo;s history of insertions and deletions.&lt;/p&gt;
&lt;p&gt;In Python 2.7, dictionaries are unordered structures. The order of the dictionaries&amp;rsquo; items is &lt;strong&gt;scrambled&lt;/strong&gt;. This means that the order of the items is deterministic and repeatable. Let&amp;rsquo;s see an example:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 2.7&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;, &amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;, &amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you leave the interpreter and open a new interactive session later, you&amp;rsquo;ll get the same item order:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 2.7. New interactive session&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;, &amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;, &amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A closer look at these two outputs shows you that the resulting order is exactly the same in both cases. That&amp;rsquo;s why you can say that the ordering is deterministic.&lt;/p&gt;
&lt;p&gt;In Python 3.5, dictionaries are still unordered, but this time, &lt;strong&gt;randomized&lt;/strong&gt; data structures. This means that every time you re-run the dictionary, you&amp;rsquo;ll get a different items order. Let&amp;rsquo;s take a look:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 3.5&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;, &amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;, &amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you enter a new interactive session, then you&amp;rsquo;ll get the following:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 3.5. New interactive session&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;, &amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;, &amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This time, you can see that the order of the items is different in both outputs. That&amp;rsquo;s why you can say they are randomized data structures.&lt;/p&gt;
&lt;p&gt;In Python 3.6 and beyond, &lt;a href=&quot;https://docs.python.org/3/whatsnew/3.6.html#whatsnew36-compactdict&quot;&gt;dictionaries are &lt;strong&gt;ordered&lt;/strong&gt; data structures&lt;/a&gt;, which means that they keep their elements in the same order in which they were introduced, as you can see here:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 3.6 and beyond&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;, &amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;, &amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is a relatively new feature of Python&amp;rsquo;s dictionaries, and it&amp;rsquo;s a very useful one. But if you&amp;rsquo;re writing code that is supposed to be run in different Python versions, then you must not rely on this feature, because it can generate buggy behaviors.&lt;/p&gt;
&lt;p&gt;Another important feature of dictionaries is that they are mutable data structures, which means that you can add, delete, and update their items. It&amp;rsquo;s worth noting that this also means that they can&amp;rsquo;t be used as keys to other dictionaries, as they are not hashable objects.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Everything you&amp;rsquo;ve learned in this section is related to the core Python implementation, &lt;a href=&quot;https://www.python.org/about/&quot;&gt;CPython&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Other Python implementations, like &lt;a href=&quot;https://pypy.org/features.html&quot;&gt;PyPy&lt;/a&gt;, &lt;a href=&quot;http://ironpython.net/&quot;&gt;IronPython&lt;/a&gt; or &lt;a href=&quot;http://www.jython.org/index.html&quot;&gt;Jython&lt;/a&gt;, could exhibit different dictionary behaviors and features that are beyond the scope of this article.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;how-to-iterate-through-a-dictionary-in-python-the-basics&quot;&gt;How to Iterate Through a Dictionary in Python: The Basics&lt;/h2&gt;
&lt;p&gt;Dictionaries are an useful and widely used data structure in Python. As a Python coder, you&amp;rsquo;ll often be in situations where you&amp;rsquo;ll need to iterate through a dictionary in Python, while you perform some actions on its key-value pairs.&lt;/p&gt;
&lt;p&gt;When it comes to iterating through a dictionary in Python, the language provides you with some great tools that we&amp;rsquo;ll cover in this article.&lt;/p&gt;
&lt;h3 id=&quot;iterating-through-keys-directly&quot;&gt;Iterating Through Keys Directly&lt;/h3&gt;
&lt;p&gt;Python&amp;rsquo;s dictionaries are &lt;a href=&quot;https://docs.python.org/3/glossary.html#term-mapping&quot;&gt;mapping objects&lt;/a&gt;. This means that they inherit some &lt;strong&gt;special methods&lt;/strong&gt;, which Python uses internally to perform some operations. These methods are named using the naming convention of adding a double underscore at the beginning of and at the end of the method&amp;rsquo;s name.&lt;/p&gt;
&lt;p&gt;To visualize the methods and attributes of any Python object, you can use &lt;code&gt;dir()&lt;/code&gt;, which is a built-in function that serves that purpose. If you run &lt;code&gt;dir()&lt;/code&gt; with an empty dictionary as an argument, then you&amp;rsquo;ll be able to see all the methods and attributes that dictionaries implement:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({})&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;__class__&amp;#39;, &amp;#39;__contains__&amp;#39;, &amp;#39;__delattr__&amp;#39;, ... , &amp;#39;__iter__&amp;#39;, ...]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you take a closer look at the previous output, you&amp;rsquo;ll see &lt;code&gt;&#39;__iter__&#39;&lt;/code&gt;. This is a method that is called when an iterator is required for a container, and it should return a new &lt;a href=&quot;https://docs.python.org/3/glossary.html#term-iterator&quot;&gt;iterator object&lt;/a&gt; that can iterate through all the objects in the container.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The output of the previous code has been abbreviated (&lt;code&gt;...&lt;/code&gt;) in order to save space.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;For mappings (like dictionaries), &lt;code&gt;.__iter__()&lt;/code&gt; should iterate over the keys. This means that if you put a dictionary directly into a &lt;a href=&quot;https://realpython.com/python-for-loop/&quot;&gt;&lt;code&gt;for&lt;/code&gt; loop&lt;/a&gt;, Python will automatically call &lt;code&gt;.__iter__()&lt;/code&gt; on that dictionary, and you&amp;rsquo;ll get an iterator over its keys:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;color&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;fruit&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;pet&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python is smart enough to know that &lt;code&gt;a_dict&lt;/code&gt; is a dictionary and that it implements &lt;code&gt;.__iter__()&lt;/code&gt;. In this example, Python called &lt;code&gt;.__iter__()&lt;/code&gt; automatically, and this allowed you to iterate over the keys of &lt;code&gt;a_dict&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is the simplest way to iterate through a dictionary in Python. Just put it directly into a &lt;code&gt;for&lt;/code&gt; loop, and you&amp;rsquo;re done!&lt;/p&gt;
&lt;p&gt;If you use this approach along with a small trick, then you can process the keys and values of any dictionary. The trick consists of using the indexing operator &lt;code&gt;[]&lt;/code&gt; with the dictionary and its keys to get access to the values:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;color -&amp;gt; blue&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;fruit -&amp;gt; apple&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;pet -&amp;gt; dog&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The preceding code allowed you to get access to the keys (&lt;code&gt;key&lt;/code&gt;) and the values (&lt;code&gt;a_dict[key]&lt;/code&gt;) of &lt;code&gt;a_dict&lt;/code&gt; at the same time. This way, you can do any operation with both the keys and the values.&lt;/p&gt;
&lt;h3 id=&quot;iterating-through-items&quot;&gt;Iterating Through &lt;code&gt;.items()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;When you&amp;rsquo;re working with dictionaries, it&amp;rsquo;s likely that you&amp;rsquo;ll want to work with both the keys and the values. One of the most useful ways to iterate through a dictionary in Python is by using &lt;code&gt;.items()&lt;/code&gt;, which is a method that returns a new &lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#dict-views&quot;&gt;view&lt;/a&gt; of the dictionary&amp;rsquo;s items:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d_items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d_items&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Here d_items is a view of items&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;dict_items([(&amp;#39;color&amp;#39;, &amp;#39;blue&amp;#39;), (&amp;#39;fruit&amp;#39;, &amp;#39;apple&amp;#39;), (&amp;#39;pet&amp;#39;, &amp;#39;dog&amp;#39;)])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Dictionary views like &lt;code&gt;d_items&lt;/code&gt; provide a dynamic view on the dictionary&amp;rsquo;s entries, which means that when the dictionary changes, the views reflect these changes.&lt;/p&gt;
&lt;p&gt;Views can be iterated over to yield their respective data, so you can iterate through a dictionary in Python by using the view object returned by &lt;code&gt;.items()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;color&amp;#39;, &amp;#39;blue&amp;#39;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;fruit&amp;#39;, &amp;#39;apple&amp;#39;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;pet&amp;#39;, &amp;#39;dog&amp;#39;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The view object returned by &lt;code&gt;.items()&lt;/code&gt; yields the key-value pairs one at a time and allows you to iterate through a dictionary in Python, but in such a way that you get access to the keys and values at the same time.&lt;/p&gt;
&lt;p&gt;If you take a closer look at the individual items yielded by &lt;code&gt;.items()&lt;/code&gt;, you&amp;rsquo;ll notice that they&amp;rsquo;re really &lt;code&gt;tuple&lt;/code&gt; objects. Let&amp;rsquo;s take a look:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;color&amp;#39;, &amp;#39;blue&amp;#39;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;class &amp;#39;tuple&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;fruit&amp;#39;, &amp;#39;apple&amp;#39;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;class &amp;#39;tuple&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;pet&amp;#39;, &amp;#39;dog&amp;#39;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;class &amp;#39;tuple&amp;#39;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once you know this, you can use &lt;a href=&quot;https://docs.python.org/3/tutorial/datastructures.html#tuples-and-sequences&quot;&gt;&lt;code&gt;tuple&lt;/code&gt; unpacking&lt;/a&gt; to iterate through the keys and values of the dictionary you are working with. To achieve this, you just need to unpack the elements of every item into two different variables representing the key and the value:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;color -&amp;gt; blue&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;fruit -&amp;gt; apple&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;pet -&amp;gt; dog&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, the variables &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt; in the header of your &lt;code&gt;for&lt;/code&gt; loop do the unpacking. Every time the loop runs, &lt;code&gt;key&lt;/code&gt; will store the key, and &lt;code&gt;value&lt;/code&gt; will store the value of the item that is been processed. This way, you&amp;rsquo;ll have more control over the items of the dictionary, and you&amp;rsquo;ll be able to process the keys and values separately and in a way that is more readable and Pythonic.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Notice that &lt;code&gt;.values()&lt;/code&gt; and  &lt;code&gt;.keys()&lt;/code&gt; return view objects just like &lt;code&gt;.items()&lt;/code&gt;, as you&amp;rsquo;ll see in the next two sections.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;iterating-through-keys&quot;&gt;Iterating Through &lt;code&gt;.keys()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;If you just need to work with the keys of a dictionary, then you can use &lt;code&gt;.keys()&lt;/code&gt;, which is a method that returns a new view object containing the dictionary&amp;rsquo;s keys:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;dict_keys([&amp;#39;color&amp;#39;, &amp;#39;fruit&amp;#39;, &amp;#39;pet&amp;#39;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The object returned by &lt;code&gt;.keys()&lt;/code&gt; here provided a dynamic view on the keys of &lt;code&gt;a_dict&lt;/code&gt;. This view can be used to iterate through the keys of &lt;code&gt;a_dict&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To iterate through a dictionary in Python by using &lt;code&gt;.keys()&lt;/code&gt;, you just need to call &lt;code&gt;.keys()&lt;/code&gt; in the header of a &lt;code&gt;for&lt;/code&gt; loop:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;color&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;fruit&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;pet&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you call &lt;code&gt;.keys()&lt;/code&gt; on &lt;code&gt;a_dict&lt;/code&gt;, you get a view of  keys. Python knows that view objects are iterables, so it starts looping, and you can process the keys of &lt;code&gt;a_dict&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On the other hand, using the same trick you&amp;rsquo;ve seen before (indexing operator &lt;code&gt;[]&lt;/code&gt;), you can get access to the values of the dictionary:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;color -&amp;gt; blue&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;fruit -&amp;gt; apple&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;pet -&amp;gt; dog&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This way you&amp;rsquo;ve gotten access to the keys (&lt;code&gt;key&lt;/code&gt;) and values (&lt;code&gt;a_dict[key]&lt;/code&gt;) of &lt;code&gt;a_dict&lt;/code&gt; at the same time, and you&amp;rsquo;ll be able to perform any action on them.&lt;/p&gt;
&lt;h3 id=&quot;iterating-through-values&quot;&gt;Iterating Through &lt;code&gt;.values()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s also common to only use the values to iterate through a dictionary in Python. One way to do that is to use &lt;code&gt;.values()&lt;/code&gt;, which returns a view with the values of the dictionary:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;dict_values([&amp;#39;blue&amp;#39;, &amp;#39;apple&amp;#39;, &amp;#39;dog&amp;#39;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the previous code, &lt;code&gt;values&lt;/code&gt; holds a reference to a view object containing the values of &lt;code&gt;a_dict&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As any view object, the object returned by &lt;code&gt;.values()&lt;/code&gt; can also be iterated over. In this case, &lt;code&gt;.values()&lt;/code&gt; yields the values of &lt;code&gt;a_dict&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;blue&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;apple&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;dog&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using &lt;code&gt;.values()&lt;/code&gt;, you&amp;rsquo;ll be getting access to only the values of &lt;code&gt;a_dict&lt;/code&gt;, without dealing with the keys.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s worth noting that they also support &lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#typesseq-common&quot;&gt;membership tests (&lt;code&gt;in&lt;/code&gt;)&lt;/a&gt;, which is an important feature if you&amp;rsquo;re trying to know if a specific element is in a dictionary or not:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;onion&amp;#39;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The membership test using &lt;code&gt;in&lt;/code&gt; returns &lt;code&gt;True&lt;/code&gt; if the key (or value or item) is present in the dictionary you&amp;rsquo;re testing, and returns &lt;code&gt;False&lt;/code&gt; otherwise. The membership test allows you to not iterate through a dictionary in Python if you just want to know if certain key (or value or item) is present in a dictionary or not.&lt;/p&gt;
&lt;h2 id=&quot;modifying-values-and-keys&quot;&gt;Modifying Values and Keys&lt;/h2&gt;
&lt;p&gt;It can be pretty common to need to modify the values and keys when you&amp;rsquo;re iterating through a dictionary in Python. There are some points you&amp;rsquo;ll need to take into account to accomplish this task.&lt;/p&gt;
&lt;p&gt;The values, for example, can be modified whenever you need, but you&amp;rsquo;ll need to use the original dictionary and the key that maps the value you want to modify:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Apply a 10% discount&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;apple&amp;#39;: 0.36, &amp;#39;orange&amp;#39;: 0.32, &amp;#39;banana&amp;#39;: 0.23}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the previous code example, to modify the values of &lt;code&gt;prices&lt;/code&gt; and apply a 10% discount, you used the expression &lt;code&gt;prices[k] = round(v * 0.9, 2)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So why do you have to use the original dictionary if you have access to its key (&lt;code&gt;k&lt;/code&gt;) and its values (&lt;code&gt;v&lt;/code&gt;)? Should you be able to modify them directly? &lt;/p&gt;
&lt;p&gt;The real problem is that &lt;code&gt;k&lt;/code&gt; and &lt;code&gt;v&lt;/code&gt; changes aren&amp;rsquo;t reflected in the original dictionary. That is, if you modify any of them (&lt;code&gt;k&lt;/code&gt; or &lt;code&gt;v&lt;/code&gt;) directly inside the loop, then what really happens is that you&amp;rsquo;ll lose the reference to the relevant dictionary component without changing anything in the dictionary.&lt;/p&gt;
&lt;p&gt;On the other hand, the keys can be added or removed from a dictionary by converting the view returned by &lt;code&gt;.keys()&lt;/code&gt; into a &lt;code&gt;list&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()):&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Use a list instead of a view&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Delete a key from prices&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;apple&amp;#39;: 0.4, &amp;#39;banana&amp;#39;: 0.25}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This approach may have some performance implications, mainly related to memory consumption. For example, instead of a view object that yields elements on demand, you&amp;rsquo;ll have an entire new &lt;code&gt;list&lt;/code&gt; in your system&amp;rsquo;s memory. However, this could be a safe way to modify the keys while you iterate through a dictionary in Python.&lt;/p&gt;
&lt;p&gt;Finally, if you try to remove a key from &lt;code&gt;prices&lt;/code&gt; by using &lt;code&gt;.keys()&lt;/code&gt; directly, then Python will raise a &lt;code&gt;RuntimeError&lt;/code&gt; telling you that the dictionary&amp;rsquo;s size has changed during iteration:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 3. dict.keys() returns a view object, not a list&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;input&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;RuntimeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;dictionary changed size during iteration&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is because &lt;code&gt;.keys()&lt;/code&gt; returns a dictionary-view object, which yields keys on demand one at a time, and if you delete an item (&lt;code&gt;del prices[key]&lt;/code&gt;), then Python raises a &lt;code&gt;RuntimeError&lt;/code&gt;, because you&amp;rsquo;ve modified the dictionary during iteration.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In Python 2, &lt;code&gt;.items()&lt;/code&gt;, &lt;code&gt;.keys()&lt;/code&gt;, and &lt;code&gt;.values()&lt;/code&gt; return &lt;code&gt;list&lt;/code&gt; objects. But &lt;code&gt;.iteritems()&lt;/code&gt;, &lt;code&gt;iterkeys()&lt;/code&gt;, and &lt;code&gt;.itervalues()&lt;/code&gt; return iterators. So, if you&amp;rsquo;re using Python 2, then you can modify the dictionary&amp;rsquo;s keys by using &lt;code&gt;.keys()&lt;/code&gt; directly. &lt;/p&gt;
&lt;p&gt;On the other hand, if you&amp;rsquo;re using &lt;code&gt;iterkeys()&lt;/code&gt; in your Python 2 code and you try to modify the keys of a dictionary, then you&amp;rsquo;ll get a &lt;code&gt;RuntimeError&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;real-world-examples&quot;&gt;Real-World Examples&lt;/h2&gt;
&lt;p&gt;So far, you&amp;rsquo;ve seen the more basic ways of iterating through a dictionary in Python. Now it&amp;rsquo;s time to see how you can perform some actions with the items of a dictionary during iteration. Let&amp;rsquo;s look at some real-world examples.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Later on in this article, you&amp;rsquo;ll see another way of solving these very same problems by using other Python tools.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;turning-keys-into-values-and-vice-versa&quot;&gt;Turning Keys Into Values and Vice Versa&lt;/h3&gt;
&lt;p&gt;Suppose you have a dictionary and for some reason need to turn keys into values and vice versa. In this situation, you can use a &lt;code&gt;for&lt;/code&gt; loop to iterate through the dictionary and build the new dictionary by using the keys as values and vice versa:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;one&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;two&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;thee&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;four&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;new_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{1: &amp;#39;one&amp;#39;, 2: &amp;#39;two&amp;#39;, 3: &amp;#39;thee&amp;#39;, 4: &amp;#39;four&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The expression &lt;code&gt;new_dict[value] = key&lt;/code&gt; did all the work for you by turning the keys into values and using the values as keys. For this code to work, the data stored in the original values must be of a hashable data type.&lt;/p&gt;
&lt;h3 id=&quot;filtering-items&quot;&gt;Filtering Items&lt;/h3&gt;
&lt;p&gt;Sometimes you&amp;rsquo;ll be in situations where you have a dictionary and you want to create a new one to store only the data that satisfies a given condition. You can do this with an &lt;code&gt;if&lt;/code&gt; statement inside a &lt;code&gt;for&lt;/code&gt; loop as follows:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;one&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;two&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;thee&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;four&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Create a new empty dictionary&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# If value satisfies the condition, then store it in new_dict&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;new_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;one&amp;#39;: 1, &amp;#39;two&amp;#39;: 2}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you&amp;rsquo;ve filtered out the items with a value greater than &lt;code&gt;2&lt;/code&gt;. Now &lt;code&gt;new_dict&lt;/code&gt; only contains the items that satisfy the condition &lt;code&gt;value &amp;lt;= 2&lt;/code&gt;. This is one possible solution for this kind of problem. Later on, you&amp;rsquo;ll see a more Pythonic and readable way to get the same result.&lt;/p&gt;
&lt;h3 id=&quot;doing-some-calculations&quot;&gt;Doing Some Calculations&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s also common to need to do some calculations while you iterate through a dictionary in Python. Suppose you&amp;rsquo;ve stored the data for your company&amp;rsquo;s sales in a dictionary, and now you want to know the total income of the year. &lt;/p&gt;
&lt;p&gt;To solve this problem you could define a variable with an initial value of zero. Then, you can accumulate every value of your dictionary in that variable:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5600.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3500.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5000.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_income&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.00&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;total_income&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Accumulate the values in total_income&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_income&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;14100.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you&amp;rsquo;ve iterated through &lt;code&gt;incomes&lt;/code&gt; and sequentially accumulated its values in &lt;code&gt;total_income&lt;/code&gt; as you wanted to do. The expression &lt;code&gt;total_income += value&lt;/code&gt; does the magic, and at the end of the loop, you&amp;rsquo;ll get the total income of the year. Note that &lt;code&gt;total_income += value&lt;/code&gt; is equivalent to &lt;code&gt;total_income = total_income + value&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;using-comprehensions&quot;&gt;Using Comprehensions&lt;/h2&gt;
&lt;p&gt;A &lt;strong&gt;dictionary comprehension&lt;/strong&gt; is a compact way to process all or part of the elements in a collection and return a dictionary as a results. In contrast to &lt;a href=&quot;https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions&quot;&gt;list comprehensions&lt;/a&gt;, they need two expressions separated with a colon followed by &lt;code&gt;for&lt;/code&gt; and &lt;code&gt;if&lt;/code&gt; (optional) clauses. When a dictionary comprehension is run, the resulting key-value pairs are inserted into a new dictionary in the same order in which they were produced.&lt;/p&gt;
&lt;p&gt;Suppose, for example, that you have two lists of data, and you need to create a new dictionary from them. In this case, you can use Python&amp;rsquo;s &lt;code&gt;zip(*iterables)&lt;/code&gt; to loop over the elements of both lists in pairs:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;categories&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;categories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;objects&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;color&amp;#39;: &amp;#39;blue&amp;#39;, &amp;#39;fruit&amp;#39;: &amp;#39;apple&amp;#39;, &amp;#39;pet&amp;#39;: &amp;#39;dog&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, &lt;code&gt;zip()&lt;/code&gt; receives two iterables (&lt;code&gt;categories&lt;/code&gt; and &lt;code&gt;objects&lt;/code&gt;) as arguments and makes an iterator that aggregates elements from each iterable. The &lt;code&gt;tuple&lt;/code&gt; objects generated by &lt;code&gt;zip()&lt;/code&gt; are then unpacked into &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;value&lt;/code&gt;, which are finally used to create the new dictionary.&lt;/p&gt;
&lt;p&gt;Dictionary comprehensions open up a wide spectrum of new possibilities and provide you with a great tool to iterate through a dictionary in Python.&lt;/p&gt;
&lt;h3 id=&quot;turning-keys-into-values-and-vice-versa-revisited&quot;&gt;Turning Keys Into Values and Vice Versa: Revisited&lt;/h3&gt;
&lt;p&gt;If you take another look at the problem of turning keys into values and vice versa, you&amp;rsquo;ll see that you could write a more Pythonic and efficient solution by using a dictionary comprehension:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;one&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;two&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;thee&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;four&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{1: &amp;#39;one&amp;#39;, 2: &amp;#39;two&amp;#39;, 3: &amp;#39;thee&amp;#39;, 4: &amp;#39;four&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this dictionary comprehension, you&amp;rsquo;ve created a totally new dictionary where the keys have taken the place of the values and vice versa. This new approach gave you the ability to write more readable, succinct, efficient, and Pythonic code.&lt;/p&gt;
&lt;p&gt;The condition for this code to work is the same one you saw before: the values must be hashable objects. Otherwise, you won&amp;rsquo;t be able to use them as keys for &lt;code&gt;a_dict&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;filtering-items-revisited&quot;&gt;Filtering Items: Revisited&lt;/h3&gt;
&lt;p&gt;To filter the items in a dictionary with a comprehension, you just need to add an &lt;code&gt;if&lt;/code&gt; clause that defines the condition you want to meet. In the previous example where you filtered a dictionary, that condition was &lt;code&gt;if v &amp;lt;= 2&lt;/code&gt;. With this &lt;code&gt;if&lt;/code&gt; clause added to the end of the dictionary comprehension, you&amp;rsquo;ll filter out the items whose values are greater than &lt;code&gt;2&lt;/code&gt;. Let&amp;rsquo;s take a look:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;one&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;two&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;thee&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;four&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_dict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;one&amp;#39;: 1, &amp;#39;two&amp;#39;: 2}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now &lt;code&gt;new_dict&lt;/code&gt; contains only the items that satisfy your condition. Compared to the previous solutions, this one is more Pythonic and efficient.&lt;/p&gt;
&lt;h3 id=&quot;doing-some-calculations-revisited&quot;&gt;Doing Some Calculations: Revisited&lt;/h3&gt;
&lt;p&gt;Remember the example with the company&amp;rsquo;s sales? If you use a list comprehension to iterate through the dictionary&amp;rsquo;s values, then you&amp;rsquo;ll get code that is more compact, fast, and Pythonic:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5600.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3500.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5000.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_income&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_income&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;14100.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The list comprehension created a &lt;code&gt;list&lt;/code&gt; object containing the values of &lt;code&gt;incomes&lt;/code&gt;, and then you summed up all of them by using &lt;code&gt;sum()&lt;/code&gt; and stored the result in &lt;code&gt;total_income&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re working with a really large dictionary, and memory usage is a problem for you, then you can use a &lt;a href=&quot;https://docs.python.org/3/glossary.html#term-generator-expression&quot;&gt;generator expression&lt;/a&gt; instead of a list comprehension. A &lt;strong&gt;generator expression&lt;/strong&gt; is an expression that returns an iterator. It looks like a list comprehension, but instead of brackets you need to use parentheses to define it:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_income&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_income&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;14100.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you change the square brackets for a pair of parentheses (the parentheses of &lt;code&gt;sum()&lt;/code&gt; here), you&amp;rsquo;ll be turning the list comprehension into a generator expression, and your code will be memory efficient, because generator expressions yield elements on demand. Instead of creating and storing the whole list in memory, you&amp;rsquo;ll only have to store one element at a time.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you are totally new to generator expressions, you can take a look at &lt;a href=&quot;https://realpython.com/introduction-to-python-generators/&quot;&gt;Introduction to  Python Generators&lt;/a&gt; to get a better understanding of the topic.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Finally, there is a simpler way to solve this problem by just using &lt;code&gt;incomes.values()&lt;/code&gt; directly as an argument to &lt;code&gt;sum()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_income&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_income&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;14100.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;sum()&lt;/code&gt; receives an iterable as an argument and returns the total sum of its elements. Here, &lt;code&gt;incomes.values()&lt;/code&gt; plays the role of the iterable passed to &lt;code&gt;sum()&lt;/code&gt;. The result is the total income you were looking for.&lt;/p&gt;
&lt;h3 id=&quot;removing-specific-items&quot;&gt;Removing Specific Items&lt;/h3&gt;
&lt;p&gt;Now, suppose you have a dictionary and need to create a new one with selected keys removed. Remember how key-view objects are like &lt;a href=&quot;https://realpython.com/python-sets/&quot;&gt;sets&lt;/a&gt;? Well, these similarities go beyond just being collections of hashable and unique objects. Key-view objects also support common &lt;code&gt;set&lt;/code&gt; operations. Let&amp;rsquo;s see how you can take advantage of this to remove specific items in a dictionary:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5600.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3500.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5000.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;non_citric&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;non_citric&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;apple&amp;#39;: 5600.0, &amp;#39;banana&amp;#39;: 5000.0}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code works because key-view objects support &lt;code&gt;set&lt;/code&gt; operations like unions, intersections, and differences. When you wrote &lt;code&gt;incomes.keys() - {&#39;orange&#39;}&lt;/code&gt; inside the dictionary comprehension, you were really doing a &lt;code&gt;set&lt;/code&gt; difference operation. If you need to perform any &lt;code&gt;set&lt;/code&gt; operations with the keys of a dictionary, then you can just use the key-view object directly without first converting it into a &lt;code&gt;set&lt;/code&gt;. This is a little-known feature of key-view objects that can be useful in some situations.&lt;/p&gt;
&lt;h3 id=&quot;sorting-a-dictionary&quot;&gt;Sorting a Dictionary&lt;/h3&gt;
&lt;p&gt;It&amp;rsquo;s often necessary to sort the elements of a collection. Since Python 3.6, dictionaries are ordered data structures, so if you use Python 3.6 (and beyond), you&amp;rsquo;ll be able to sort the items of any dictionary by using &lt;code&gt;sorted()&lt;/code&gt; and with the help of a dictionary comprehension:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 3.6, and beyond&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5600.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3500.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5000.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_income&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_income&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;apple&amp;#39;: 5600.0, &amp;#39;banana&amp;#39;: 5000.0, &amp;#39;orange&amp;#39;: 3500.0}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code allows you to create a new dictionary with its keys in sorted order. This is possible because &lt;code&gt;sorted(incomes)&lt;/code&gt; returns a list of sorted keys that you can use to generate the new dictionary &lt;code&gt;sorted_dict&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;iterating-in-sorted-order&quot;&gt;Iterating in Sorted Order&lt;/h2&gt;
&lt;p&gt;Sometimes you may need to iterate through a dictionary in Python but want to do it in sorted order. This can be achieved by using &lt;code&gt;sorted()&lt;/code&gt;. When you call &lt;code&gt;sorted(iterable)&lt;/code&gt;, you get a &lt;code&gt;list&lt;/code&gt; with the elements of &lt;code&gt;iterable&lt;/code&gt; in sorted order.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s see how you can use &lt;code&gt;sorted()&lt;/code&gt; to iterate through a dictionary in Python when you need to do it in sorted order.&lt;/p&gt;
&lt;h3 id=&quot;sorted-by-keys&quot;&gt;Sorted by Keys&lt;/h3&gt;
&lt;p&gt;If you need to iterate through a dictionary in Python and want it to be sorted by keys, then you can use your dictionary as an argument to &lt;code&gt;sorted()&lt;/code&gt;. This will return a &lt;code&gt;list&lt;/code&gt; containing the keys in sorted order, and you&amp;rsquo;ll be able to iterate through them:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5600.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3500.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5000.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;apple -&amp;gt; 5600.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;banana -&amp;gt; 5000.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;orange -&amp;gt; 3500.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you sorted the dictionary (alphabetically) by keys using &lt;code&gt;sorted(incomes)&lt;/code&gt; in the header of the &lt;code&gt;for&lt;/code&gt; loop. Notice that you can also use &lt;code&gt;sorted(incomes.keys())&lt;/code&gt; to get the same result. In both cases, you&amp;rsquo;ll get a &lt;code&gt;list&lt;/code&gt; containing the keys of your dictionary in sorted order.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The sorting order will depend on the data type you are using for keys or values and the internal rules that Python uses to sort those data types.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;sorted-by-values&quot;&gt;Sorted by Values&lt;/h3&gt;
&lt;p&gt;You could also need to iterate through a dictionary in Python with its items sorted by values. You can use &lt;code&gt;sorted()&lt;/code&gt; too, but with a second argument called &lt;code&gt;key&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;key&lt;/code&gt; keyword argument specifies a function of one argument that is used to extract a comparison key from each element you&amp;rsquo;re processing.&lt;/p&gt;
&lt;p&gt;To sort the items of a dictionary by values, you can write a function that returns the value of each item and use this function as the &lt;code&gt;key&lt;/code&gt; argument to &lt;code&gt;sorted()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5600.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3500.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5000.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;by_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;by_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;orange&amp;#39;, &amp;#39;-&amp;gt;&amp;#39;, 3500.0)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;banana&amp;#39;, &amp;#39;-&amp;gt;&amp;#39;, 5000.0)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;apple&amp;#39;, &amp;#39;-&amp;gt;&amp;#39;, 5600.0)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you defined &lt;code&gt;by_value()&lt;/code&gt; and used it to sort the items of &lt;code&gt;incomes&lt;/code&gt; by value. Then you iterated through the dictionary in sorted order by using &lt;code&gt;sorted()&lt;/code&gt;. The key function (&lt;code&gt;by_value()&lt;/code&gt;) tells &lt;code&gt;sorted()&lt;/code&gt; to sort &lt;code&gt;incomes.items()&lt;/code&gt; by the second element of each item, that is, by the value (&lt;code&gt;item[1]&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;You may also just want to iterate through the values of a dictionary in sorted order, without worrying about the keys. In that case, you can use &lt;code&gt;.values()&lt;/code&gt; as follows:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3500.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;5000.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;5600.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;sorted(incomes.values())&lt;/code&gt; returned the values of the dictionary in sorted order as you desired. The keys won&amp;rsquo;t be accessible if you use &lt;code&gt;incomes.values()&lt;/code&gt;, but sometimes you don&amp;rsquo;t really need the keys, just the values, and this is a fast way to get access to them.&lt;/p&gt;
&lt;h3 id=&quot;reversed&quot;&gt;Reversed&lt;/h3&gt;
&lt;p&gt;If you need to sort your dictionaries in reverse order, you can add &lt;code&gt;reverse=True&lt;/code&gt; as an argument to &lt;code&gt;sorted()&lt;/code&gt;. The keyword argument &lt;code&gt;reverse&lt;/code&gt; should take a boolean value. If it&amp;rsquo;s set to &lt;code&gt;True&lt;/code&gt;, then the elements are sorted in reverse order:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5600.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3500.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;5000.00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;orange -&amp;gt; 3500.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;banana -&amp;gt; 5000.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;apple -&amp;gt; 5600.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you iterated over the keys of &lt;code&gt;incomes&lt;/code&gt; in reverse order by using &lt;code&gt;sorted(incomes, reverse=True)&lt;/code&gt; in the header of the &lt;code&gt;for&lt;/code&gt; loop.&lt;/p&gt;
&lt;p&gt;Finally, it&amp;rsquo;s important to note that &lt;code&gt;sorted()&lt;/code&gt; doesn&amp;rsquo;t really modify the order of the underlying dictionary. What really happen is that &lt;code&gt;sorted()&lt;/code&gt; creates an independent list with its element in sorted order, so &lt;code&gt;incomes&lt;/code&gt; remains the same:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incomes&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;apple&amp;#39;: 5600.0, &amp;#39;orange&amp;#39;: 3500.0, &amp;#39;banana&amp;#39;: 5000.0}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code shows you that &lt;code&gt;incomes&lt;/code&gt; didn&amp;rsquo;t change. &lt;code&gt;sorted()&lt;/code&gt; didn&amp;rsquo;t modify &lt;code&gt;incomes&lt;/code&gt;. It just created a new sorted list from the keys of &lt;code&gt;incomes&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;iterating-destructively-with-popitem&quot;&gt;Iterating Destructively With &lt;code&gt;.popitem&lt;/code&gt;()&lt;/h2&gt;
&lt;p&gt;Sometimes you need to iterate through a dictionary in Python and delete its items sequentially.  To accomplish this task, you can use &lt;code&gt;.popitem()&lt;/code&gt;, which will remove and return an arbitrary key-value pair from a dictionary. On the other hand, when you call &lt;code&gt;.popitem()&lt;/code&gt; on an empty dictionary, it raises a &lt;code&gt;KeyError&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you really need to destructively iterate through a dictionary in Python, then &lt;code&gt;.popitem()&lt;/code&gt; can be useful. Here&amp;rsquo;s an example:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# File: dict_popitem.py&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;color&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;blue&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;fruit&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;dog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Dictionary length: {len(a_dict)}&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;popitem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Do something with item here...&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{item}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; removed&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;KeyError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;The dictionary has no item now...&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you used a &lt;code&gt;while&lt;/code&gt; loop instead of a &lt;code&gt;for&lt;/code&gt; loop. The reason for this is that it&amp;rsquo;s never safe to iterate through a dictionary in Python if you pretend to modify it this way, that is, if you&amp;rsquo;re deleting or adding items to it.&lt;/p&gt;
&lt;p&gt;Inside the &lt;code&gt;while&lt;/code&gt; loop, you defined a &lt;code&gt;try...except&lt;/code&gt; block to catch the &lt;code&gt;KeyError&lt;/code&gt; raised by &lt;code&gt;.popitems()&lt;/code&gt; when &lt;code&gt;a_dict&lt;/code&gt; turns empty. In the &lt;code&gt;try...except&lt;/code&gt; block, you process the dictionary, removing an item in each iteration. The variable &lt;code&gt;item&lt;/code&gt; keeps a reference to the successive items and allows you to do some actions with them.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In the previous code example, you used Python&amp;rsquo;s f-strings for string formatting. If you want to dive deeper into f-strings, then you can take a look at &lt;a href=&quot;https://realpython.com/python-f-strings/&quot;&gt;Python 3&amp;rsquo;s f-Strings: An Improved String Formatting Syntax (Guide)&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you &lt;a href=&quot;https://realpython.com/run-python-scripts&quot;&gt;run this script from your command-line&lt;/a&gt;,  then you&amp;rsquo;ll get the following results:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python3 dict_popitem.py
&lt;span class=&quot;go&quot;&gt;Dictionary length: 3&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;pet&amp;#39;, &amp;#39;dog&amp;#39;) removed&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Dictionary length: 2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;fruit&amp;#39;, &amp;#39;apple&amp;#39;) removed&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Dictionary length: 1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;color&amp;#39;, &amp;#39;blue&amp;#39;) removed&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Dictionary length: 0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The dictionary has no item now...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here &lt;code&gt;.popitem()&lt;/code&gt; sequentially removed the items of &lt;code&gt;a_dict&lt;/code&gt;. The loop broke when the dictionary became empty, and &lt;code&gt;.popitem()&lt;/code&gt; raised a &lt;code&gt;KeyError&lt;/code&gt; exception.&lt;/p&gt;
&lt;h2 id=&quot;using-some-of-pythons-built-in-functions&quot;&gt;Using Some of Python&amp;rsquo;s Built-In Functions&lt;/h2&gt;
&lt;p&gt;Python provides some built-in functions that could be useful when you&amp;rsquo;re working with collections, like dictionaries. These functions are a sort of iteration tool that provides you with another way of iterating through a dictionary in Python. Let&amp;rsquo;s see some of them.&lt;/p&gt;
&lt;h3 id=&quot;map&quot;&gt;&lt;code&gt;map()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Python&amp;rsquo;s &lt;code&gt;map()&lt;/code&gt; is defined as &lt;code&gt;map(function, iterable, ...)&lt;/code&gt; and returns an iterator that applies &lt;code&gt;function&lt;/code&gt; to every item of &lt;code&gt;iterable&lt;/code&gt;, yielding the results on demand. So, &lt;code&gt;map()&lt;/code&gt; could be viewed as an iteration tool that you can use to iterate through a dictionary in Python.&lt;/p&gt;
&lt;p&gt;Suppose you have a dictionary containing the prices of a bunch of products, and you need to apply a discount to them. In this case, you can define a function that manages the discount and then uses it as the first argument to &lt;code&gt;map()&lt;/code&gt;. The second argument can be &lt;code&gt;prices.items()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;discount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.95&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;discount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_prices&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;apple&amp;#39;: 0.38, &amp;#39;orange&amp;#39;: 0.33, &amp;#39;banana&amp;#39;: 0.24}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, &lt;code&gt;map()&lt;/code&gt; iterated through the items of the dictionary (&lt;code&gt;prices.items()&lt;/code&gt;) to apply a 5% discount to each fruit by using &lt;code&gt;discount()&lt;/code&gt;. In this case, you need to use &lt;code&gt;dict()&lt;/code&gt; to generate the &lt;code&gt;new_prices&lt;/code&gt; dictionary from the iterator returned by &lt;code&gt;map()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note that &lt;code&gt;discount()&lt;/code&gt; returns a &lt;code&gt;tuple&lt;/code&gt; of the form &lt;code&gt;(key, value)&lt;/code&gt;, where &lt;code&gt;current_price[0]&lt;/code&gt; represents the key and &lt;code&gt;round(current_price[1] * 0.95, 2)&lt;/code&gt; represents the new value.&lt;/p&gt;
&lt;h3 id=&quot;filter&quot;&gt;&lt;code&gt;filter()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;filter()&lt;/code&gt; is another built-in function that you can use to iterate through a dictionary in Python and filter out some of its items. This function is defined as &lt;code&gt;filter(function, iterable)&lt;/code&gt; and returns an iterator from those elements of &lt;code&gt;iterable&lt;/code&gt; for which &lt;code&gt;function&lt;/code&gt; returns &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Suppose you want to know the products with a price lower than &lt;code&gt;0.40&lt;/code&gt;. You need to define a function to determine if the price satisfies that condition and pass it as first argument to &lt;code&gt;filter()&lt;/code&gt;. The second argument can be &lt;code&gt;prices.keys()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;has_low_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.4&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;low_price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;has_low_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keys&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;low_price&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;orange&amp;#39;, &amp;#39;banana&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you iterated through the keys of &lt;code&gt;prices&lt;/code&gt; with &lt;code&gt;filter()&lt;/code&gt;. Then &lt;code&gt;filter()&lt;/code&gt; applies &lt;code&gt;has_low_price()&lt;/code&gt; to every key of &lt;code&gt;prices&lt;/code&gt;. Finally, you need to use &lt;code&gt;list()&lt;/code&gt; to generate the list of products with a low price, because &lt;code&gt;filter()&lt;/code&gt; returns an iterator, and you really need a &lt;code&gt;list&lt;/code&gt; object.&lt;/p&gt;
&lt;h2 id=&quot;using-collectionschainmap&quot;&gt;Using &lt;code&gt;collections.ChainMap&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.python.org/3/library/collections.html&quot;&gt;&lt;code&gt;collections&lt;/code&gt;&lt;/a&gt; is a useful module from the Python Standard Library that provides specialized container data types. One of these data types is &lt;code&gt;ChainMap&lt;/code&gt;, which is a dictionary-like class for creating a single view of multiple mappings (like dictionaries). With &lt;code&gt;ChainMap&lt;/code&gt;, you can group multiple dictionaries together to create a single, updateable view.&lt;/p&gt;
&lt;p&gt;Now, suppose you have two (or more) dictionaries, and you need to iterate through them together as one. To achieve this, you can create a &lt;code&gt;ChainMap&lt;/code&gt; object and initialize it with your dictionaries:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;collections&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ChainMap&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fruit_prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vegetable_prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;pepper&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;onion&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.55&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chained_dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ChainMap&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fruit_prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vegetable_prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chained_dict&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# A ChainMap object&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;ChainMap({&amp;#39;apple&amp;#39;: 0.4, &amp;#39;orange&amp;#39;: 0.35}, {&amp;#39;pepper&amp;#39;: 0.2, &amp;#39;onion&amp;#39;: 0.55})&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chained_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chained_dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;pepper -&amp;gt; 0.2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;orange -&amp;gt; 0.35&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;onion -&amp;gt; 0.55&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;apple -&amp;gt; 0.4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After importing &lt;code&gt;ChainMap&lt;/code&gt; from &lt;code&gt;collections&lt;/code&gt;, you need to create a &lt;code&gt;ChainMap&lt;/code&gt; object with the dictionaries you want to chain, and then you can freely iterate through the resulting object as you would do with a regular dictionary.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ChainMap&lt;/code&gt; objects also implement &lt;code&gt;.keys()&lt;/code&gt;, &lt;code&gt;values()&lt;/code&gt;, and &lt;code&gt;.items()&lt;/code&gt; as a standard dictionary does, so you can use these methods to iterate through the dictionary-like object generated by &lt;code&gt;ChainMap&lt;/code&gt;, just like you would do with a regular dictionary:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chained_dict&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;apple -&amp;gt; 0.4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;pepper -&amp;gt; 0.2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;orange -&amp;gt; 0.35&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;onion -&amp;gt; 0.55&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case, you&amp;rsquo;ve called &lt;code&gt;.items()&lt;/code&gt; on a &lt;code&gt;ChainMap&lt;/code&gt; object. The &lt;code&gt;ChainMap&lt;/code&gt; object behaved as if it were a regular dictionary, and &lt;code&gt;.items()&lt;/code&gt; returned a dictionary view object that can be iterated over as usual.&lt;/p&gt;
&lt;h2 id=&quot;using-itertools&quot;&gt;Using &lt;code&gt;itertools&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Python&amp;rsquo;s &lt;code&gt;itertools&lt;/code&gt; is a module that provides some useful tools to perform iteration tasks. Let&amp;rsquo;s see how you can use some of them to iterate through a dictionary in Python.&lt;/p&gt;
&lt;h3 id=&quot;cyclic-iteration-with-cycle&quot;&gt;Cyclic Iteration With &lt;code&gt;cycle()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Suppose you want to iterate through a dictionary in Python, but you need to iterate through it repeatedly in a single loop. To get this task done, you can use &lt;code&gt;itertools.cycle(iterable)&lt;/code&gt;, which makes an iterator returning elements from &lt;code&gt;iterable&lt;/code&gt; and saving a copy of each. When &lt;code&gt;iterable&lt;/code&gt; is exhausted, &lt;code&gt;cycle()&lt;/code&gt; returns elements from the saved copy. This is performed in cyclic fashion, so it&amp;rsquo;s up to you to stop the cycle.&lt;/p&gt;
&lt;p&gt;In the following example, you&amp;rsquo;ll be iterating through the items of a dictionary three consecutive times:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;itertools&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cycle&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Define how many times you need to iterate through prices&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total_items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;times&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cycle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total_items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;total_items&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;apple&amp;#39;, 0.4)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;orange&amp;#39;, 0.35)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;banana&amp;#39;, 0.25)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;apple&amp;#39;, 0.4)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;orange&amp;#39;, 0.35)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;banana&amp;#39;, 0.25)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;apple&amp;#39;, 0.4)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;orange&amp;#39;, 0.35)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;banana&amp;#39;, 0.25)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The preceding code allowed you to iterate through &lt;code&gt;prices&lt;/code&gt; a given number of times (&lt;code&gt;3&lt;/code&gt; in this case). This cycle could be as long as you need, but you are responsible for stopping it. The &lt;code&gt;if&lt;/code&gt; condition breaks the cycle when &lt;code&gt;total_items&lt;/code&gt; counts down to zero.&lt;/p&gt;
&lt;h3 id=&quot;chained-iteration-with-chain&quot;&gt;Chained Iteration With &lt;code&gt;chain()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;itertools&lt;/code&gt; also provides &lt;code&gt;chain(*iterables)&lt;/code&gt;, which gets some &lt;code&gt;iterables&lt;/code&gt; as arguments and makes an iterator that yields elements from the first iterable until it&amp;rsquo;s exhausted, then iterates over the next iterable and so on, until all of them are exhausted.&lt;/p&gt;
&lt;p&gt;This allows you to iterate through multiple dictionaries in a chain, like to what you did with &lt;code&gt;collections.ChainMap&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;itertools&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chain&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fruit_prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vegetable_prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;pepper&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;onion&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.55&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;tomato&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;item&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fruit_prices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;vegetable_prices&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;apple&amp;#39;, 0.4)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;orange&amp;#39;, 0.35)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;banana&amp;#39;, 0.25)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;pepper&amp;#39;, 0.2)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;onion&amp;#39;, 0.55)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;tomato&amp;#39;, 0.42)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the above code, &lt;code&gt;chain()&lt;/code&gt; returned an iterable that combined the items from &lt;code&gt;fruit_prices&lt;/code&gt; and &lt;code&gt;vegetable_prices&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s also possible to use &lt;code&gt;.keys()&lt;/code&gt; or &lt;code&gt;.values()&lt;/code&gt;, depending on your needs, with the condition of being homogeneous: if you use &lt;code&gt;.keys()&lt;/code&gt; for an argument to &lt;code&gt;chain()&lt;/code&gt;, then you need to use &lt;code&gt;.keys()&lt;/code&gt; for the rest of them.&lt;/p&gt;
&lt;h2 id=&quot;using-the-dictionary-unpacking-operator&quot;&gt;Using the Dictionary Unpacking Operator (&lt;code&gt;**&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;Python 3.5 brings a new and interesting feature. &lt;a href=&quot;https://www.python.org/dev/peps/pep-0448&quot;&gt;PEP 448 - Additional Unpacking Generalizations&lt;/a&gt; can make your life easier when it comes to iterating through multiple dictionaries in Python. Let&amp;rsquo;s see how this works with a short example.&lt;/p&gt;
&lt;p&gt;Suppose you have two (or more) dictionaries, and you need to iterate through them together, without using &lt;code&gt;collections.ChainMap&lt;/code&gt; or &lt;code&gt;itertools.chain()&lt;/code&gt;, as you&amp;rsquo;ve seen in the previous sections. In this case, you can use the dictionary unpacking operator (&lt;code&gt;**&lt;/code&gt;) to merge the two dictionaries into a new one and then iterate through it:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fruit_prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vegetable_prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;pepper&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;onion&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.55&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# How to use the unpacking operator **&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vegetable_prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fruit_prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;pepper&amp;#39;: 0.2, &amp;#39;onion&amp;#39;: 0.55, &amp;#39;apple&amp;#39;: 0.4, &amp;#39;orange&amp;#39;: 0.35}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# You can use this feature to iterate through multiple dictionaries&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vegetable_prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fruit_prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;k&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;-&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;pepper -&amp;gt; 0.2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;onion -&amp;gt; 0.55&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;apple -&amp;gt; 0.4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;orange -&amp;gt; 0.35&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The dictionary unpacking operator (&lt;code&gt;**&lt;/code&gt;) is really an awesome feature in Python. It allows you to merge multiple dictionaries into a new one, as you did in the example with &lt;code&gt;vegetable_prices&lt;/code&gt; and &lt;code&gt;fruit_prices&lt;/code&gt;. Once you&amp;rsquo;ve merged the dictionaries with the unpacking operator, you can iterate through the new dictionary as usual.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s important to note that if the dictionaries you&amp;rsquo;re trying to merge have repeated or common keys, then the values of the right-most dictionary will prevail:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vegetable_prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;pepper&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;onion&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.55&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fruit_prices&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;apple&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;orange&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pepper&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;vegetable_prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fruit_prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;pepper&amp;#39;: 0.25, &amp;#39;onion&amp;#39;: 0.55, &amp;#39;apple&amp;#39;: 0.4, &amp;#39;orange&amp;#39;: 0.35}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;pepper&lt;/code&gt; key is present in both dictionaries. After you merge them, the &lt;code&gt;fruit_prices&lt;/code&gt; value for &lt;code&gt;pepper&lt;/code&gt; (&lt;code&gt;0.25&lt;/code&gt;) prevailed, because &lt;code&gt;fruit_prices&lt;/code&gt; is the right-most dictionary.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You now know the basics of how to iterate through a dictionary in Python, as well as some more advanced techniques and strategies!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&amp;rsquo;ve learned:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What dictionaries are, as well as some of their main features and implementation details&lt;/li&gt;
&lt;li&gt;What the basic ways to iterate through a dictionary in Python are&lt;/li&gt;
&lt;li&gt;What kind of tasks you can accomplish by iterating through a dictionary in Python&lt;/li&gt;
&lt;li&gt;How to use some more elaborated techniques and strategies to iterate through a dictionary in Python&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You have the tools and knowledge you&amp;rsquo;ll need to get the most out of dictionaries in Python. This will help you be more efficient and effective in your use of dictionary iteration in the future.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Python Logging: A Stroll Through the Source Code</title>
      <id>https://realpython.com/python-logging-source-code/</id>
      <link href="https://realpython.com/python-logging-source-code/"/>
      <updated>2019-05-22T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn about how the Python logging package is designed from an OOP perspective. You&#39;ll walk line by line down the package&#39;s core module and become better equipped to know what your code is doing.</summary>
      <content type="html">
        &lt;p&gt;The Python &lt;code&gt;logging&lt;/code&gt; package is a a lightweight but extensible package for keeping better track of what your own code does.  Using it gives you much  more flexibility than just littering your code with superfluous &lt;code&gt;print()&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;However, Python&amp;rsquo;s &lt;code&gt;logging&lt;/code&gt; package can be complicated in certain spots.  Handlers, loggers, levels, namespaces, filters: it&amp;rsquo;s not easy to keep track of all of these pieces and how they interact.&lt;/p&gt;
&lt;p&gt;One way to tie up the loose ends in your understanding of &lt;code&gt;logging&lt;/code&gt; is to peek under the hood to its CPython source code.  The Python code behind &lt;code&gt;logging&lt;/code&gt; is concise and modular, and reading through it can help you get that &lt;em&gt;aha&lt;/em&gt; moment.&lt;/p&gt;
&lt;p&gt;This article is meant to complement the logging &lt;a href=&quot;https://docs.python.org/3/howto/logging.html&quot;&gt;HOWTO&lt;/a&gt; document as well as &lt;a href=&quot;https://realpython.com/python-logging/&quot;&gt;Logging in Python&lt;/a&gt;, which is a walkthrough on how to use the package.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this article, you&amp;rsquo;ll be familiar with the following&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;logging&lt;/code&gt; levels and how they work&lt;/li&gt;
&lt;li&gt;Thread-safety versus process-safety in &lt;code&gt;logging&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The design of &lt;code&gt;logging&lt;/code&gt; from an OOP perspective&lt;/li&gt;
&lt;li&gt;Logging in libraries vs applications&lt;/li&gt;
&lt;li&gt;Best practices and design patterns for using &lt;code&gt;logging&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the most part, we&amp;rsquo;ll go line-by-line down the core module in Python&amp;rsquo;s &lt;code&gt;logging&lt;/code&gt; package in order to build a picture of how it&amp;rsquo;s laid out.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-mastery-course&quot; data-focus=&quot;false&quot;&gt;5 Thoughts On Python Mastery&lt;/a&gt;, a free course for Python developers that shows you the roadmap and the mindset you&#39;ll need to take your Python skills to the next level.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;how-to-follow-along&quot;&gt;How to Follow Along&lt;/h2&gt;
&lt;p&gt;Because the &lt;code&gt;logging&lt;/code&gt; source code is central to this article, you can assume that any code block or link is based on a specific commit in the Python 3.7 CPython repository, namely &lt;a href=&quot;https://github.com/python/cpython/tree/d730719b094cb006711b1cd546927b863c173b31&quot;&gt;commit &lt;code&gt;d730719&lt;/code&gt;&lt;/a&gt;.  You can find the &lt;code&gt;logging&lt;/code&gt; package itself in the &lt;a href=&quot;https://github.com/python/cpython/tree/d730719b094cb006711b1cd546927b863c173b31/Lib/logging&quot;&gt;&lt;code&gt;Lib/&lt;/code&gt;&lt;/a&gt; directory within the CPython source.&lt;/p&gt;
&lt;p&gt;Within the &lt;code&gt;logging&lt;/code&gt; package, most of the heavy lifting occurs within &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py&quot;&gt;&lt;code&gt;logging/__init__.py&lt;/code&gt;&lt;/a&gt;, which is the file you&amp;rsquo;ll spend the most time on here:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;cpython/
│
├── Lib/
│   ├── logging/
│   │   ├── __init__.py
│   │   ├── config.py
│   │   └── handlers.py
│   ├── ...
├── Modules/
├── Include/
...
... [truncated]
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With that, let&amp;rsquo;s jump in.&lt;/p&gt;
&lt;h2 id=&quot;preliminaries&quot;&gt;Preliminaries&lt;/h2&gt;
&lt;p&gt;Before we get to the heavyweight classes, the top hundred lines or so of &lt;code&gt;__init__.py&lt;/code&gt; introduce a few subtle but important concepts.&lt;/p&gt;
&lt;h3 id=&quot;preliminary-1-a-level-is-just-an-int&quot;&gt;Preliminary #1: A Level Is Just an &lt;code&gt;int&lt;/code&gt;!&lt;/h3&gt;
&lt;p&gt;Objects like &lt;code&gt;logging.INFO&lt;/code&gt; or &lt;code&gt;logging.DEBUG&lt;/code&gt; can seem a bit opaque.  What are these variables internally, and how are they defined?&lt;/p&gt;
&lt;p&gt;In fact, the uppercase constants from Python&amp;rsquo;s &lt;code&gt;logging&lt;/code&gt; &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L89&quot;&gt;are just integers&lt;/a&gt;, forming an enum-like collection of numerical levels:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CRITICAL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;FATAL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CRITICAL&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ERROR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;WARNING&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;WARN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WARNING&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;INFO&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;DEBUG&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;NOTSET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Why not just use the strings &lt;code&gt;&quot;INFO&quot;&lt;/code&gt; or &lt;code&gt;&quot;DEBUG&quot;&lt;/code&gt;?  Levels are &lt;code&gt;int&lt;/code&gt; constants to allow for the simple, unambiguous comparison of one level with another.  They are given names as well to lend them semantic meaning.  Saying that a message has a severity of 50 may not be immediately clear, but saying that it has a level of &lt;code&gt;CRITICAL&lt;/code&gt; lets you know that you&amp;rsquo;ve got a flashing red light somewhere in your program.&lt;/p&gt;
&lt;p&gt;Now, technically, you can pass just the &lt;code&gt;str&lt;/code&gt; form of a level in some places, such as &lt;code&gt;logger.setLevel(&quot;DEBUG&quot;)&lt;/code&gt;.  Internally, this will call &lt;code&gt;_checkLevel()&lt;/code&gt;, which ultimately does a &lt;code&gt;dict&lt;/code&gt; lookup for the corresponding &lt;code&gt;int&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_nameToLevel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;CRITICAL&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CRITICAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;FATAL&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FATAL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;ERROR&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERROR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;WARN&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WARNING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;WARNING&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WARNING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;INFO&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;INFO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;DEBUG&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s1&quot;&gt;&amp;#39;NOTSET&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOTSET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_checkLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_nameToLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Unknown level: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%r&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_nameToLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Level not an integer or a valid string: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%r&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Which should you prefer?  I&amp;rsquo;m not too opinionated on this, but it&amp;rsquo;s notable that the &lt;code&gt;logging&lt;/code&gt; docs consistently use the form &lt;code&gt;logging.DEBUG&lt;/code&gt; rather than &lt;code&gt;&quot;DEBUG&quot;&lt;/code&gt; or &lt;code&gt;10&lt;/code&gt;.  Also, passing the &lt;code&gt;str&lt;/code&gt; form isn&amp;rsquo;t an option in Python 2, and some &lt;code&gt;logging&lt;/code&gt; methods such as &lt;code&gt;logger.isEnabledFor()&lt;/code&gt; will accept only an &lt;code&gt;int&lt;/code&gt;, not its &lt;code&gt;str&lt;/code&gt; cousin.&lt;/p&gt;
&lt;h3 id=&quot;preliminary-2-logging-is-thread-safe-but-not-process-safe&quot;&gt;Preliminary #2: Logging Is Thread-Safe, but Not Process-Safe&lt;/h3&gt;
&lt;p&gt;A few lines down, you&amp;rsquo;ll find the following short &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L210&quot;&gt;code block&lt;/a&gt;, which is sneakily critical to the whole package:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;threading&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;_lock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;threading&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RLock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_acquireLock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
     &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_lock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;acquire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_releaseLock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_lock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;_lock&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;_lock&lt;/code&gt; object is a &lt;a href=&quot;https://realpython.com/intro-to-python-threading/#basic-synchronization-using-lock&quot;&gt;reentrant lock&lt;/a&gt; that sits in the global namespace of the &lt;code&gt;logging/__init__.py&lt;/code&gt; module.  It makes pretty much every object and operation in the entire &lt;code&gt;logging&lt;/code&gt; package thread-safe, enabling threads to do read and write operations without the threat of a race condition.  You can see in the module source code that &lt;code&gt;_acquireLock()&lt;/code&gt; and &lt;code&gt;_releaseLock()&lt;/code&gt; are ubiquitous to the module and its classes.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s something not accounted for here, though: what about process safety?  The short answer is that the &lt;code&gt;logging&lt;/code&gt; module is &lt;em&gt;not&lt;/em&gt; process safe.  This isn&amp;rsquo;t inherently a fault of &lt;code&gt;logging&lt;/code&gt;&amp;mdash;generally, two processes can&amp;rsquo;t write to same file without a lot of proactive effort on behalf of the programmer first.&lt;/p&gt;
&lt;p&gt;This means that you&amp;rsquo;ll want to be careful before using classes such as a &lt;code&gt;logging.FileHandler&lt;/code&gt; with multiprocessing involved.  If two processes want to read from and write to the same underlying file concurrently, then you can run into a nasty bug halfway through a long-running routine.&lt;/p&gt;
&lt;p&gt;If you want to get around this limitation, there&amp;rsquo;s a thorough &lt;a href=&quot;https://docs.python.org/3/howto/logging-cookbook.html#logging-to-a-single-file-from-multiple-processes&quot;&gt;recipe&lt;/a&gt; in the official Logging Cookbook.  Because this entails a decent amount of setup, one alternative is to have each process log to a separate file based on its process ID, which you can grab with &lt;a href=&quot;https://docs.python.org/3/library/os.html#os.getpid&quot;&gt;&lt;code&gt;os.getpid()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;package-architecture-loggings-mro&quot;&gt;Package Architecture: Logging&amp;rsquo;s MRO&lt;/h2&gt;
&lt;p&gt;Now that we&amp;rsquo;ve covered some preliminary setup code, let&amp;rsquo;s take a high-level look at how &lt;code&gt;logging&lt;/code&gt; is laid out.  The &lt;code&gt;logging&lt;/code&gt; package uses a healthy dose of &lt;a href=&quot;https://realpython.com/python3-object-oriented-programming/&quot;&gt;OOP&lt;/a&gt; and inheritance.  Here&amp;rsquo;s a partial look at the method resolution order (MRO) for some of the most important classes in the package:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;object
│
├── LogRecord
├── Filterer
│   ├── Logger
│   │   └── RootLogger
│   └── Handler
│       ├── StreamHandler
│       └── NullHandler
├── Filter
└── Manager
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The tree diagram above doesn&amp;rsquo;t cover all of the classes in the module, just those that are most worth highlighting.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: You can use the dunder attribute &lt;code&gt;logging.StreamHandler.__mro__&lt;/code&gt; to see the chain of inheritance.  A definitive &lt;a href=&quot;https://www.python.org/download/releases/2.3/mro/&quot;&gt;guide to the MRO&lt;/a&gt; can be found in the Python 2 docs, though it is applicable to Python 3 as well.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This litany of classes is typically one source of confusion because there&amp;rsquo;s a lot going on, and it&amp;rsquo;s all jargon-heavy.  &lt;code&gt;Filter&lt;/code&gt; versus &lt;code&gt;Filterer&lt;/code&gt;?  &lt;code&gt;Logger&lt;/code&gt; versus &lt;code&gt;Handler&lt;/code&gt;?  It can be challenging to keep track of everything, much less visualize how it fits together.  A picture is worth a thousand words, so here&amp;rsquo;s a diagram of a scenario where one logger with two handlers attached to it writes a log message with level &lt;code&gt;logging.INFO&lt;/code&gt;:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/flow-new.0a9432c705ad.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-77&quot; src=&quot;https://files.realpython.com/media/flow-new.0a9432c705ad.png&quot; width=&quot;1752&quot; height=&quot;567&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/flow-new.0a9432c705ad.png&amp;amp;w=438&amp;amp;sig=c6cc86b43b9696b4413f7e9be33f017ab96e2e31 438w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/flow-new.0a9432c705ad.png&amp;amp;w=876&amp;amp;sig=c0229451eff029f62c8f1ba62cd8bc25f91a2dd3 876w, https://files.realpython.com/media/flow-new.0a9432c705ad.png 1752w&quot; sizes=&quot;75vw&quot; alt=&quot;Flow of the logging package&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Flow of logging objects (Image: Real Python)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;In Python code, everything above would look like this:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pylog&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FileHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/tmp/records.log&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;INFO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ERROR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;testing &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.. &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.. &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%d&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;..&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There&amp;rsquo;s a more detailed map of this flow in the &lt;a href=&quot;https://docs.python.org/3.5/howto/logging.html#logging-flow&quot;&gt;Logging HOWTO&lt;/a&gt;.  What&amp;rsquo;s shown above is a simplified scenario.&lt;/p&gt;
&lt;p&gt;Your code defines just one &lt;code&gt;Logger&lt;/code&gt; instance, &lt;code&gt;logger&lt;/code&gt;, along with two &lt;code&gt;Handler&lt;/code&gt; instances, &lt;code&gt;h1&lt;/code&gt; and &lt;code&gt;h2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When you call &lt;code&gt;logger.info(&quot;testing %d.. %d.. %d..&quot;, 1, 2, 3)&lt;/code&gt;, the &lt;code&gt;logger&lt;/code&gt; object serves as a filter because it also has a &lt;code&gt;level&lt;/code&gt; associated with it.  Only if the message level is severe enough will the logger do anything with the message.  Because the logger has level &lt;code&gt;DEBUG&lt;/code&gt;, and the message carries a higher &lt;code&gt;INFO&lt;/code&gt; level, it gets the go-ahead to move on.&lt;/p&gt;
&lt;p&gt;Internally, &lt;code&gt;logger&lt;/code&gt; calls &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L1481&quot;&gt;&lt;code&gt;logger.makeRecord()&lt;/code&gt;&lt;/a&gt; to put the message string &lt;code&gt;&quot;testing %d.. %d.. %d..&quot;&lt;/code&gt; and its arguments &lt;code&gt;(1, 2, 3)&lt;/code&gt; into a bona fide class instance of a &lt;code&gt;LogRecord&lt;/code&gt;, which is just a container for the message and its metadata.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;logger&lt;/code&gt; object looks around for its handlers (instances of &lt;code&gt;Handler&lt;/code&gt;), which may be tied directly to &lt;code&gt;logger&lt;/code&gt; itself or to its parents (a concept that we&amp;rsquo;ll touch on later).  In this example, it finds two handlers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;One with level &lt;code&gt;INFO&lt;/code&gt; that dumps log data to a file at &lt;code&gt;/tmp/records.log&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;One that writes to &lt;code&gt;sys.stderr&lt;/code&gt; but only if the incoming message is at level &lt;code&gt;ERROR&lt;/code&gt; or higher&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At this point, there&amp;rsquo;s another round of tests that kicks in.  Because the &lt;code&gt;LogRecord&lt;/code&gt; and its message only carry level &lt;code&gt;INFO&lt;/code&gt;, the record gets written to Handler 1 (green arrow), but not to Handler 2&amp;rsquo;s &lt;code&gt;stderr&lt;/code&gt; stream (red arrow).  For Handlers, writing the &lt;code&gt;LogRecord&lt;/code&gt; to their stream is called &lt;strong&gt;emitting&lt;/strong&gt; it, which is captured in their &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L882&quot;&gt;&lt;code&gt;.emit()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Next, let&amp;rsquo;s further dissect everything from above.&lt;/p&gt;
&lt;h3 id=&quot;the-logrecord-class&quot;&gt;The &lt;code&gt;LogRecord&lt;/code&gt; Class&lt;/h3&gt;
&lt;p&gt;What is a &lt;code&gt;LogRecord&lt;/code&gt;?  When you log a message, an instance of the &lt;code&gt;LogRecord&lt;/code&gt; class is the object you send to be logged.  It&amp;rsquo;s created for you by a &lt;code&gt;Logger&lt;/code&gt; instance and encapsulates all the pertinent info about that event.  Internally, it&amp;rsquo;s little more than a wrapper around a &lt;code&gt;dict&lt;/code&gt; that contains attributes for the record.  A &lt;code&gt;Logger&lt;/code&gt; instance sends a &lt;code&gt;LogRecord&lt;/code&gt; instance to zero or more &lt;code&gt;Handler&lt;/code&gt; instances.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;LogRecord&lt;/code&gt; contains some metadata, such as the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A name&lt;/li&gt;
&lt;li&gt;The creation time as a Unix timestamp&lt;/li&gt;
&lt;li&gt;The message itself&lt;/li&gt;
&lt;li&gt;Information on what function made the logging call&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;rsquo;s a peek into the metadata that it carries with it, which you can introspect by stepping through a &lt;code&gt;logging.error()&lt;/code&gt; call with the &lt;a href=&quot;https://realpython.com/python-debugging-pdb/&quot;&gt;&lt;code&gt;pdb&lt;/code&gt; module&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pdb&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;bad vibes&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;f(1)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After stepping through some higher-level functions, you end up &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L1517&quot;&gt;at line 1517&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;(Pdb) l&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1514                     exc_info = (type(exc_info), exc_info, exc_info.__traceback__)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1515                 elif not isinstance(exc_info, tuple):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1516                     exc_info = sys.exc_info()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1517             record = self.makeRecord(self.name, level, fn, lno, msg, args,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1518                                      exc_info, func, extra, sinfo)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1519 -&amp;gt;          self.handle(record)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1520&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1521         def handle(self, record):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1522             &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1523             Call the handlers for the specified record.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1524&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) from pprint import pprint&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) pprint(vars(record))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;args&amp;#39;: (),&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;created&amp;#39;: 1550671851.660067,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;exc_info&amp;#39;: None,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;exc_text&amp;#39;: None,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;filename&amp;#39;: &amp;#39;&amp;lt;stdin&amp;gt;&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;funcName&amp;#39;: &amp;#39;f&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;levelname&amp;#39;: &amp;#39;ERROR&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;levelno&amp;#39;: 40,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;lineno&amp;#39;: 2,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;module&amp;#39;: &amp;#39;&amp;lt;stdin&amp;gt;&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;msecs&amp;#39;: 660.067081451416,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;msg&amp;#39;: &amp;#39;bad vibes&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;name&amp;#39;: &amp;#39;root&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;pathname&amp;#39;: &amp;#39;&amp;lt;stdin&amp;gt;&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;process&amp;#39;: 2360,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;processName&amp;#39;: &amp;#39;MainProcess&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;relativeCreated&amp;#39;: 295145.5490589142,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;stack_info&amp;#39;: None,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;thread&amp;#39;: 4372293056,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;threadName&amp;#39;: &amp;#39;MainThread&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A &lt;code&gt;LogRecord&lt;/code&gt;, internally, contains a trove of metadata that&amp;rsquo;s used in one way or another.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll rarely need to deal with a &lt;code&gt;LogRecord&lt;/code&gt; directly, since the &lt;code&gt;Logger&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt; do this for you.  It&amp;rsquo;s still worthwhile to know what information is wrapped up in a &lt;code&gt;LogRecord&lt;/code&gt;, because this is where all that useful info, like the timestamp, come from when you see record log messages.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Below the &lt;code&gt;LogRecord&lt;/code&gt; class, you&amp;rsquo;ll also find the &lt;code&gt;setLogRecordFactory()&lt;/code&gt;, &lt;code&gt;getLogRecordFactory()&lt;/code&gt;, and &lt;code&gt;makeLogRecord()&lt;/code&gt; &lt;a href=&quot;https://realpython.com/factory-method-python/&quot;&gt;factory functions&lt;/a&gt;.  You won&amp;rsquo;t need these unless you want to use a custom class instead of &lt;code&gt;LogRecord&lt;/code&gt; to encapsulate log messages and their metadata.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;the-logger-and-handler-classes&quot;&gt;The &lt;code&gt;Logger&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt; Classes&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;Logger&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt; classes are both central to how &lt;code&gt;logging&lt;/code&gt; works, and they interact with each other frequently.  A &lt;code&gt;Logger&lt;/code&gt;, a &lt;code&gt;Handler&lt;/code&gt;, and a &lt;code&gt;LogRecord&lt;/code&gt; each have a &lt;code&gt;.level&lt;/code&gt; associated with them.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;Logger&lt;/code&gt; takes the &lt;code&gt;LogRecord&lt;/code&gt; and passes it off to the &lt;code&gt;Handler&lt;/code&gt;, but only if the effective level of the &lt;code&gt;LogRecord&lt;/code&gt; is equal to or higher than that of the &lt;code&gt;Logger&lt;/code&gt;.  The same goes for the &lt;code&gt;LogRecord&lt;/code&gt; versus &lt;code&gt;Handler&lt;/code&gt; test.  This is called &lt;strong&gt;level-based filtering&lt;/strong&gt;, which &lt;code&gt;Logger&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt; implement in slightly different ways.&lt;/p&gt;
&lt;p&gt;In other words, there is an (at least) two-step test applied before the message that you log gets to go anywhere.  In order to be fully passed from a logger to handler and then logged to the end stream (which could be &lt;code&gt;sys.stdout&lt;/code&gt;, a file, or an email via SMTP), a &lt;code&gt;LogRecord&lt;/code&gt; must have a level at least as high as &lt;em&gt;both&lt;/em&gt; the logger and handler.  &lt;/p&gt;
&lt;p&gt;PEP 282 describes how this works:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Each &lt;code&gt;Logger&lt;/code&gt; object keeps track of a log level (or threshold) that it is interested in, and discards log requests below that level. (&lt;a href=&quot;https://www.python.org/dev/peps/pep-0282/&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So where does this level-based filtering actually occur for both &lt;code&gt;Logger&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt;?&lt;/p&gt;
&lt;p&gt;For the &lt;code&gt;Logger&lt;/code&gt; class, it&amp;rsquo;s a reasonable first assumption that the logger would compare its &lt;code&gt;.level&lt;/code&gt; attribute to the level of the &lt;code&gt;LogRecord&lt;/code&gt;, and be done there.  However, it&amp;rsquo;s slightly more involved than that.&lt;/p&gt;
&lt;p&gt;Level-based filtering for loggers occurs in &lt;code&gt;.isEnabledFor()&lt;/code&gt;, which in turn calls &lt;code&gt;.getEffectiveLevel()&lt;/code&gt;.  &lt;em&gt;Always&lt;/em&gt; use &lt;code&gt;logger.getEffectiveLevel()&lt;/code&gt; rather than just consulting &lt;code&gt;logger.level&lt;/code&gt;.  The reason has to do with the organization of &lt;code&gt;Logger&lt;/code&gt; objects in a hierarchical namespace.  (You&amp;rsquo;ll see more on this later.)&lt;/p&gt;
&lt;p&gt;By default, a &lt;code&gt;Logger&lt;/code&gt; instance has a level of &lt;code&gt;0&lt;/code&gt; (&lt;code&gt;NOTSET&lt;/code&gt;).  However, loggers also have &lt;strong&gt;parent loggers&lt;/strong&gt;, one of which is the root logger, which functions as the parent of all other loggers.  A &lt;code&gt;Logger&lt;/code&gt; will walk upwards in its hierarchy and get its effective level vis-à-vis its parent (which ultimately may be &lt;code&gt;root&lt;/code&gt; if no other parents are found).&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L1605&quot;&gt;where this happens&lt;/a&gt; in the &lt;code&gt;Logger&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Filterer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getEffectiveLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOTSET&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isEnabledFor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;KeyError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_acquireLock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;is_enabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;is_enabled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_cache&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getEffectiveLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;_releaseLock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_enabled&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Correspondingly, here&amp;rsquo;s an example that calls the source code you see above:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;app&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# No!&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getEffectiveLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;RootLogger root (WARNING)&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s the takeaway: don&amp;rsquo;t rely on &lt;code&gt;.level&lt;/code&gt;.  If you haven&amp;rsquo;t explicitly set a level on your &lt;code&gt;logger&lt;/code&gt; object, and you&amp;rsquo;re depending on &lt;code&gt;.level&lt;/code&gt; for some reason, then your logging setup will likely behave differently than you expected it to.&lt;/p&gt;
&lt;p&gt;What about &lt;code&gt;Handler&lt;/code&gt;?  For handlers, the level-to-level comparison is simpler, though it actually happens &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L1575&quot;&gt;in &lt;code&gt;.callHandlers()&lt;/code&gt;&lt;/a&gt; from the &lt;code&gt;Logger&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Filterer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;callHandlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;found&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdlr&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;found&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;found&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;levelno&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdlr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;hdlr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For a given &lt;code&gt;LogRecord&lt;/code&gt; instance (named &lt;code&gt;record&lt;/code&gt; in the source code above), a logger checks with each of its registered handlers and does a quick check on the &lt;code&gt;.level&lt;/code&gt; attribute of that &lt;code&gt;Handler&lt;/code&gt; instance.  If the &lt;code&gt;.levelno&lt;/code&gt; of the &lt;code&gt;LogRecord&lt;/code&gt; is greater than or equal to that of the handler, only then does the record get passed on.  A &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L894&quot;&gt;docstring&lt;/a&gt; in &lt;code&gt;logging&lt;/code&gt; refers to this as &amp;ldquo;conditionally emit[ting] the specified logging record.&amp;rdquo;&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card1090ef&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse1090ef&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse1090ef&quot;&gt;Handlers and the Places They Go&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse1090ef&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse1090ef&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse1090ef&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card1090ef&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;The most important attribute for a &lt;code&gt;Handler&lt;/code&gt; subclass instance is its &lt;code&gt;.stream&lt;/code&gt; attribute.  This is the final destination where logs get written to and can be pretty much any file-like object.  Here&amp;rsquo;s an example with &lt;a href=&quot;https://docs.python.org/3/library/io.html#io.StringIO&quot;&gt;&lt;code&gt;io.StringIO&lt;/code&gt;&lt;/a&gt;, which is an in-memory stream (buffer) for text I/O.  &lt;/p&gt;
&lt;p&gt;First, set up a &lt;code&gt;Logger&lt;/code&gt; instance with a level of &lt;code&gt;DEBUG&lt;/code&gt;.  You&amp;rsquo;ll see that, by default, it has no direct handlers:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;io&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;abc&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, you can subclass &lt;code&gt;logging.StreamHandler&lt;/code&gt; to make the &lt;code&gt;.flush()&lt;/code&gt; call a no-op.  We would want to flush &lt;code&gt;sys.stderr&lt;/code&gt; or &lt;code&gt;sys.stdout&lt;/code&gt;, but not the in-memory buffer in this case:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;IOHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# No-op&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, declare the buffer object itself and tie it in as the &lt;code&gt;.stream&lt;/code&gt; for your custom handler with a level of &lt;code&gt;INFO&lt;/code&gt;, and then tie that handler into the logger:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;io&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StringIO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IOHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;INFO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;extraneous info&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;you&amp;#39;ve been warned&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critical&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;SOS&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getvalue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;you&amp;#39;ve been warned&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;SOS&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This last chunk is another illustration of level-based filtering.  &lt;/p&gt;
&lt;p&gt;Three messages with levels &lt;code&gt;DEBUG&lt;/code&gt;, &lt;code&gt;WARNING&lt;/code&gt;, and &lt;code&gt;CRITICAL&lt;/code&gt; are passed through the chain.  At first, it may look as if they don&amp;rsquo;t go anywhere, but two of them do.  All three of them make it out of the gates from &lt;code&gt;logger&lt;/code&gt; (which has level &lt;code&gt;DEBUG&lt;/code&gt;).  &lt;/p&gt;
&lt;p&gt;However, only two of them get emitted by the handler because it has a higher level of &lt;code&gt;INFO&lt;/code&gt;, which exceeds &lt;code&gt;DEBUG&lt;/code&gt;.  Finally, you get the entire contents of the buffer as a &lt;code&gt;str&lt;/code&gt; and close the buffer to explicitly free up system resources.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h3 id=&quot;the-filter-and-filterer-classes&quot;&gt;The &lt;code&gt;Filter&lt;/code&gt; and &lt;code&gt;Filterer&lt;/code&gt; Classes&lt;/h3&gt;
&lt;p&gt;Above, we asked the question, &amp;ldquo;Where does level-based filtering happen?&amp;rdquo;  In answering this question, it&amp;rsquo;s easy to get distracted by the &lt;code&gt;Filter&lt;/code&gt; and &lt;code&gt;Filterer&lt;/code&gt; classes.  Paradoxically, level-based filtering for &lt;code&gt;Logger&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt; instances occurs without the help of either of the &lt;code&gt;Filter&lt;/code&gt; or &lt;code&gt;Filterer&lt;/code&gt; classes.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Filter&lt;/code&gt; and &lt;code&gt;Filterer&lt;/code&gt; are designed to let you add additional function-based filters on top of the level-based filtering that is done by default.  I like to think of it as &lt;em&gt;à la carte&lt;/em&gt; filtering.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Filterer&lt;/code&gt; is the base class for &lt;code&gt;Logger&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt; because both of these classes are eligible for receiving additional custom filters that you specify.  You add instances of &lt;code&gt;Filter&lt;/code&gt; to them with &lt;code&gt;logger.addFilter()&lt;/code&gt; or &lt;code&gt;handler.addFilter()&lt;/code&gt;, which is what &lt;code&gt;self.filters&lt;/code&gt; refers to in the following method:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Filterer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filters&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;hasattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;filter&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;                &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Given a &lt;code&gt;record&lt;/code&gt; (which is a &lt;code&gt;LogRecord&lt;/code&gt; instance), &lt;code&gt;.filter()&lt;/code&gt; returns &lt;code&gt;True&lt;/code&gt; or &lt;code&gt;False&lt;/code&gt; depending on whether that record gets the okay from this class&amp;rsquo;s filters.&lt;/p&gt;
&lt;p&gt;Here is .&lt;code&gt;handle()&lt;/code&gt; in turn, for the &lt;code&gt;Logger&lt;/code&gt; and &lt;code&gt;Handler&lt;/code&gt; classes:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Filterer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disabled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callHandlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Filterer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;acquire&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;finally&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;                &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;release&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rv&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Neither &lt;code&gt;Logger&lt;/code&gt; nor &lt;code&gt;Handler&lt;/code&gt; come with any additional filters by default, but here&amp;rsquo;s a quick example of how you could add one:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;rp&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;INFO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filters&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Initially empty&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ShortMsgFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Only allow records that contain long messages (&amp;gt; 25 chars).&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ShortMsgFilter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filters&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;lt;__main__.ShortMsgFilter object at 0x10c28b208&amp;gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Reeeeaaaaallllllly long message&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Length: 31&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Reeeeaaaaallllllly long message&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Done&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Length: &amp;lt;25, no output&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Above, you define a class &lt;code&gt;ShortMsgFilter&lt;/code&gt; and override its &lt;code&gt;.filter()&lt;/code&gt;.  In &lt;code&gt;.addHandler()&lt;/code&gt;, you could also just pass a callable, such as a function or lambda or a class that defines &lt;code&gt;.__call__()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-manager-class&quot;&gt;The &lt;code&gt;Manager&lt;/code&gt; Class&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s one more behind-the-scenes actor of &lt;code&gt;logging&lt;/code&gt; that is worth touching on: the &lt;code&gt;Manager&lt;/code&gt; class.  What matters most is not the &lt;code&gt;Manager&lt;/code&gt; class but a single instance of it that acts as a container for the growing hierarchy of loggers that are defined across packages.  You&amp;rsquo;ll see in the next section how just a single instance of this class is central to gluing the module together and allowing its parts to talk to each other.&lt;/p&gt;
&lt;h2 id=&quot;the-all-important-root-logger&quot;&gt;The All-Important Root Logger&lt;/h2&gt;
&lt;p&gt;When it comes to &lt;code&gt;Logger&lt;/code&gt; instances, one stands out. It&amp;rsquo;s called the root logger:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RootLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;fm&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;root&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RootLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WARNING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;manager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Manager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last three lines of this code block are one of the ingenious tricks employed by the &lt;code&gt;logging&lt;/code&gt; package.  Here are a few points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The root logger is just a no-frills Python object with the identifier &lt;code&gt;root&lt;/code&gt;.  It has a level of &lt;code&gt;logging.WARNING&lt;/code&gt; and a &lt;code&gt;.name&lt;/code&gt; of &lt;code&gt;&quot;root&quot;&lt;/code&gt;.  As far as the class &lt;code&gt;RootLogger&lt;/code&gt; is concerned, this unique name is all that&amp;rsquo;s special about it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;root&lt;/code&gt; object in turn becomes a &lt;strong&gt;class attribute&lt;/strong&gt; for the &lt;code&gt;Logger&lt;/code&gt; class.  This means that all instances of &lt;code&gt;Logger&lt;/code&gt;, and the &lt;code&gt;Logger&lt;/code&gt; class itself, all have a &lt;code&gt;.root&lt;/code&gt; attribute that is the root logger.  This is another example of a singleton-like pattern being enforced in the &lt;code&gt;logging&lt;/code&gt; package.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A &lt;code&gt;Manager&lt;/code&gt; instance is set as the &lt;code&gt;.manager&lt;/code&gt; class attribute for &lt;code&gt;Logger&lt;/code&gt;.  This eventually comes into play in &lt;code&gt;logging.getLogger(&quot;name&quot;)&lt;/code&gt;.  The &lt;code&gt;.manager&lt;/code&gt; does all the facilitation of searching for existing loggers with the name &lt;code&gt;&quot;name&quot;&lt;/code&gt; and creating them if they don&amp;rsquo;t exist.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;the-logger-hierarchy&quot;&gt;The Logger Hierarchy&lt;/h3&gt;
&lt;p&gt;Everything is a child of &lt;code&gt;root&lt;/code&gt; in the logger namespace, and I mean everything.  That includes loggers that you specify yourself as well as those from third-party libraries that you import.&lt;/p&gt;
&lt;p&gt;Remember earlier how the &lt;code&gt;.getEffectiveLevel()&lt;/code&gt; for our &lt;code&gt;logger&lt;/code&gt; instances was 30 (&lt;code&gt;WARNING&lt;/code&gt;) even though we had not explicitly set it?  That&amp;rsquo;s because the root logger sits at the top of the hierarchy, and its level is a fallback if any nested loggers have a null level of &lt;code&gt;NOTSET&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Or getLogger(&amp;quot;&amp;quot;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;RootLogger root (WARNING)&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Self-referential&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getEffectiveLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The same logic applies to the search for a logger&amp;rsquo;s handlers.  The search is effectively a reverse-order search up the tree of a logger&amp;rsquo;s parents.&lt;/p&gt;
&lt;h3 id=&quot;a-multi-handler-design&quot;&gt;A Multi-Handler Design&lt;/h3&gt;
&lt;p&gt;The logger hierarchy may seem neat in theory, but how beneficial is it in practice?  &lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a break from exploring the &lt;code&gt;logging&lt;/code&gt; code and foray into writing our own mini-application&amp;mdash;one that takes advantage of the logger hierarchy in a way that reduces boilerplate code and keeps things scalable if the project&amp;rsquo;s codebase grows.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the project structure:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;project/
│
└── project/
    ├── __init__.py
    ├── utils.py
    └── base.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Don&amp;rsquo;t worry about the application&amp;rsquo;s main functions in &lt;code&gt;utils.py&lt;/code&gt; and &lt;code&gt;base.py&lt;/code&gt;.  What we&amp;rsquo;re paying more attention to here is the interaction in &lt;code&gt;logging&lt;/code&gt; objects between the modules in &lt;code&gt;project/&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In this case, say that you want to design a multipronged logging setup:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Each module gets a &lt;code&gt;logger&lt;/code&gt; with multiple handlers.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Some of the handlers are shared between different &lt;code&gt;logger&lt;/code&gt; instances in different modules.  These handlers only care about level-based filtering, not the module where the log record emanated from.  There is a handler for &lt;code&gt;DEBUG&lt;/code&gt; messages, one for &lt;code&gt;INFO&lt;/code&gt;, one for &lt;code&gt;WARNING&lt;/code&gt;, and so on.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Each &lt;code&gt;logger&lt;/code&gt; is also tied to one more additional handler that only receives &lt;code&gt;LogRecord&lt;/code&gt; instances from that lone &lt;code&gt;logger&lt;/code&gt;.  You can call this a module-based file handler.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Visually, what we&amp;rsquo;re shooting for would look something like this:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/multipronged.b3d2192d5cbc.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-77&quot; src=&quot;https://files.realpython.com/media/multipronged.b3d2192d5cbc.png&quot; width=&quot;1803&quot; height=&quot;951&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/multipronged.b3d2192d5cbc.png&amp;amp;w=450&amp;amp;sig=ed2e9f9d0a7d3572febdf8921e8ed10aaa8ea35c 450w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/multipronged.b3d2192d5cbc.png&amp;amp;w=901&amp;amp;sig=e90933fafe50b390b4f30824ebc23c9ce10ac9f2 901w, https://files.realpython.com/media/multipronged.b3d2192d5cbc.png 1803w&quot; sizes=&quot;75vw&quot; alt=&quot;Multipronged logging setup&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;A multipronged logging design (Image: Real Python)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The two turquoise objects are instances of &lt;code&gt;Logger&lt;/code&gt;, established with &lt;code&gt;logging.getLogger(__name__)&lt;/code&gt; for each module in a package.  Everything else is a &lt;code&gt;Handler&lt;/code&gt; instance.&lt;/p&gt;
&lt;p&gt;The thinking behind this design is that it&amp;rsquo;s neatly compartmentalized.  You can conveniently look at messages coming from a single logger, or look at messages of a certain level and above coming from any logger or module.&lt;/p&gt;
&lt;p&gt;The properties of the logger hierarchy make it suitable for setting up this multipronged logger-handler layout.  What does that mean?  Here&amp;rsquo;s a concise explanation from the Django documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Why is the hierarchy important? Well, because loggers can be set to propagate their logging calls to their parents. In this way, you can define a single set of handlers at the root of a logger tree, and capture all logging calls in the subtree of loggers. A logging handler defined in the &lt;code&gt;project&lt;/code&gt; namespace will catch all logging messages issued on the &lt;code&gt;project.interesting&lt;/code&gt; and &lt;code&gt;project.interesting.stuff&lt;/code&gt; loggers. (&lt;a href=&quot;https://docs.djangoproject.com/en/2.1/topics/logging/&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The term &lt;strong&gt;propagate&lt;/strong&gt; refers to how a logger keeps walking up its chain of parents looking for handlers.  The &lt;code&gt;.propagate&lt;/code&gt; attribute is &lt;code&gt;True&lt;/code&gt; for a &lt;code&gt;Logger&lt;/code&gt; instance by default:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propagate&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;.callHandlers()&lt;/code&gt;, if &lt;code&gt;propagate&lt;/code&gt; is &lt;code&gt;True&lt;/code&gt;, each successive parent gets reassigned to the local variable &lt;code&gt;c&lt;/code&gt; until the hierarchy is exhausted:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Filterer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;callHandlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;found&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdlr&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;found&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;found&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;levelno&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdlr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;hdlr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propagate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;                &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s what this means: because the &lt;code&gt;__name__&lt;/code&gt; dunder variable within a package&amp;rsquo;s &lt;code&gt;__init__.py&lt;/code&gt; module is just the name of the package, a logger there becomes a parent to any loggers present in other modules in the same package.&lt;/p&gt;
&lt;p&gt;Here are the resulting &lt;code&gt;.name&lt;/code&gt; attributes from assigning to &lt;code&gt;logger&lt;/code&gt; with &lt;code&gt;logging.getLogger(__name__)&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Module&lt;/th&gt;
&lt;th&gt;&lt;code&gt;.name&lt;/code&gt; Attribute&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;project/__init__.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&#39;project&#39;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;project/utils.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&#39;project.utils&#39;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;project/base.py&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&#39;project.base&#39;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Because the &lt;code&gt;&#39;project.utils&#39;&lt;/code&gt; and &lt;code&gt;&#39;project.base&#39;&lt;/code&gt; loggers are children of &lt;code&gt;&#39;project&#39;&lt;/code&gt;, they will latch onto not only their own direct handlers but whatever handlers are attached to &lt;code&gt;&#39;project&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s build out the modules.  First comes &lt;code&gt;__init__.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# __init__.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;levels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;DEBUG&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;INFO&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;WARNING&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;ERROR&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CRITICAL&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;levels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FileHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/tmp/level-{level.lower()}.log&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add_module_handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DEBUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FileHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/tmp/module-{logger.name.replace(&amp;#39;.&amp;#39;, &amp;#39;-&amp;#39;)}.log&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This module is imported when the &lt;code&gt;project&lt;/code&gt; package is imported.  You add a handler for each level in &lt;code&gt;DEBUG&lt;/code&gt; through &lt;code&gt;CRITICAL&lt;/code&gt;, then attach it to a single logger at the top of the hierarchy.  &lt;/p&gt;
&lt;p&gt;You also define a utility function that adds one more &lt;code&gt;FileHandler&lt;/code&gt; to a logger, where the &lt;code&gt;filename&lt;/code&gt; of the handler corresponds to the module name where the logger is defined.  (This assumes the logger is defined with &lt;code&gt;__name__&lt;/code&gt;.)&lt;/p&gt;
&lt;p&gt;You can then add some minimal boilerplate logger setup in &lt;code&gt;base.py&lt;/code&gt; and &lt;code&gt;utils.py&lt;/code&gt;.  Notice that you only need to add one additional handler with &lt;code&gt;add_module_handler()&lt;/code&gt; from &lt;code&gt;__init__.py&lt;/code&gt;.  You don&amp;rsquo;t need to worry about the level-oriented handlers because they are already added to their parent logger named &lt;code&gt;&#39;project&#39;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# base.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;project&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add_module_handler&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;add_module_handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;debug called from base.func1()&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critical&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;critical called from base.func1()&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s &lt;code&gt;utils.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# utils.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;project&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;add_module_handler&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;add_module_handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;debug called from utils.func2()&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critical&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;critical called from utils.func2()&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Let&amp;rsquo;s see how all of this works together from a fresh Python session:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pprint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pprint&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;project&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;project&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;utils&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;project&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;Logger project (DEBUG)&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;lt;Logger project.base (DEBUG)&amp;gt;, &amp;lt;Logger project.utils (DEBUG)&amp;gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handlers&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;lt;FileHandler /tmp/module-project-base.log (DEBUG)&amp;gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;lt;FileHandler /tmp/level-debug.log (DEBUG)&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;lt;FileHandler /tmp/level-info.log (INFO)&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;lt;FileHandler /tmp/level-warning.log (WARNING)&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;lt;FileHandler /tmp/level-error.log (ERROR)&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;lt;FileHandler /tmp/level-critical.log (CRITICAL)&amp;gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;utils&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;func2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll see in the resulting log files that our filtration system works as intended.  Module-oriented handlers direct one logger to a specific file, while level-oriented handlers direct multiple loggers to a different file:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; cat /tmp/level-debug.log 
&lt;span class=&quot;go&quot;&gt;debug called from base.func1()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;critical called from base.func1()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;debug called from utils.func2()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;critical called from utils.func2()&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; cat /tmp/level-critical.log 
&lt;span class=&quot;go&quot;&gt;critical called from base.func1()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;critical called from utils.func2()&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; cat /tmp/module-project-base.log
&lt;span class=&quot;go&quot;&gt;debug called from base.func1()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;critical called from base.func1()&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; cat /tmp/module-project-utils.log 
&lt;span class=&quot;go&quot;&gt;debug called from utils.func2()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;critical called from utils.func2()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A drawback worth mentioning is that this design introduces a lot of redundancy.  One &lt;code&gt;LogRecord&lt;/code&gt; instance may go to no less than six files.  That&amp;rsquo;s also a non-negligible amount of file I/O that may add up in a performance-critical application.&lt;/p&gt;
&lt;p&gt;Now that you&amp;rsquo;ve seen a practical example, let&amp;rsquo;s switch gears and delve into a possible source of confusion in &lt;code&gt;logging&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;the-why-didnt-my-log-message-go-anywhere-dilemma&quot;&gt;The &amp;ldquo;Why Didn&amp;rsquo;t My Log Message Go Anywhere?&amp;rdquo; Dilemma&lt;/h2&gt;
&lt;p&gt;There are two common situations with &lt;code&gt;logging&lt;/code&gt; when it&amp;rsquo;s easy to get tripped up:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You logged a message that seemingly went nowhere, and you&amp;rsquo;re not sure why.&lt;/li&gt;
&lt;li&gt;Instead of being suppressed, a log message appeared in a place that you didn&amp;rsquo;t expect it to.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Each of these has a reason or two commonly associated with it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You logged a message that seemingly went nowhere, and you&amp;rsquo;re not sure why.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Don&amp;rsquo;t forget that the &lt;strong&gt;effective&lt;/strong&gt; level of a logger for which you don&amp;rsquo;t otherwise set a custom level is &lt;code&gt;WARNING&lt;/code&gt;, because a logger will walk up its hierarchy until it finds the root logger with its own &lt;code&gt;WARNING&lt;/code&gt; level:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;xyz&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;debug&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;mind numbing info here&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critical&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;storm is coming&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;storm is coming&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because of this default, the &lt;code&gt;.debug()&lt;/code&gt; call goes nowhere.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Instead of being suppressed, a log message appeared in a place that you didn&amp;rsquo;t expect it to.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When you defined your &lt;code&gt;logger&lt;/code&gt; above, you didn&amp;rsquo;t add any handlers to it.  So, why is it writing to the console?&lt;/p&gt;
&lt;p&gt;The reason for this is that &lt;code&gt;logging&lt;/code&gt; &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#1157&quot;&gt;sneakily uses&lt;/a&gt; a handler called &lt;code&gt;lastResort&lt;/code&gt; that writes to &lt;code&gt;sys.stderr&lt;/code&gt; if no other handlers are found:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;_StderrHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
    &lt;span class=&quot;nd&quot;&gt;@property&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stderr&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;_defaultLastResort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_StderrHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WARNING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lastResort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_defaultLastResort&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This kicks in when a logger goes to find its handlers:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Filterer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;callHandlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;found&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdlr&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;found&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;found&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;levelno&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdlr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;hdlr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;propagate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;found&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastResort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;                &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;levelno&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lastResort&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;                     &lt;span class=&quot;n&quot;&gt;lastResort&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the logger gives up on its search for handlers (both its own direct handlers and attributes of parent loggers), then it picks up the &lt;code&gt;lastResort&lt;/code&gt; handler and uses that.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s one more subtle detail worth knowing about.  This section has largely talked about the instance methods (methods that a class defines) rather than the module-level functions of the &lt;code&gt;logging&lt;/code&gt; package that carry the same name.&lt;/p&gt;
&lt;p&gt;If you use the functions, such as &lt;code&gt;logging.info()&lt;/code&gt; rather than &lt;code&gt;logger.info()&lt;/code&gt;, then something slightly different happens internally.  The function calls &lt;code&gt;logging.basicConfig()&lt;/code&gt;, which adds a &lt;code&gt;StreamHandler&lt;/code&gt; that writes to &lt;code&gt;sys.stderr&lt;/code&gt;.  In the end, the behavior is virtually the same:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handlers&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasHandlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;basicConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handlers&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;lt;StreamHandler &amp;lt;stderr&amp;gt; (NOTSET)&amp;gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hasHandlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;taking-advantage-of-lazy-formatting&quot;&gt;Taking Advantage of Lazy Formatting&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s time to switch gears and take a closer look at how messages themselves are joined with their data.  While it&amp;rsquo;s been supplanted by &lt;a href=&quot;https://realpython.com/python-f-strings/#option-2-strformat&quot;&gt;&lt;code&gt;str.format()&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/python-f-strings/&quot;&gt;f-strings&lt;/a&gt;, you&amp;rsquo;ve probably used Python&amp;rsquo;s percent-style formatting to do something like this:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;To iterate is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, to recurse &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;human&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;divine&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;To iterate is human, to recurse divine&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As a result, you may be tempted to do the same thing in a &lt;code&gt;logging&lt;/code&gt; call:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Bad!  Check out a more efficient alternative below.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;To iterate is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, to recurse &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;human&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;divine&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;WARNING:root:To iterate is human, to recurse divine&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This uses the entire format string and its arguments as the &lt;code&gt;msg&lt;/code&gt; argument to &lt;code&gt;logging.warning()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Here is the recommended alternative, &lt;a href=&quot;https://docs.python.org/3/howto/logging.html#logging-variable-data&quot;&gt;straight from the &lt;code&gt;logging&lt;/code&gt; docs&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Better: formatting doesn&amp;#39;t occur until it really needs to.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;To iterate is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, to recurse &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;human&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;divine&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;WARNING:root:To iterate is human, to recurse divine&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It looks a little weird, right?  This seems to defy the conventions of how percent-style string formatting works, but it&amp;rsquo;s a more efficient function call because the format string gets formatted &lt;a href=&quot;https://docs.python.org/3/howto/logging.html#optimization&quot;&gt;&lt;strong&gt;lazily&lt;/strong&gt; rather than &lt;strong&gt;greedily&lt;/strong&gt;&lt;/a&gt;.  Here&amp;rsquo;s what that means.&lt;/p&gt;
&lt;p&gt;The method signature for &lt;code&gt;Logger.warning()&lt;/code&gt; looks like this:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;warning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The same applies to the other methods, such as &lt;code&gt;.debug()&lt;/code&gt;.  When you call &lt;code&gt;warning(&quot;To iterate is %s, to recurse %s&quot;, &quot;human&quot;, &quot;divine&quot;)&lt;/code&gt;, both &lt;code&gt;&quot;human&quot;&lt;/code&gt; and &lt;code&gt;&quot;divine&quot;&lt;/code&gt; get caught as &lt;code&gt;*args&lt;/code&gt; and, within the scope of the method&amp;rsquo;s body, &lt;code&gt;args&lt;/code&gt; is equal to &lt;code&gt;(&quot;human&quot;, &quot;divine&quot;)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Contrast this to the first call above:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;To iterate is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, to recurse &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;human&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;divine&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this form, everything in the parentheses gets immediately merged together into &lt;code&gt;&quot;To iterate is human, to recurse divine&quot;&lt;/code&gt; and passed as &lt;code&gt;msg&lt;/code&gt;, while &lt;code&gt;args&lt;/code&gt; is an empty tuple.&lt;/p&gt;
&lt;p&gt;Why does this matter?  Repeated logging calls can degrade runtime performance slightly, but the &lt;code&gt;logging&lt;/code&gt; package does its very best to control that and keep it in check.  By not merging the format string with its arguments right away, &lt;code&gt;logging&lt;/code&gt; is delaying the string formatting until the &lt;code&gt;LogRecord&lt;/code&gt; is requested by a &lt;code&gt;Handler&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This happens in &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L371&quot;&gt;&lt;code&gt;LogRecord.getMessage()&lt;/code&gt;&lt;/a&gt;, so only after &lt;code&gt;logging&lt;/code&gt; deems that the &lt;code&gt;LogRecord&lt;/code&gt; will actually be passed to a handler does it become its fully merged self.&lt;/p&gt;
&lt;p&gt;All that is to say that the &lt;code&gt;logging&lt;/code&gt; package makes some very fine-tuned performance optimizations in the right places.  This may seem like minutia, but if you&amp;rsquo;re making the same &lt;code&gt;logging.debug()&lt;/code&gt; call a million times inside a loop, and the &lt;code&gt;args&lt;/code&gt; are function calls, then the lazy nature of how &lt;code&gt;logging&lt;/code&gt; does string formatting can make a difference.&lt;/p&gt;
&lt;p&gt;Before doing any merging of &lt;code&gt;msg&lt;/code&gt; and &lt;code&gt;args&lt;/code&gt;, a &lt;code&gt;Logger&lt;/code&gt; instance will check its &lt;code&gt;.isEnabledFor()&lt;/code&gt; to see if that merging should be done in the first place.&lt;/p&gt;
&lt;h2 id=&quot;functions-vs-methods&quot;&gt;Functions vs Methods&lt;/h2&gt;
&lt;p&gt;Towards the bottom of &lt;code&gt;logging/__init__.py&lt;/code&gt; sit the module-level functions that are advertised up front in the public API of &lt;code&gt;logging&lt;/code&gt;.  You already saw the &lt;code&gt;Logger&lt;/code&gt; methods such as &lt;code&gt;.debug()&lt;/code&gt;, &lt;code&gt;.info()&lt;/code&gt;, and &lt;code&gt;.warning()&lt;/code&gt;.  The top-level functions are wrappers around the corresponding methods of the same name, but they have two important features:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;They always call their corresponding method from the root logger, &lt;code&gt;root&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Before calling the root logger methods, they call &lt;code&gt;logging.basicConfig()&lt;/code&gt; with no arguments if &lt;code&gt;root&lt;/code&gt; doesn&amp;rsquo;t have any handlers.  As you saw earlier, it is this call that sets a &lt;code&gt;sys.stdout&lt;/code&gt; handler for the root logger.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For illustration, here&amp;rsquo;s &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L1953&quot;&gt;&lt;code&gt;logging.error()&lt;/code&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handlers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;basicConfig&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll find the same pattern for &lt;code&gt;logging.debug()&lt;/code&gt;, &lt;code&gt;logging.info()&lt;/code&gt;, and the others as well.  Tracing the chain of commands is interesting.  Eventually, you&amp;rsquo;ll end up at the same place, which is where the internal &lt;code&gt;Logger._log()&lt;/code&gt; is called.&lt;/p&gt;
&lt;p&gt;The calls to &lt;code&gt;debug()&lt;/code&gt;, &lt;code&gt;info()&lt;/code&gt;, &lt;code&gt;warning()&lt;/code&gt;, and the other level-based functions all route to here.  &lt;code&gt;_log()&lt;/code&gt; primarily has two purposes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Call &lt;code&gt;self.makeRecord()&lt;/code&gt;:&lt;/strong&gt; Make a &lt;code&gt;LogRecord&lt;/code&gt; instance from the &lt;code&gt;msg&lt;/code&gt; and other arguments you pass to it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Call &lt;code&gt;self.handle()&lt;/code&gt;:&lt;/strong&gt; This determines what actually gets done with the record.  Where does it get sent?  Does it make it there or get filtered out?&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;rsquo;s that entire process in one diagram:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/flow-2.b9f0faf58539.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-66&quot; src=&quot;https://files.realpython.com/media/flow-2.b9f0faf58539.png&quot; width=&quot;753&quot; height=&quot;1023&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/flow-2.b9f0faf58539.png&amp;amp;w=188&amp;amp;sig=d9980bfa251659d5b9c5c5208dbac0149f62cdda 188w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/flow-2.b9f0faf58539.png&amp;amp;w=376&amp;amp;sig=ac83a123ce0467359ef04381b6139748e02733f2 376w, https://files.realpython.com/media/flow-2.b9f0faf58539.png 753w&quot; sizes=&quot;75vw&quot; alt=&quot;Logging function call stack&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Internals of a logging call (Image: Real Python)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;You can also trace the call stack with &lt;code&gt;pdb&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card8e67cf&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse8e67cf&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse8e67cf&quot;&gt;Tracing the Call to logging.warning()&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse8e67cf&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse8e67cf&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse8e67cf&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card8e67cf&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pdb&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;logging.warning(&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;quot;, &amp;quot;uh&amp;quot;, &amp;quot;oh&amp;quot;)&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; &amp;lt;string&amp;gt;(1)&amp;lt;module&amp;gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;--Call--&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1971)warning()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; def warning(msg, *args, **kwargs):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1977)warning()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; if len(root.handlers) == 0:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) unt&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1978)warning()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; basicConfig()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) unt&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1979)warning()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; root.warning(msg, *args, **kwargs)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;--Call--&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1385)warning()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; def warning(self, msg, *args, **kwargs):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) l&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1380             logger.info(&amp;quot;Houston, we have a %s&amp;quot;, &amp;quot;interesting problem&amp;quot;, exc_info=1)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1381             &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1382             if self.isEnabledFor(INFO):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1383                 self._log(INFO, msg, args, **kwargs)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1384     &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1385 -&amp;gt;        def warning(self, msg, *args, **kwargs):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1386             &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1387             Log &amp;#39;msg % args&amp;#39; with severity &amp;#39;WARNING&amp;#39;.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1388     &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1389             To pass exception information, use the keyword argument exc_info with&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1390             a true value, e.g.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1394)warning()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; if self.isEnabledFor(WARNING):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) unt&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1395)warning()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; self._log(WARNING, msg, args, **kwargs)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;--Call--&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1496)_log()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False):&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1501)_log()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; sinfo = None&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) unt 1517&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1517)_log()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; record = self.makeRecord(self.name, level, fn, lno, msg, args,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1518)_log()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; exc_info, func, extra, sinfo)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) s&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;--Call--&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1481)makeRecord()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; def makeRecord(self, name, level, fn, lno, msg, args, exc_info,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) p name&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;root&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) p level&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;30&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) p msg&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;%s-%s&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) p args&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;uh&amp;#39;, &amp;#39;oh&amp;#39;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) up&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1518)_log()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; exc_info, func, extra, sinfo)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) unt&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;gt; lib/python3.7/logging/__init__.py(1519)_log()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-&amp;gt; self.handle(record)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(Pdb) n&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;WARNING:root:uh-oh&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h2 id=&quot;what-does-getlogger-really-do&quot;&gt;What Does &lt;code&gt;getLogger()&lt;/code&gt; Really Do?&lt;/h2&gt;
&lt;p&gt;Also hiding in this section of the source code is the top-level &lt;code&gt;getLogger()&lt;/code&gt;, which wraps &lt;code&gt;Logger.manager.getLogger()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the entry point for enforcing the singleton logger design:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;If you specify a &lt;code&gt;name&lt;/code&gt;, then the underlying &lt;code&gt;.getLogger()&lt;/code&gt; does a &lt;code&gt;dict&lt;/code&gt; lookup on the string &lt;code&gt;name&lt;/code&gt;.  What this comes down to is a lookup in the &lt;code&gt;loggerDict&lt;/code&gt; of &lt;code&gt;logging.Manager&lt;/code&gt;.  This is a dictionary of all registered loggers, including the intermediate &lt;code&gt;PlaceHolder&lt;/code&gt; instances that are generated when you reference a logger far down in the hierarchy before referencing its parents.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Otherwise, &lt;code&gt;root&lt;/code&gt; is returned.  There is only one &lt;code&gt;root&lt;/code&gt;&amp;mdash;the instance of &lt;code&gt;RootLogger&lt;/code&gt; discussed above.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This feature is what lies behind a trick that can let you peek into all of the registered loggers:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loggerDict&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{}&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pprint&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pprint&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;asyncio&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pprint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loggerDict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;asyncio&amp;#39;: &amp;lt;Logger asyncio (WARNING)&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;concurrent&amp;#39;: &amp;lt;logging.PlaceHolder object at 0x10d153710&amp;gt;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;concurrent.futures&amp;#39;: &amp;lt;Logger concurrent.futures (WARNING)&amp;gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Whoa, hold on a minute.  What&amp;rsquo;s happening here?  It looks like something changed internally to the &lt;code&gt;logging&lt;/code&gt; package as a result of an import of another library, and that&amp;rsquo;s exactly what happened.&lt;/p&gt;
&lt;p&gt;Firstly, recall that &lt;code&gt;Logger.manager&lt;/code&gt; is a class attribute, where an instance of &lt;code&gt;Manager&lt;/code&gt; is tacked onto the &lt;code&gt;Logger&lt;/code&gt; class.  The &lt;code&gt;manager&lt;/code&gt; is designed to track and manage all of the singleton instances of &lt;code&gt;Logger&lt;/code&gt;.  These are housed in &lt;code&gt;.loggerDict&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, when you initially import &lt;code&gt;logging&lt;/code&gt;, this dictionary is empty.  But after you import &lt;code&gt;asyncio&lt;/code&gt;, the same dictionary gets populated with three loggers.  This is an example of one module setting the attributes of another module in-place.  Sure enough, inside of &lt;code&gt;asyncio/log.py&lt;/code&gt;, you&amp;rsquo;ll find the following:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__package__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# &amp;quot;asyncio&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The key-value pair is &lt;a href=&quot;https://github.com/python/cpython/blob/d730719b094cb006711b1cd546927b863c173b31/Lib/logging/__init__.py#L1243&quot;&gt;set&lt;/a&gt; in &lt;code&gt;Logger.getLogger()&lt;/code&gt; so that the &lt;code&gt;manager&lt;/code&gt; can oversee the entire namespace of loggers.  This means that the object &lt;code&gt;asyncio.log.logger&lt;/code&gt; gets registered in the logger dictionary that belongs to the &lt;code&gt;logging&lt;/code&gt; package.  Something similar happens in the &lt;code&gt;concurrent.futures&lt;/code&gt; package as well, which is imported by &lt;code&gt;asyncio&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can see the power of the singleton design in an equivalence test:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;asyncio&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;manager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loggerDict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;asyncio&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This comparison illustrates (glossing over a few details) what &lt;code&gt;getLogger()&lt;/code&gt; ultimately does.&lt;/p&gt;
&lt;h2 id=&quot;library-vs-application-logging-what-is-nullhandler&quot;&gt;Library vs Application Logging: What Is &lt;code&gt;NullHandler&lt;/code&gt;?&lt;/h2&gt;
&lt;p&gt;That brings us to the final hundred or so lines in the &lt;code&gt;logging/__init__.py&lt;/code&gt; source, where &lt;code&gt;NullHandler&lt;/code&gt; is defined.  Here&amp;rsquo;s the definition in all its glory:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;NullHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Handler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;handle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;createLock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lock&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;NullHandler&lt;/code&gt; is all about the distinctions between logging in a library versus an application.  Let&amp;rsquo;s see what that means.&lt;/p&gt;
&lt;p&gt;A &lt;strong&gt;library&lt;/strong&gt; is an extensible, generalizable Python package that is intended for other users to install and set up.  It is built by a developer with the express purpose of being distributed to users.  Examples include popular open-source projects like &lt;a href=&quot;https://github.com/numpy/numpy&quot;&gt;NumPy&lt;/a&gt;, &lt;a href=&quot;https://github.com/dateutil/dateutil&quot;&gt;&lt;code&gt;dateutil&lt;/code&gt;&lt;/a&gt;, and &lt;a href=&quot;https://github.com/pyca/cryptography&quot;&gt;&lt;code&gt;cryptography&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;An &lt;strong&gt;application&lt;/strong&gt; (or app, or program) is designed for a more specific purpose and a much smaller set of users (possibly just one user).  It&amp;rsquo;s a program or set of programs highly tailored by the user to do a limited set of things.  An example of an application is a Django app that sits behind a web page.  Applications commonly use (&lt;code&gt;import&lt;/code&gt;) libraries and the tools they contain.&lt;/p&gt;
&lt;p&gt;When it comes to logging, there are different best practices in a library versus an app.&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s where &lt;code&gt;NullHandler&lt;/code&gt; fits in.  It&amp;rsquo;s basically a do-nothing stub class.  &lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re writing a Python library, you really need to do this one minimalist piece of setup in your package&amp;rsquo;s &lt;code&gt;__init__.py&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Place this in your library&amp;#39;s uppermost `__init__.py`&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Nothing else!&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NullHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This serves two critical purposes.&lt;/p&gt;
&lt;p&gt;Firstly, a library logger that is declared with &lt;code&gt;logger = logging.getLogger(__name__)&lt;/code&gt; (without any further configuration) will log to &lt;code&gt;sys.stderr&lt;/code&gt; by default, even if that&amp;rsquo;s not what the end user wants. This could be described as an opt-out approach, where the end user of the library has to go in and disable logging to their console if they don&amp;rsquo;t want it.&lt;/p&gt;
&lt;p&gt;Common wisdom says to use an opt-in approach instead: don&amp;rsquo;t emit any log messages by default, and let the end users of the library determine if they want to further configure the library&amp;rsquo;s loggers and add handlers to them.  Here&amp;rsquo;s that philosophy worded more bluntly by the author of the &lt;code&gt;logging&lt;/code&gt; package, Vinay Sajip:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A third party library which uses &lt;code&gt;logging&lt;/code&gt; should not spew logging output by default which may not be wanted by a developer/user of an application which uses it. (&lt;a href=&quot;https://wiki.python.org/moin/LoggingPackage&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This leaves it up to the library user, not library developer, to incrementally call methods such as &lt;code&gt;logger.addHandler()&lt;/code&gt; or &lt;code&gt;logger.setLevel()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The second reason that &lt;code&gt;NullHandler&lt;/code&gt; exists is more archaic.  In Python 2.7 and earlier, trying to log a &lt;code&gt;LogRecord&lt;/code&gt; from a logger that has no handler set would &lt;a href=&quot;https://github.com/python/cpython/blob/e84f6d3817ad3d18fdfbb5223b8078606166cea0/Lib/logging/__init__.py#L1348&quot;&gt;raise a warning&lt;/a&gt;.  Adding the no-op class &lt;code&gt;NullHandler&lt;/code&gt; will avert this.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what specifically happens in the line &lt;code&gt;logging.getLogger(__name__).addHandler(NullHandler())&lt;/code&gt; from above:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Python gets (creates) the &lt;code&gt;Logger&lt;/code&gt; instance with the same name as your package.  If you&amp;rsquo;re designing the &lt;code&gt;calculus&lt;/code&gt; package, within &lt;code&gt;__init__.py&lt;/code&gt;, then &lt;code&gt;__name__&lt;/code&gt; will be equal to &lt;code&gt;&#39;calculus&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A &lt;code&gt;NullHandler&lt;/code&gt; instance gets attached to this logger.  That means that Python will not default to using the &lt;code&gt;lastResort&lt;/code&gt; handler.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Keep in mind that any logger created in any of the other &lt;code&gt;.py&lt;/code&gt; modules of the package will be children of this logger in the logger hierarchy and that, because this handler also belongs to them, they won&amp;rsquo;t need to use the &lt;code&gt;lastResort&lt;/code&gt; handler and won&amp;rsquo;t default to logging to standard error (&lt;code&gt;stderr&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;As a quick example, let&amp;rsquo;s say your library has the following structure:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;calculus/
│
├── __init__.py
└── integration.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;integration.py&lt;/code&gt;, as the library developer you are free to do the following:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# calculus/integration.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;logging&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getLogger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;warning&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Look!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Do stuff&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, a user comes along and installs your library from PyPI via &lt;code&gt;pip install calculus&lt;/code&gt;.  They use &lt;code&gt;from calculus.integration import func&lt;/code&gt; in some application code.  This user is free to manipulate and configure the &lt;code&gt;logger&lt;/code&gt; object from the library like any other Python object, to their heart&amp;rsquo;s content.&lt;/p&gt;
&lt;h2 id=&quot;what-logging-does-with-exceptions&quot;&gt;What Logging Does With Exceptions&lt;/h2&gt;
&lt;p&gt;One thing that you may be wary of is the danger of exceptions that stem from your calls to &lt;code&gt;logging&lt;/code&gt;.  If you have a &lt;code&gt;logging.error()&lt;/code&gt; call that is designed to give you some more verbose debugging information, but that call itself for some reason raises an exception, that would be the height of irony, right?&lt;/p&gt;
&lt;p&gt;Cleverly, if the &lt;code&gt;logging&lt;/code&gt; package encounters an exception that has to do with logging itself, then it will print the traceback, but not raise the exception itself.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example that deals with a common typo: passing two arguments to a format string that is only expecting one argument.  The important distinction is that what you see below is &lt;em&gt;not&lt;/em&gt; an exception being raised, but rather a prettified printed traceback of the internal exception, which itself was suppressed: &lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;critical&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;This &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; has too many arguments&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;msg&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;other&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;--- Logging error ---&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;lib/python3.7/logging/__init__.py&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1034&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;emit&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;lib/python3.7/logging/__init__.py&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;880&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fmt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;lib/python3.7/logging/__init__.py&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;619&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;message&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;lib/python3.7/logging/__init__.py&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;380&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;getMessage&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;not all arguments converted during string formatting&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Call stack:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  File &amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;, line 1, in &amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Message: &amp;#39;This %s has too many arguments&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Arguments: (&amp;#39;msg&amp;#39;, &amp;#39;other&amp;#39;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This lets your program gracefully carry on with its actual program flow.  The rationale is that you wouldn&amp;rsquo;t want an uncaught exception to come from a &lt;code&gt;logging&lt;/code&gt; call itself and stop a program dead in its tracks.&lt;/p&gt;
&lt;p&gt;Tracebacks can be messy, but this one is informative and relatively straightforward.  What enables the suppression of exceptions related to &lt;code&gt;logging&lt;/code&gt; is &lt;code&gt;Handler.handleError()&lt;/code&gt;.  When the handler calls &lt;code&gt;.emit()&lt;/code&gt;, which is the method where it attempts to log the record, it falls back to &lt;code&gt;.handleError()&lt;/code&gt; if something goes awry.  Here&amp;rsquo;s the implementation of &lt;code&gt;.emit()&lt;/code&gt; for the &lt;code&gt;StreamHandler&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;emit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;terminator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handleError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;record&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Any exception related to the formatting and writing gets caught rather than being raised, and &lt;code&gt;handleError&lt;/code&gt; gracefully writes the traceback to &lt;code&gt;sys.stderr&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;logging-python-tracebacks&quot;&gt;Logging Python Tracebacks&lt;/h2&gt;
&lt;p&gt;Speaking of exceptions and their tracebacks, what about cases where your program encounters them but should log the exception and keep chugging along in its execution?&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s walk through a couple of ways to do this.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a contrived example of a lottery simulator using code that isn&amp;rsquo;t Pythonic on purpose.  You&amp;rsquo;re developing an online lottery game where users can wager on their lucky number:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Lottery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make_tickets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;yield&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;pool&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_tickets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shuffle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Behind the frontend application sits the critical code below.  You want to make sure that you keep track of any errors caused by the site that may make a user lose their money.  The first (suboptimal) way is to use &lt;code&gt;logging.error()&lt;/code&gt; and log the &lt;code&gt;str&lt;/code&gt; form of the exception instance itself:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;lucky_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Enter your ticket number: &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;drawn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Lottery&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;draw&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lucky_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;drawn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Winner chicken dinner!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# NOTE: See below for a better way to do this.&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Could not draw ticket: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will only get you the actual exception message, rather than the traceback.  You check the logs on your website&amp;rsquo;s server and find this cryptic message:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;ERROR:root:Could not draw ticket: object of type &amp;#39;generator&amp;#39; has no len()
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Hmm.  As the application developer, you&amp;rsquo;ve got a serious problem, and a user got ripped off as a result.  But maybe this exception message itself isn&amp;rsquo;t very informative.  Wouldn&amp;rsquo;t it be nice to see the lineage of the traceback that led to this exception?&lt;/p&gt;
&lt;p&gt;The proper solution is to use &lt;code&gt;logging.exception()&lt;/code&gt;, which logs a message with level &lt;code&gt;ERROR&lt;/code&gt; and also displays the exception traceback.  Replace the two final lines above with these:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;logging&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Could not draw ticket&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you get a better indication of what&amp;rsquo;s going on:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;ERROR:root:Could not draw ticket&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;9&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;draw&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;lib/python3.7/random.py&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;275&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;shuffle&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;reversed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))):&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;object of type &amp;#39;generator&amp;#39; has no len()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using &lt;code&gt;exception()&lt;/code&gt; saves you from having to reference the exception yourself because &lt;code&gt;logging&lt;/code&gt; pulls it in with &lt;code&gt;sys.exc_info()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This makes things clearer that the problem stems from &lt;code&gt;random.shuffle()&lt;/code&gt;, which needs to know the length of the object it is shuffling.  Because our &lt;code&gt;Lottery&lt;/code&gt; class passes a generator to &lt;code&gt;shuffle()&lt;/code&gt;, it gets held up and raises before the pool can be shuffled, much less generate a winning ticket.&lt;/p&gt;
&lt;p&gt;In large, full-blown applications, you&amp;rsquo;ll find &lt;code&gt;logging.exception()&lt;/code&gt; to be even more useful when deep, multi-library tracebacks are involved, and you can&amp;rsquo;t step into them with a live debugger like &lt;code&gt;pdb&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The code for &lt;code&gt;logging.Logger.exception()&lt;/code&gt;, and hence &lt;code&gt;logging.exception()&lt;/code&gt;, is just a single line:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exc_info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exc_info&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exc_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That is, &lt;code&gt;logging.exception()&lt;/code&gt; just calls &lt;code&gt;logging.error()&lt;/code&gt; with &lt;code&gt;exc_info=True&lt;/code&gt;, which is otherwise &lt;code&gt;False&lt;/code&gt; by default.  If you want to log an exception traceback but at a level different than &lt;code&gt;logging.ERROR&lt;/code&gt;, just call that function or method with &lt;code&gt;exc_info=True&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Keep in mind that &lt;code&gt;exception()&lt;/code&gt; should only be called in the context of an exception handler, inside of an &lt;code&gt;except&lt;/code&gt; block:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_longwinded_nested_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# We are in the context of exception handler now.&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# If it&amp;#39;s unclear exactly *why* we couldn&amp;#39;t process&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# `i`, then log the traceback and move on rather than&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# ditching completely.&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;logger&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Could not process &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;continue&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Use this pattern sparingly rather than as a means to suppress any exception.  It can be most helpful when you&amp;rsquo;re debugging a long function call stack where you&amp;rsquo;re otherwise seeing an ambiguous, unclear, and hard-to-track error.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Pat yourself on the back, because you&amp;rsquo;ve just walked through almost 2,000 lines of dense source code.  You&amp;rsquo;re now better equipped to deal with the &lt;code&gt;logging&lt;/code&gt; package!&lt;/p&gt;
&lt;p&gt;Keep in mind that this tutorial has been far from exhaustive in covering all of the classes found in the &lt;code&gt;logging&lt;/code&gt; package.  There&amp;rsquo;s even more machinery that glues everything together. If you&amp;rsquo;d like to learn more, then you can look into the &lt;code&gt;Formatter&lt;/code&gt; classes and the separate modules &lt;code&gt;logging/config.py&lt;/code&gt; and &lt;code&gt;logging/handlers.py&lt;/code&gt;.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Interactive Data Visualization in Python With Bokeh</title>
      <id>https://realpython.com/courses/interactive-data-visualization-python-bokeh/</id>
      <link href="https://realpython.com/courses/interactive-data-visualization-python-bokeh/"/>
      <updated>2019-05-21T14:00:00+00:00</updated>
      <summary>This course will get you up and running with Bokeh, using examples and a real-world dataset. You&#39;ll learn how to visualize your data, customize and organize your visualizations, and add interactivity.</summary>
      <content type="html">
        &lt;p&gt;Bokeh prides itself on being a library for &lt;em&gt;interactive&lt;/em&gt; data visualization. The graphics are rendered using HTML and JavaScript, and your visualizations are easy to share as an HTML page. You will create a number of visualizations based on a real-world dataset. &lt;/p&gt;
&lt;p&gt;The goal of this course is to get you up and running with Bokeh.&lt;/p&gt;
&lt;p&gt;You will learn how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Transform your data&lt;/strong&gt; into visualizations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Customize and organize&lt;/strong&gt; your visualizations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add interactivity&lt;/strong&gt; to your visualizations&lt;/li&gt;
&lt;/ul&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Unicode &amp; Character Encodings in Python: A Painless Guide</title>
      <id>https://realpython.com/python-encodings-guide/</id>
      <link href="https://realpython.com/python-encodings-guide/"/>
      <updated>2019-05-20T14:00:00+00:00</updated>
      <summary>In this tutorial, you&#39;ll get a Python-centric introduction to character encodings and unicode. Handling character encodings and numbering systems can at times seem painful and complicated, but this guide is here to help with easy-to-follow Python examples.</summary>
      <content type="html">
        &lt;p&gt;Handling character encodings in Python or any other language can at times seem painful.  Places such as Stack Overflow have thousands of questions stemming from confusion over exceptions like &lt;code&gt;UnicodeDecodeError&lt;/code&gt; and &lt;code&gt;UnicodeEncodeError&lt;/code&gt;. This tutorial is designed to clear the &lt;code&gt;Exception&lt;/code&gt; fog and illustrate that working with text and binary data in Python 3 can be a smooth experience.  Python&amp;rsquo;s Unicode support is strong and robust, but it takes some time to master.&lt;/p&gt;
&lt;p&gt;This tutorial is different because it&amp;rsquo;s not language-agnostic but instead deliberately Python-centric.  You&amp;rsquo;ll still get a language-agnostic primer, but you&amp;rsquo;ll then dive into illustrations in Python, with text-heavy paragraphs kept to a minimum.  You&amp;rsquo;ll see how to use concepts of character encodings in live Python code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this tutorial, you&amp;rsquo;ll:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get conceptual overviews on character encodings and numbering systems&lt;/li&gt;
&lt;li&gt;Understand how encoding comes into play with Python&amp;rsquo;s &lt;code&gt;str&lt;/code&gt; and &lt;code&gt;bytes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Know about support in Python for numbering systems through its various forms of &lt;code&gt;int&lt;/code&gt; literals&lt;/li&gt;
&lt;li&gt;Be familiar with Python&amp;rsquo;s built-in functions related to character encodings and numbering systems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Character encoding and numbering systems are so closely connected that they need to be covered in the same tutorial or else the treatment of either would be totally inadequate.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: This article is Python 3-centric.  Specifically, all code examples in this tutorial were generated from a CPython 3.7.2 shell, although all minor versions of Python 3 should behave (mostly) the same in their treatment of text.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re still using Python 2 and are intimidated by the differences in how Python 2 and Python 3 treat text and binary data, then hopefully this tutorial will help you make the switch.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-tricks-sample&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a chapter from Python Tricks: The Book&lt;/a&gt; that shows you Python&#39;s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;whats-a-character-encoding&quot;&gt;What&amp;rsquo;s a Character Encoding?&lt;/h2&gt;
&lt;p&gt;There are tens if not hundreds of character encodings.  The best way to start understanding what they are is to cover one of the simplest character encodings, ASCII.&lt;/p&gt;
&lt;p&gt;Whether you&amp;rsquo;re self-taught or have a formal computer science background, chances are you&amp;rsquo;ve seen an ASCII table once or twice.  ASCII is a good place to start learning about character encoding because it is a small and contained encoding.  (Too small, as it turns out.)&lt;/p&gt;
&lt;p&gt;It encompasses the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lowercase English letters&lt;/strong&gt;: &lt;em&gt;a&lt;/em&gt; through &lt;em&gt;z&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Uppercase English letters&lt;/strong&gt;: &lt;em&gt;A&lt;/em&gt; through &lt;em&gt;Z&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Some punctuation and symbols&lt;/strong&gt;: &lt;code&gt;&quot;$&quot;&lt;/code&gt; and &lt;code&gt;&quot;!&quot;&lt;/code&gt;, to name a couple&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Whitespace characters&lt;/strong&gt;: an actual space (&lt;code&gt;&quot; &quot;&lt;/code&gt;), as well as a newline, carriage return, horizontal tab, vertical tab, and a few others&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Some non-printable characters&lt;/strong&gt;:  characters such as backspace, &lt;code&gt;&quot;\b&quot;&lt;/code&gt;, that can&amp;rsquo;t be printed literally in the way that the letter &lt;em&gt;A&lt;/em&gt; can&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So what is a more formal definition of a character encoding?  &lt;/p&gt;
&lt;p&gt;At a very high level, it&amp;rsquo;s a way of translating characters (such as letters, punctuation, symbols, whitespace, and control characters) to integers and ultimately to bits.  Each character can be encoded to a unique sequence of bits.  Don&amp;rsquo;t worry if you&amp;rsquo;re shaky on the concept of bits, because we&amp;rsquo;ll get to them shortly.&lt;/p&gt;
&lt;p&gt;The various categories outlined represent groups of characters.  Each single character has a corresponding &lt;strong&gt;code point&lt;/strong&gt;, which you can think of as just an integer.  Characters are segmented into different ranges within the ASCII table:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Code Point Range&lt;/th&gt;
&lt;th&gt;Class&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0 through 31&lt;/td&gt;
&lt;td&gt;Control/non-printable characters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32 through 64&lt;/td&gt;
&lt;td&gt;Punctuation, symbols, numbers, and space&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;65 through 90&lt;/td&gt;
&lt;td&gt;Uppercase English alphabet letters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;91 through 96&lt;/td&gt;
&lt;td&gt;Additional graphemes, such as &lt;code&gt;[&lt;/code&gt; and &lt;code&gt;\&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;97 through 122&lt;/td&gt;
&lt;td&gt;Lowercase English alphabet letters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;123 through 126&lt;/td&gt;
&lt;td&gt;Additional graphemes, such as &lt;code&gt;{&lt;/code&gt; and &lt;code&gt;|&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;127&lt;/td&gt;
&lt;td&gt;Control/non-printable character (&lt;code&gt;DEL&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;The entire ASCII table contains 128 characters.  This table captures the complete &lt;strong&gt;character set&lt;/strong&gt; that ASCII permits.  If you don&amp;rsquo;t see a character here, then you simply can&amp;rsquo;t express it as printed text under the ASCII encoding scheme.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardf90431&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsef90431&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsef90431&quot;&gt;ASCII Table&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsef90431&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsef90431&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapsef90431&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardf90431&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Code Point&lt;/th&gt;
&lt;th&gt;Character (Name)&lt;/th&gt;
&lt;th&gt;Code Point&lt;/th&gt;
&lt;th&gt;Character (Name)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;NUL (Null)&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;SOH (Start of Heading)&lt;/td&gt;
&lt;td&gt;65&lt;/td&gt;
&lt;td&gt;&lt;code&gt;A&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;STX (Start of Text)&lt;/td&gt;
&lt;td&gt;66&lt;/td&gt;
&lt;td&gt;&lt;code&gt;B&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;ETX (End of Text)&lt;/td&gt;
&lt;td&gt;67&lt;/td&gt;
&lt;td&gt;&lt;code&gt;C&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;EOT (End of Transmission)&lt;/td&gt;
&lt;td&gt;68&lt;/td&gt;
&lt;td&gt;&lt;code&gt;D&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;ENQ (Enquiry)&lt;/td&gt;
&lt;td&gt;69&lt;/td&gt;
&lt;td&gt;&lt;code&gt;E&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;ACK (Acknowledgment)&lt;/td&gt;
&lt;td&gt;70&lt;/td&gt;
&lt;td&gt;&lt;code&gt;F&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;BEL (Bell)&lt;/td&gt;
&lt;td&gt;71&lt;/td&gt;
&lt;td&gt;&lt;code&gt;G&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;BS  (Backspace)&lt;/td&gt;
&lt;td&gt;72&lt;/td&gt;
&lt;td&gt;&lt;code&gt;H&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;HT  (Horizontal Tab)&lt;/td&gt;
&lt;td&gt;73&lt;/td&gt;
&lt;td&gt;&lt;code&gt;I&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;LF  (Line Feed)&lt;/td&gt;
&lt;td&gt;74&lt;/td&gt;
&lt;td&gt;&lt;code&gt;J&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;VT  (Vertical Tab)&lt;/td&gt;
&lt;td&gt;75&lt;/td&gt;
&lt;td&gt;&lt;code&gt;K&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;FF  (Form Feed)&lt;/td&gt;
&lt;td&gt;76&lt;/td&gt;
&lt;td&gt;&lt;code&gt;L&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;CR  (Carriage Return)&lt;/td&gt;
&lt;td&gt;77&lt;/td&gt;
&lt;td&gt;&lt;code&gt;M&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;SO  (Shift Out)&lt;/td&gt;
&lt;td&gt;78&lt;/td&gt;
&lt;td&gt;&lt;code&gt;N&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;SI  (Shift In)&lt;/td&gt;
&lt;td&gt;79&lt;/td&gt;
&lt;td&gt;&lt;code&gt;O&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;DLE (Data Link Escape)&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;&lt;code&gt;P&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;DC1 (Device Control 1)&lt;/td&gt;
&lt;td&gt;81&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Q&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;DC2 (Device Control 2)&lt;/td&gt;
&lt;td&gt;82&lt;/td&gt;
&lt;td&gt;&lt;code&gt;R&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;DC3 (Device Control 3)&lt;/td&gt;
&lt;td&gt;83&lt;/td&gt;
&lt;td&gt;&lt;code&gt;S&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;DC4 (Device Control 4)&lt;/td&gt;
&lt;td&gt;84&lt;/td&gt;
&lt;td&gt;&lt;code&gt;T&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;NAK (Negative Acknowledgment)&lt;/td&gt;
&lt;td&gt;85&lt;/td&gt;
&lt;td&gt;&lt;code&gt;U&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;SYN (Synchronous Idle)&lt;/td&gt;
&lt;td&gt;86&lt;/td&gt;
&lt;td&gt;&lt;code&gt;V&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;ETB (End of Transmission Block)&lt;/td&gt;
&lt;td&gt;87&lt;/td&gt;
&lt;td&gt;&lt;code&gt;W&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;CAN (Cancel)&lt;/td&gt;
&lt;td&gt;88&lt;/td&gt;
&lt;td&gt;&lt;code&gt;X&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;EM  (End of Medium)&lt;/td&gt;
&lt;td&gt;89&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Y&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;SUB (Substitute)&lt;/td&gt;
&lt;td&gt;90&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Z&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;ESC (Escape)&lt;/td&gt;
&lt;td&gt;91&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;FS  (File Separator)&lt;/td&gt;
&lt;td&gt;92&lt;/td&gt;
&lt;td&gt;&lt;code&gt;\&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;GS  (Group Separator)&lt;/td&gt;
&lt;td&gt;93&lt;/td&gt;
&lt;td&gt;&lt;code&gt;]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;RS  (Record Separator)&lt;/td&gt;
&lt;td&gt;94&lt;/td&gt;
&lt;td&gt;&lt;code&gt;^&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;31&lt;/td&gt;
&lt;td&gt;US  (Unit Separator)&lt;/td&gt;
&lt;td&gt;95&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;SP  (Space)&lt;/td&gt;
&lt;td&gt;96&lt;/td&gt;
&lt;td&gt;&lt;code&gt;`&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;&lt;code&gt;!&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;97&lt;/td&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;98&lt;/td&gt;
&lt;td&gt;&lt;code&gt;b&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;&lt;code&gt;#&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;99&lt;/td&gt;
&lt;td&gt;&lt;code&gt;c&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;&lt;code&gt;%&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;&lt;code&gt;e&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;38&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;amp;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;102&lt;/td&gt;
&lt;td&gt;&lt;code&gt;f&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&#39;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;103&lt;/td&gt;
&lt;td&gt;&lt;code&gt;g&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;40&lt;/td&gt;
&lt;td&gt;&lt;code&gt;(&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;104&lt;/td&gt;
&lt;td&gt;&lt;code&gt;h&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;41&lt;/td&gt;
&lt;td&gt;&lt;code&gt;)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;105&lt;/td&gt;
&lt;td&gt;&lt;code&gt;i&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;42&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;106&lt;/td&gt;
&lt;td&gt;&lt;code&gt;j&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;107&lt;/td&gt;
&lt;td&gt;&lt;code&gt;k&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;44&lt;/td&gt;
&lt;td&gt;&lt;code&gt;,&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;108&lt;/td&gt;
&lt;td&gt;&lt;code&gt;l&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;45&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;109&lt;/td&gt;
&lt;td&gt;&lt;code&gt;m&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;46&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;110&lt;/td&gt;
&lt;td&gt;&lt;code&gt;n&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;47&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;111&lt;/td&gt;
&lt;td&gt;&lt;code&gt;o&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;48&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;112&lt;/td&gt;
&lt;td&gt;&lt;code&gt;p&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;49&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;113&lt;/td&gt;
&lt;td&gt;&lt;code&gt;q&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;50&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;114&lt;/td&gt;
&lt;td&gt;&lt;code&gt;r&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;51&lt;/td&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;115&lt;/td&gt;
&lt;td&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;52&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;116&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;53&lt;/td&gt;
&lt;td&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;117&lt;/td&gt;
&lt;td&gt;&lt;code&gt;u&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;54&lt;/td&gt;
&lt;td&gt;&lt;code&gt;6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;118&lt;/td&gt;
&lt;td&gt;&lt;code&gt;v&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;55&lt;/td&gt;
&lt;td&gt;&lt;code&gt;7&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;119&lt;/td&gt;
&lt;td&gt;&lt;code&gt;w&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;56&lt;/td&gt;
&lt;td&gt;&lt;code&gt;8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;&lt;code&gt;x&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;td&gt;&lt;code&gt;9&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;121&lt;/td&gt;
&lt;td&gt;&lt;code&gt;y&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;58&lt;/td&gt;
&lt;td&gt;&lt;code&gt;:&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;122&lt;/td&gt;
&lt;td&gt;&lt;code&gt;z&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;59&lt;/td&gt;
&lt;td&gt;&lt;code&gt;;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;123&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;124&lt;/td&gt;
&lt;td&gt;&lt;code&gt;|&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;61&lt;/td&gt;
&lt;td&gt;&lt;code&gt;=&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;125&lt;/td&gt;
&lt;td&gt;&lt;code&gt;}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;62&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;126&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;63&lt;/td&gt;
&lt;td&gt;&lt;code&gt;?&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;127&lt;/td&gt;
&lt;td&gt;DEL (delete)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h3 id=&quot;the-string-module&quot;&gt;The &lt;code&gt;string&lt;/code&gt; Module&lt;/h3&gt;
&lt;p&gt;Python&amp;rsquo;s &lt;code&gt;string&lt;/code&gt; module is a convenient one-stop-shop for string constants that fall in ASCII&amp;rsquo;s character set.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the core of the module in all its glory:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# From lib/python3.7/string.py&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;whitespace&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\t\n\r\v\f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ascii_lowercase&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;abcdefghijklmnopqrstuvwxyz&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ascii_uppercase&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ABCDEFGHIJKLMNOPQRSTUVWXYZ&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;ascii_letters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ascii_lowercase&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ascii_uppercase&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;digits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;0123456789&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hexdigits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;abcdef&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ABCDEF&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;octdigits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;01234567&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;punctuation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;quot;&amp;quot;!&amp;quot;#$%&amp;amp;&amp;#39;()*+,-./:;&amp;lt;=&amp;gt;?@[\]^_`{|}~&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;printable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ascii_letters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;punctuation&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;whitespace&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Most of these constants should be self-documenting in their identifier name.  We&amp;rsquo;ll cover what &lt;code&gt;hexdigits&lt;/code&gt; and &lt;code&gt;octdigits&lt;/code&gt; are shortly.&lt;/p&gt;
&lt;p&gt;You can use these constants for everyday string manipulation:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;string&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;What&amp;#39;s wrong with ASCII?!?!?&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rstrip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;punctuation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;What&amp;#39;s wrong with ASCII&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;code&gt;string.printable&lt;/code&gt; includes all of &lt;code&gt;string.whitespace&lt;/code&gt;.  This disagrees slightly with another method for testing whether a character is considered printable, namely &lt;code&gt;str.isprintable()&lt;/code&gt;, which will tell you that none of &lt;code&gt;{&#39;\v&#39;, &#39;\n&#39;, &#39;\r&#39;, &#39;\f&#39;, &#39;\t&#39;}&lt;/code&gt; are considered printable.&lt;/p&gt;
&lt;p&gt;The subtle difference is because of definition: &lt;code&gt;str.isprintable()&lt;/code&gt; considers something printable if &amp;ldquo;all of its characters are considered printable in &lt;code&gt;repr()&lt;/code&gt;.&amp;rdquo;&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;a-bit-of-a-refresher&quot;&gt;A Bit of a Refresher&lt;/h3&gt;
&lt;p&gt;Now is a good time for a short refresher on the &lt;strong&gt;bit&lt;/strong&gt;, the most fundamental unit of information that a computer knows.&lt;/p&gt;
&lt;p&gt;A bit is a signal that has only two possible states.  There are different ways of symbolically representing a bit that all mean the same thing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0 or 1&lt;/li&gt;
&lt;li&gt;&amp;ldquo;yes&amp;rdquo; or &amp;ldquo;no&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;True&lt;/code&gt; or &lt;code&gt;False&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&amp;ldquo;on&amp;rdquo; or &amp;ldquo;off&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Our ASCII table from the previous section uses what you and I would just call numbers (0 through 127), but what are more precisely called numbers in base 10 (decimal).&lt;/p&gt;
&lt;p&gt;You can also express each of these base-10 numbers with a sequence of bits (base 2).  Here are the binary versions of 0 through 10 in decimal:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decimal&lt;/th&gt;
&lt;th&gt;Binary (Compact)&lt;/th&gt;
&lt;th&gt;Binary (Padded Form)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;00000000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;00000001&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;00000010&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;00000011&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;100&lt;/td&gt;
&lt;td&gt;00000100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;101&lt;/td&gt;
&lt;td&gt;00000101&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;110&lt;/td&gt;
&lt;td&gt;00000110&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;111&lt;/td&gt;
&lt;td&gt;00000111&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;1000&lt;/td&gt;
&lt;td&gt;00001000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;1001&lt;/td&gt;
&lt;td&gt;00001001&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;1010&lt;/td&gt;
&lt;td&gt;00001010&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Notice that as the decimal number &lt;em&gt;n&lt;/em&gt; increases, you need more &lt;a href=&quot;https://chortle.ccsu.edu/AssemblyTutorial/Chapter-14/ass14_4.html&quot;&gt;&lt;strong&gt;significant bits&lt;/strong&gt;&lt;/a&gt; to represent the character set up to and including that number.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a handy way to represent ASCII strings as sequences of bits in Python.  Each character from the ASCII string gets pseudo-encoded into 8 bits, with spaces in between the 8-bit sequences that each represent a single character:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make_bitseq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isascii&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ASCII only allowed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;{ord(i):08b}&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_bitseq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;bits&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;01100010 01101001 01110100 01110011&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_bitseq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;CAPS&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;01000011 01000001 01010000 01010011&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_bitseq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;$25.43&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;00100100 00110010 00110101 00101110 00110100 00110011&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_bitseq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;~5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;01111110 00110101&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: &lt;code&gt;.isascii()&lt;/code&gt; was introduced in Python 3.7.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://realpython.com/python-f-strings/&quot;&gt;f-string&lt;/a&gt; &lt;code&gt;f&quot;{ord(i):08b}&quot;&lt;/code&gt; uses Python&amp;rsquo;s &lt;a href=&quot;https://docs.python.org/3/library/string.html#formatspec&quot;&gt;Format Specification Mini-Language&lt;/a&gt;, which is a way of specifying formatting for replacement fields in format strings:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The left side of the colon, &lt;code&gt;ord(i)&lt;/code&gt;, is the actual object whose value will be formatted and inserted into the output.  Using &lt;code&gt;ord()&lt;/code&gt; gives you the base-10 code point for a single &lt;code&gt;str&lt;/code&gt; character.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The right hand side of the colon is the format specifier.  &lt;code&gt;08&lt;/code&gt; means &lt;em&gt;width 8, 0 padded&lt;/em&gt;, and the &lt;code&gt;b&lt;/code&gt; functions as a sign to output the resulting number in base 2 (binary).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This trick is mainly just for fun, and it will fail very badly for any character that you don&amp;rsquo;t see present in the ASCII table.  We&amp;rsquo;ll discuss how other encodings fix this problem later on. &lt;/p&gt;
&lt;h3 id=&quot;we-need-more-bits&quot;&gt;We Need More Bits!&lt;/h3&gt;
&lt;p&gt;There&amp;rsquo;s a critically important formula that&amp;rsquo;s related to the definition of a bit.  Given a number of bits, &lt;em&gt;n&lt;/em&gt;, the number of distinct possible values that can be represented in &lt;em&gt;n&lt;/em&gt; bits is &lt;em&gt;2&lt;sup&gt;n&lt;/sup&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;n_possible_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nbits&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s what that means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 bit will let you express &lt;em&gt;2&lt;sup&gt;1&lt;/sup&gt; == 2&lt;/em&gt; possible values.&lt;/li&gt;
&lt;li&gt;8 bits will let you express &lt;em&gt;2&lt;sup&gt;8&lt;/sup&gt; == 256&lt;/em&gt; possible values.&lt;/li&gt;
&lt;li&gt;64 bits will let you express &lt;em&gt;2&lt;sup&gt;64&lt;/sup&gt; == 18,446,744,073,709,551,616&lt;/em&gt; possible values.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&amp;rsquo;s a corollary to this formula: given a range of distinct possible values, how can we find the number of bits, &lt;em&gt;n&lt;/em&gt;, that is required for the range to be fully represented?  What you&amp;rsquo;re trying to solve for is &lt;em&gt;n&lt;/em&gt; in the equation &lt;em&gt;2&lt;sup&gt;n&lt;/sup&gt; = x&lt;/em&gt; (where you already know &lt;em&gt;x&lt;/em&gt;).  &lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what that works out to:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;math&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ceil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;n_bits_required&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvalues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ceil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nvalues&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_bits_required&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;256&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The reason that you need to use a ceiling in &lt;code&gt;n_bits_required()&lt;/code&gt; is to account for values that are not clean powers of 2.  Say you need to store a character set of 110 characters total.  Naively, this should take &lt;code&gt;log(110) / log(2) == 6.781&lt;/code&gt; bits, but there&amp;rsquo;s no such thing as 0.781 bits.  110 values will require 7 bits, not 6, with the final slots being unneeded:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_bits_required&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All of this serves to to prove one concept: ASCII is, strictly speaking, a 7-bit code.  The ASCII table that you saw above contains 128 code points and characters, 0 through 127 inclusive.  This requires 7 bits:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_bits_required&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 0 through 127&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n_possible_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;128&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The issue with this is that modern computers don&amp;rsquo;t store much of anything in 7-bit slots.  They traffic in units of 8 bits, conventionally known as a &lt;strong&gt;byte&lt;/strong&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Throughout this tutorial, I assume that a byte refers to 8 bits, as it has since the 1960s, rather than some other unit of storage.  You are free to call this an &lt;a href=&quot;https://en.wikipedia.org/wiki/Octet_(computing)&quot;&gt;&lt;em&gt;octet&lt;/em&gt;&lt;/a&gt; if you prefer.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;This means that the storage space used by ASCII is half-empty.  If it&amp;rsquo;s not clear why this is, think back to the decimal-to-binary table from above.  You &lt;em&gt;can&lt;/em&gt; express the numbers 0 and 1 with just 1 bit, or you can use 8 bits to express them as 00000000 and 00000001, respectively.&lt;/p&gt;
&lt;p&gt;You &lt;em&gt;can&lt;/em&gt; express the numbers 0 through 3 with just 2 bits, or 00 through 11, or you can use 8 bits to express them as 00000000, 00000001, 00000010, and 00000011, respectively.  The highest ASCII code point, 127, requires only 7 significant bits.&lt;/p&gt;
&lt;p&gt;Knowing this, you can see that &lt;code&gt;make_bitseq()&lt;/code&gt; converts ASCII strings into a &lt;code&gt;str&lt;/code&gt; representation of bytes, where every character consumes one byte:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_bitseq&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;bits&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;01100010 01101001 01110100 01110011&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;ASCII&amp;rsquo;s underutilization of the 8-bit bytes offered by modern computers led to a family of conflicting, informalized encodings that each specified additional characters to be used with the remaining 128 available code points allowed in an 8-bit character encoding scheme.&lt;/p&gt;
&lt;p&gt;Not only did these different encodings clash with each other, but each one of them was by itself still a grossly incomplete representation of the world&amp;rsquo;s characters, regardless of the fact that they made use of one additional bit.  &lt;/p&gt;
&lt;p&gt;Over the years, one character encoding mega-scheme came to rule them all.  However, before we get there, let&amp;rsquo;s talk for a minute about numbering systems, which are a fundamental underpinning of character encoding schemes.&lt;/p&gt;
&lt;h2 id=&quot;covering-all-the-bases-other-number-systems&quot;&gt;Covering All the Bases: Other Number Systems&lt;/h2&gt;
&lt;p&gt;In the discussion of ASCII above, you saw that each character maps to an integer in the range 0 through 127.&lt;/p&gt;
&lt;p&gt;This range of numbers is expressed in decimal (base 10).  It&amp;rsquo;s the way that you, me, and the rest of us humans are used to counting, for no reason more complicated than that we have 10 fingers.  &lt;/p&gt;
&lt;p&gt;But there are other numbering systems as well that are especially prevalent throughout the CPython source code.  While the &amp;ldquo;underlying number&amp;rdquo; is the same, all numbering systems are just different ways of expressing the same number.&lt;/p&gt;
&lt;p&gt;If I asked you what number the string &lt;code&gt;&quot;11&quot;&lt;/code&gt; represents, you&amp;rsquo;d be right to give me a strange look before answering that it represents eleven.&lt;/p&gt;
&lt;p&gt;However, this string representation can express different underlying numbers in different numbering systems.  In addition to decimal, the alternatives include the following common numbering systems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Binary&lt;/strong&gt;: base 2&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Octal&lt;/strong&gt;: base 8&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hexadecimal (hex)&lt;/strong&gt;: base 16&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But what does it mean for us to say that, in a certain numbering system, numbers are represented in base &lt;em&gt;N&lt;/em&gt;?&lt;/p&gt;
&lt;p&gt;Here is the best way that I know of to articulate what this means: it&amp;rsquo;s the number of fingers that you&amp;rsquo;d count on in that system.&lt;/p&gt;
&lt;p&gt;If you want a much fuller but still gentle introduction to numbering systems, Charles Petzold&amp;rsquo;s &lt;a href=&quot;https://realpython.com/asins/073560505X&quot;&gt;&lt;em&gt;Code&lt;/em&gt;&lt;/a&gt; is an incredibly cool book that explores the foundations of computer code in detail.&lt;/p&gt;
&lt;p&gt;One way to demonstrate how different numbering systems interpret the same thing is with Python&amp;rsquo;s &lt;code&gt;int()&lt;/code&gt; constructor.  If you pass a &lt;code&gt;str&lt;/code&gt; to &lt;code&gt;int()&lt;/code&gt;, Python will assume by default that the string expresses a number in base 10 unless you tell it otherwise:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;11&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;11&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 10 is already default&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;11&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Binary&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;11&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Octal&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;11&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Hex&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;17&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There&amp;rsquo;s a more common way of telling Python that your integer is typed in a base other than 10.  Python accepts &lt;strong&gt;literal&lt;/strong&gt; forms of each of the 3 alternative numbering systems above:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type of Literal&lt;/th&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;n/a&lt;/td&gt;
&lt;td&gt;&lt;code&gt;11&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Binary literal&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b&lt;/code&gt; or &lt;code&gt;0B&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b11&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Octal literal&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o&lt;/code&gt; or &lt;code&gt;0O&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o11&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hex literal&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x&lt;/code&gt; or &lt;code&gt;0X&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x11&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;All of these are sub-forms of &lt;strong&gt;integer literals&lt;/strong&gt;.  You can see that these produce the same results, respectively, as the calls to &lt;code&gt;int()&lt;/code&gt; with non-default &lt;code&gt;base&lt;/code&gt; values.  They&amp;rsquo;re all just &lt;code&gt;int&lt;/code&gt; to Python:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;11&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mb&quot;&gt;0b11&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Binary literal&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mo&quot;&gt;0o11&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Octal literal&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;9&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x11&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Hex literal&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;17&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s how you could type the binary, octal, and hexadecimal equivalents of the decimal numbers 0 through 20. Any of these are perfectly valid in a Python interpreter shell or source code, and all work out to be of type &lt;code&gt;int&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decimal&lt;/th&gt;
&lt;th&gt;Binary&lt;/th&gt;
&lt;th&gt;Octal&lt;/th&gt;
&lt;th&gt;Hex&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x0&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x1&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o2&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b11&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x3&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b100&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x4&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b101&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x5&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b110&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o6&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x6&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;7&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b111&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o7&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x7&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;8&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b1000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x8&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;9&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b1001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o11&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x9&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;10&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b1010&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o12&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xa&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;11&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b1011&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o13&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xb&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;12&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b1100&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o14&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xc&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;13&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b1101&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o15&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xd&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;14&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b1110&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o16&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xe&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;15&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b1111&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o17&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xf&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;16&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b10000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o20&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x10&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;17&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b10001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o21&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x11&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;18&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b10010&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o22&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x12&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;19&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b10011&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o23&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x13&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;20&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0b10100&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0o24&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x14&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardf4d199&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsef4d199&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsef4d199&quot;&gt;Integer Literals in CPython Source&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsef4d199&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsef4d199&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapsef4d199&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardf4d199&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;It&amp;rsquo;s amazing just how prevalent these expressions are in the Python Standard Library.  If you want to see for yourself, navigate to wherever your &lt;code&gt;lib/python3.7/&lt;/code&gt; directory sits, and check out the use of hex literals like this:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; grep -nri --include &lt;span class=&quot;s2&quot;&gt;&amp;quot;*\.py&amp;quot;&lt;/span&gt; -e &lt;span class=&quot;s2&quot;&gt;&amp;quot;\b0x&amp;quot;&lt;/span&gt; lib/python3.7
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This should work on any Unix system that has &lt;code&gt;grep&lt;/code&gt;.  You could use &lt;code&gt;&quot;\b0o&quot;&lt;/code&gt; to search for octal literals or &amp;ldquo;\b0b&amp;rdquo; to search for binary literals.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;What&amp;rsquo;s the argument for using these alternate &lt;code&gt;int&lt;/code&gt; literal syntaxes?  In short, it&amp;rsquo;s because 2, 8, and 16 are all powers of 2, while 10 is not.  These three alternate number systems occasionally offer a way for expressing values in a computer-friendly manner.  For example, the number 65536 or &lt;em&gt;2&lt;sup&gt;16&lt;/sup&gt;&lt;/em&gt;, is just 10000 in hexadecimal, or &lt;code&gt;0x10000&lt;/code&gt; as a Python hexadecimal literal.&lt;/p&gt;
&lt;h2 id=&quot;enter-unicode&quot;&gt;Enter Unicode&lt;/h2&gt;
&lt;p&gt;As you saw, the problem with ASCII is that it&amp;rsquo;s not nearly a big enough set of characters to accommodate the world&amp;rsquo;s set of languages, dialects, symbols, and glyphs.  (It&amp;rsquo;s &lt;a href=&quot;https://en.wikipedia.org/wiki/English_terms_with_diacritical_marks&quot;&gt;not even big enough for English alone&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;Unicode fundamentally serves the same purpose as ASCII, but it just encompasses a way, way, &lt;em&gt;way&lt;/em&gt; bigger set of code points.  There are a handful of encodings that emerged chronologically between ASCII and Unicode, but they are not really worth mentioning just yet because Unicode and one of its encoding schemes, UTF-8, has become so predominantly used.&lt;/p&gt;
&lt;p&gt;Think of Unicode as a massive version of the ASCII table&amp;mdash;one that has 1,114,112 possible code points.  That&amp;rsquo;s 0 through 1,114,111, or 0 through &lt;em&gt;17 * (2&lt;sup&gt;16&lt;/sup&gt;) - 1&lt;/em&gt;, or &lt;code&gt;0x10ffff&lt;/code&gt; hexadecimal.  In fact, ASCII is a perfect subset of Unicode.  The first 128 characters in the Unicode table correspond precisely to the ASCII characters that you&amp;rsquo;d reasonably expect them to.&lt;/p&gt;
&lt;p&gt;In the interest of being technically exacting, &lt;strong&gt;Unicode itself is &lt;em&gt;not&lt;/em&gt; an encoding&lt;/strong&gt;.  Rather, Unicode is &lt;strong&gt;implemented&lt;/strong&gt; by different character encodings, which you&amp;rsquo;ll see soon.  Unicode is better thought of as a map (something like a &lt;code&gt;dict&lt;/code&gt;) or a 2-column database table.  It maps characters (like &lt;code&gt;&quot;a&quot;&lt;/code&gt;, &lt;code&gt;&quot;¢&quot;&lt;/code&gt;, or even &lt;code&gt;&quot;ቈ&quot;&lt;/code&gt;) to distinct, positive integers.  A character encoding needs to offer a bit more.&lt;/p&gt;
&lt;p&gt;Unicode contains virtually every character that you can imagine, including additional non-printable ones too.  One of my favorites is the pesky right-to-left mark, which has code point 8207 and is used in text with both left-to-right and right-to-left language scripts, such as an article containing both English and Arabic paragraphs.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The world of character encodings is one of many fine-grained technical details over which some people love to nitpick about.  One such detail is that only 1,111,998 of the Unicode code points are actually usable, due to &lt;a href=&quot;https://www.quora.com/How-do-you-determine-how-many-characters-Unicode-can-store&quot;&gt;a couple of archaic reasons&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;unicode-vs-utf-8&quot;&gt;Unicode vs UTF-8&lt;/h3&gt;
&lt;p&gt;It didn&amp;rsquo;t take long for people to realize that all of the world&amp;rsquo;s characters could not be packed into one byte each.  It&amp;rsquo;s evident from this that modern, more comprehensive encodings would need to use multiple bytes to encode some characters.&lt;/p&gt;
&lt;p&gt;You also saw above that Unicode is not technically a full-blown character encoding.  Why is that?&lt;/p&gt;
&lt;p&gt;There is one thing that Unicode doesn&amp;rsquo;t tell you: it doesn&amp;rsquo;t tell you how to get actual bits from text&amp;mdash;just code points.  It doesn&amp;rsquo;t tell you enough about how to convert text to binary data and vice versa.  &lt;/p&gt;
&lt;p&gt;Unicode is an abstract encoding standard, not an encoding.  That&amp;rsquo;s where UTF-8 and other encoding schemes come into play.  The Unicode standard (a map of characters to code points) defines several different encodings from its single character set.&lt;/p&gt;
&lt;p&gt;UTF-8 as well as its lesser-used cousins, UTF-16 and UTF-32, are encoding formats for representing Unicode characters as binary data of one or more bytes per character.  We&amp;rsquo;ll discuss UTF-16 and UTF-32 in a moment, but UTF-8 has taken the largest share of the pie by far.&lt;/p&gt;
&lt;p&gt;That brings us to a definition that is long overdue.  What does it mean, formally, to &lt;strong&gt;encode&lt;/strong&gt; and &lt;strong&gt;decode&lt;/strong&gt;?&lt;/p&gt;
&lt;h3 id=&quot;encoding-and-decoding-in-python-3&quot;&gt;Encoding and Decoding in Python 3&lt;/h3&gt;
&lt;p&gt;Python 3&amp;rsquo;s &lt;code&gt;str&lt;/code&gt; type is meant to represent human-readable text and can contain any Unicode character.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;bytes&lt;/code&gt; type, conversely, represents binary data, or sequences of raw bytes, that do not intrinsically have an encoding attached to it.&lt;/p&gt;
&lt;p&gt;Encoding and decoding is the process of going from one to the other:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/encode-decode.3e665ad9b455.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-66&quot; src=&quot;https://files.realpython.com/media/encode-decode.3e665ad9b455.png&quot; width=&quot;903&quot; height=&quot;483&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/encode-decode.3e665ad9b455.png&amp;amp;w=225&amp;amp;sig=8c71ee012d841138b1fe6aa879b87b41289e03c9 225w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/encode-decode.3e665ad9b455.png&amp;amp;w=451&amp;amp;sig=e5fa9f52aaedc7dad445049ac254948b685eedac 451w, https://files.realpython.com/media/encode-decode.3e665ad9b455.png 903w&quot; sizes=&quot;75vw&quot; alt=&quot;Encode versus decode&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Encoding vs decoding (Image: Real Python)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;In &lt;code&gt;.encode()&lt;/code&gt; and &lt;code&gt;.decode()&lt;/code&gt;, the &lt;code&gt;encoding&lt;/code&gt; parameter is &lt;code&gt;&quot;utf-8&quot;&lt;/code&gt; by default, though it&amp;rsquo;s generally safer and more unambiguous to specify it:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;résumé&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;r\xc3\xa9sum\xc3\xa9&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;El Niño&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;El Ni\xc3\xb1o&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;r&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xc3\xa9&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xc3\xa9&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;résumé&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;El Ni&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xc3\xb1&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;o&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;El Niño&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The results of &lt;code&gt;str.encode()&lt;/code&gt; is a &lt;a href=&quot;https://docs.python.org/3/library/stdtypes.html#bytes-objects&quot;&gt;&lt;code&gt;bytes&lt;/code&gt;&lt;/a&gt; object.  Both bytes literals (such as &lt;code&gt;b&quot;r\xc3\xa9sum\xc3\xa9&quot;&lt;/code&gt;) and the representations of bytes permit only ASCII characters.&lt;/p&gt;
&lt;p&gt;This is why, when calling &lt;code&gt;&quot;El Niño&quot;.encode(&quot;utf-8&quot;)&lt;/code&gt;, the ASCII-compatible &lt;code&gt;&quot;El&quot;&lt;/code&gt; is allowed to be represented as it is, but the &lt;em&gt;n&lt;/em&gt; with tilde is escaped to &lt;code&gt;&quot;\xc3\xb1&quot;&lt;/code&gt;.  That messy-looking sequence represents two bytes, &lt;code&gt;0xc3&lt;/code&gt; and &lt;code&gt;0xb1&lt;/code&gt; in hex:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{i:08b}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xc3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xb1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;11000011 10110001&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That is, &lt;a href=&quot;https://unicode-table.com/en/00F1/&quot;&gt;the character &lt;code&gt;ñ&lt;/code&gt;&lt;/a&gt; requires two bytes for its binary representation under UTF-8.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you type &lt;code&gt;help(str.encode)&lt;/code&gt;, you&amp;rsquo;ll probably see a default of &lt;code&gt;encoding=&#39;utf-8&#39;&lt;/code&gt;.  Be careful about excluding this and just using &lt;code&gt;&quot;résumé&quot;.encode()&lt;/code&gt;, because the default &lt;a href=&quot;https://docs.python.org/3/whatsnew/3.6.html#pep-528-change-windows-console-encoding-to-utf-8&quot;&gt;may be different&lt;/a&gt; in Windows prior to Python 3.6.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;python-3-all-in-on-unicode&quot;&gt;Python 3: All-In on Unicode&lt;/h3&gt;
&lt;p&gt;Python 3 is all-in on Unicode and UTF-8 specifically.  Here&amp;rsquo;s what that means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Python 3 source code is assumed to be UTF-8 by default.  This means that you don&amp;rsquo;t need &lt;code&gt;# -*- coding: UTF-8 -*-&lt;/code&gt; at the top of &lt;code&gt;.py&lt;/code&gt; files in Python 3.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;All text (&lt;code&gt;str&lt;/code&gt;) is Unicode by default.  Encoded Unicode text is represented as binary data (&lt;code&gt;bytes&lt;/code&gt;).  The &lt;code&gt;str&lt;/code&gt; type can contain any literal Unicode character, such as &lt;code&gt;&quot;Δv / Δt&quot;&lt;/code&gt;, all of which will be stored as Unicode.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Anything from the Unicode character set is kosher in identifiers, meaning &lt;code&gt;résumé = &quot;~/Documents/resume.pdf&quot;&lt;/code&gt; is valid if this strikes your fancy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Python&amp;rsquo;s &lt;a href=&quot;https://docs.python.org/3/library/re.html&quot;&gt;&lt;code&gt;re&lt;/code&gt; module&lt;/a&gt; defaults to the &lt;code&gt;re.UNICODE&lt;/code&gt; flag rather than &lt;code&gt;re.ASCII&lt;/code&gt;.  This means, for instance, that &lt;code&gt;r&quot;\w&quot;&lt;/code&gt; matches Unicode word characters, not just ASCII letters.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The default &lt;code&gt;encoding&lt;/code&gt; in &lt;code&gt;str.encode()&lt;/code&gt; and &lt;code&gt;bytes.decode()&lt;/code&gt; is UTF-8.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There is one other property that is more nuanced, which is that the default &lt;code&gt;encoding&lt;/code&gt; to the built-in &lt;code&gt;open()&lt;/code&gt; is platform-dependent and depends on the value of &lt;code&gt;locale.getpreferredencoding()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Mac OS X High Sierra&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;locale&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getpreferredencoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;UTF-8&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Windows Server 2012; other Windows builds may use UTF-16&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;locale&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locale&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getpreferredencoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;cp1252&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Again, the lesson here is to be careful about making assumptions when it comes to the universality of UTF-8, even if it is the predominant encoding.  It never hurts to be explicit in your code.&lt;/p&gt;
&lt;h3 id=&quot;one-byte-two-bytes-three-bytes-four&quot;&gt;One Byte, Two Bytes, Three Bytes, Four&lt;/h3&gt;
&lt;p&gt;A crucial feature is that UTF-8 is a &lt;strong&gt;variable-length encoding&lt;/strong&gt;.  It&amp;rsquo;s tempting to gloss over what this means, but it&amp;rsquo;s worth delving into.&lt;/p&gt;
&lt;p&gt;Think back to the section on ASCII.  Everything in extended-ASCII-land demands at most one byte of space.  You can quickly prove this with the following generator expression:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;all&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ascii&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;UTF-8 is quite different.  A given Unicode character can occupy anywhere from one to four bytes.  Here&amp;rsquo;s an example of a single Unicode character taking up four bytes:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ibrow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;🤨&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ibrow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ibrow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;\xf0\x9f\xa4\xa8&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ibrow&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Calling list() on a bytes object gives you&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# the decimal value for each byte&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xf0\x9f\xa4\xa8&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[240, 159, 164, 168]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is a subtle but important feature of &lt;code&gt;len()&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The length of a single Unicode character as a Python &lt;code&gt;str&lt;/code&gt; will &lt;em&gt;always&lt;/em&gt; be 1, no matter how many bytes it occupies.&lt;/li&gt;
&lt;li&gt;The length of the same character encoded to &lt;code&gt;bytes&lt;/code&gt; will be anywhere between 1 and 4.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The table below summarizes what general types of characters fit into each byte-length bucket:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decimal Range&lt;/th&gt;
&lt;th&gt;Hex Range&lt;/th&gt;
&lt;th&gt;What&amp;rsquo;s Included&lt;/th&gt;
&lt;th&gt;Examples&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;0 to 127&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;\u0000&quot;&lt;/code&gt; to &lt;code&gt;&quot;\u007F&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;U.S. ASCII&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;A&quot;&lt;/code&gt;, &lt;code&gt;&quot;\n&quot;&lt;/code&gt;, &lt;code&gt;&quot;7&quot;&lt;/code&gt;, &lt;code&gt;&quot;&amp;amp;&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;128 to 2047&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;\u0080&quot;&lt;/code&gt; to &lt;code&gt;&quot;\u07FF&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Most Latinic alphabets*&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;ę&quot;&lt;/code&gt;, &lt;code&gt;&quot;±&quot;&lt;/code&gt;, &lt;code&gt;&quot;ƌ&quot;&lt;/code&gt;, &lt;code&gt;&quot;ñ&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2048 to 65535&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;\u0800&quot;&lt;/code&gt; to &lt;code&gt;&quot;\uFFFF&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Additional parts of the multilingual plane (BMP)**&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;ത&quot;&lt;/code&gt;, &lt;code&gt;&quot;ᄇ&quot;&lt;/code&gt;, &lt;code&gt;&quot;ᮈ&quot;&lt;/code&gt;, &lt;code&gt;&quot;‰&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;65536 to 1114111&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;\U00010000&quot;&lt;/code&gt; to &lt;code&gt;&quot;\U0010FFFF&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Other***&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;𝕂&quot;&lt;/code&gt;, &lt;code&gt;&quot;𐀀&quot;&lt;/code&gt;, &lt;code&gt;&quot;😓&quot;&lt;/code&gt;, &lt;code&gt;&quot;🂲&quot;&lt;/code&gt;,&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;&lt;sub&gt;*Such as English, Arabic, Greek, and Irish&lt;/sub&gt;&lt;br&gt;
&lt;sub&gt;**A huge array of languages and symbols&amp;mdash;mostly Chinese, Japanese, and Korean by volume (also ASCII and Latin alphabets)&lt;/sub&gt;&lt;br&gt;
&lt;sub&gt;***Additional Chinese, Japanese, Korean, and Vietnamese characters, plus more symbols and emojis&lt;/sub&gt;&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: In the interest of not losing sight of the big picture, there is an additional set of technical features of UTF-8 that aren&amp;rsquo;t covered here because they are rarely visible to a Python user.  &lt;/p&gt;
&lt;p&gt;For instance, UTF-8 actually uses prefix codes that indicate the number of bytes in a sequence.  This enables a decoder to tell what bytes belong together in a variable-length encoding, and lets the first byte serve as an indicator of the number of bytes in the coming sequence.&lt;/p&gt;
&lt;p&gt;Wikipedia&amp;rsquo;s &lt;a href=&quot;https://en.wikipedia.org/wiki/UTF-8&quot;&gt;UTF-8&lt;/a&gt; article does not shy away from technical detail, and there is always the official &lt;a href=&quot;http://www.unicode.org/versions/latest/&quot;&gt;Unicode Standard&lt;/a&gt; for your reading enjoyment as well.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;what-about-utf-16-and-utf-32&quot;&gt;What About UTF-16 and UTF-32?&lt;/h3&gt;
&lt;p&gt;Let&amp;rsquo;s get back to two other encoding variants, UTF-16 and UTF-32.&lt;/p&gt;
&lt;p&gt;The difference between these and UTF-8 is substantial in practice.  Here&amp;rsquo;s an example of how major the difference is with a round-trip conversion:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;letters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;αβγδ&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawdata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;letters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawdata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;αβγδ&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rawdata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-16&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 😧&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;뇎닎돎듎&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case, encoding four Greek letters with UTF-8 and then decoding back to text in UTF-16 would produce a text &lt;code&gt;str&lt;/code&gt; that is in a completely different language (Korean).  &lt;/p&gt;
&lt;p&gt;Glaringly wrong results like this are possible when the same encoding isn&amp;rsquo;t used bidirectionally.  Two variations of decoding the same &lt;code&gt;bytes&lt;/code&gt; object may produce results that aren&amp;rsquo;t even in the same language.&lt;/p&gt;
&lt;p&gt;This table summarizes the range or number of bytes under UTF-8, UTF-16, and UTF-32:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Encoding&lt;/th&gt;
&lt;th&gt;Bytes Per Character (Inclusive)&lt;/th&gt;
&lt;th&gt;Variable Length&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;UTF-8&lt;/td&gt;
&lt;td&gt;1 to 4&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UTF-16&lt;/td&gt;
&lt;td&gt;2 to 4&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UTF-32&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;One other curious aspect of the UTF family is that UTF-8 will not &lt;em&gt;always&lt;/em&gt; take up less space than UTF-16.  That may seem mathematically counterintuitive, but it&amp;rsquo;s quite possible:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;記者 鄭啟源 羅智堅&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;26&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-16&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;22&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The reason for this is that the code points in the range &lt;code&gt;U+0800&lt;/code&gt; through &lt;code&gt;U+FFFF&lt;/code&gt; (2048 through 65535 in decimal) take up three bytes in UTF-8 versus only two in UTF-16.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not by any means recommending that you jump aboard the UTF-16 train, regardless of whether or not you operate in a language whose characters are commonly in this range.  Among other reasons, one of the strong arguments for using UTF-8 is that, in the world of encoding, it&amp;rsquo;s &lt;a href=&quot;https://en.wikipedia.org/wiki/UTF-8#/media/File:Utf8webgrowth.svg&quot;&gt;a great idea to blend in with the crowd&lt;/a&gt;.  &lt;/p&gt;
&lt;p&gt;Not to mention, it&amp;rsquo;s 2019: computer memory is cheap, so saving 4 bytes by going out of your way to use UTF-16 is arguably not worth it.&lt;/p&gt;
&lt;h2 id=&quot;pythons-built-in-functions&quot;&gt;Python&amp;rsquo;s Built-In Functions&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ve made it through the hard part.  Time to use what you&amp;rsquo;ve seen thus far in Python.&lt;/p&gt;
&lt;p&gt;Python has a group of built-in functions that relate in some way to numbering systems and character encoding:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#ascii&quot;&gt;&lt;code&gt;ascii()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#bin&quot;&gt;&lt;code&gt;bin()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#bytes&quot;&gt;&lt;code&gt;bytes()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#chr&quot;&gt;&lt;code&gt;chr()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#hex&quot;&gt;&lt;code&gt;hex()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#int&quot;&gt;&lt;code&gt;int()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#oct&quot;&gt;&lt;code&gt;oct()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#ord&quot;&gt;&lt;code&gt;ord()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/functions.html#str&quot;&gt;&lt;code&gt;str()&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These can be logically grouped together based on their purpose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;ascii()&lt;/code&gt;, &lt;code&gt;bin()&lt;/code&gt;, &lt;code&gt;hex()&lt;/code&gt;, and &lt;code&gt;oct()&lt;/code&gt;&lt;/strong&gt; are for obtaining a different representation of an input.  Each one produces a &lt;code&gt;str&lt;/code&gt;.  The first, &lt;code&gt;ascii()&lt;/code&gt;, produces an ASCII only representation of an object, with non-ASCII characters escaped.  The remaining three give binary, hexadecimal, and octal representations of an integer, respectively.  These are only &lt;em&gt;representations&lt;/em&gt;, not a fundamental change in the input.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;bytes()&lt;/code&gt;, &lt;code&gt;str()&lt;/code&gt;, and &lt;code&gt;int()&lt;/code&gt;&lt;/strong&gt; are class constructors for their respective types, &lt;code&gt;bytes&lt;/code&gt;, &lt;code&gt;str&lt;/code&gt;, and &lt;code&gt;int&lt;/code&gt;.  They each offer ways of coercing the input into the desired type.  For instance, as you saw earlier, while &lt;code&gt;int(11.0)&lt;/code&gt; is probably more common, you might also see &lt;code&gt;int(&#39;11&#39;, base=16)&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;ord()&lt;/code&gt; and &lt;code&gt;chr()&lt;/code&gt;&lt;/strong&gt; are inverses of each other in that &lt;code&gt;ord()&lt;/code&gt; converts a &lt;code&gt;str&lt;/code&gt; character to its base-10 code point, while &lt;code&gt;chr()&lt;/code&gt; does the opposite.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s a more detailed look at each of these nine functions:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Signature&lt;/th&gt;
&lt;th&gt;Accepts&lt;/th&gt;
&lt;th&gt;Return Type&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ascii()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ascii(obj)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ASCII only representation of an object, with non-ASCII characters escaped&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bin()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bin(number)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number: int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Binary representation of an integer, with the prefix &lt;code&gt;&quot;0b&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bytes()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bytes(iterable_of_ints)&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;code&gt;bytes(s, enc[, errors])&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;code&gt;bytes(bytes_or_buffer)&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;code&gt;bytes([i])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bytes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Coerce (convert) the input to &lt;code&gt;bytes&lt;/code&gt;, raw binary data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;chr()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;chr(i)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;i: int&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;code&gt;i&amp;gt;=0&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;code&gt;i&amp;lt;=1114111&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Convert an integer code point to a single Unicode character&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hex()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;hex(number)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number: int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Hexadecimal representation of an integer, with the prefix &lt;code&gt;&quot;0x&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;int()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int([x])&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;code&gt;int(x, base=10)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Coerce (convert) the input to &lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;oct()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;oct(number)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;number: int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Octal representation of an integer, with the prefix &lt;code&gt;&quot;0o&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ord()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ord(c)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;c: str&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;code&gt;len(c) == 1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Convert a single Unicode character to its integer code point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;str()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str(object=&amp;rsquo;&amp;lsquo;)&lt;/code&gt;&lt;br&gt;&lt;br&gt;&lt;code&gt;str(b[, enc[, errors]])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Varies&lt;/td&gt;
&lt;td&gt;&lt;code&gt;str&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Coerce (convert) the input to &lt;code&gt;str&lt;/code&gt;, text&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;You can expand the section below to see some examples of each function.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardd3a91c&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsed3a91c&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsed3a91c&quot;&gt;Examples: ascii()&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsed3a91c&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsed3a91c&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapsed3a91c&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardd3a91c&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;&lt;code&gt;ascii()&lt;/code&gt; gives you an ASCII-only representation of an object, with non-ASCII characters escaped:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ascii&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;abcdefg&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;quot;&amp;#39;abcdefg&amp;#39;&amp;quot;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ascii&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;jalepeño&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;quot;&amp;#39;jalepe\\xf1o&amp;#39;&amp;quot;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ascii&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;(1, 2, 3)&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ascii&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xc0ffee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Hex literal (int)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;12648430&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardfaeab5&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsefaeab5&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsefaeab5&quot;&gt;Examples: bin()&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsefaeab5&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsefaeab5&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapsefaeab5&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardfaeab5&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;&lt;code&gt;bin()&lt;/code&gt; gives you a binary representation of an integer, with the prefix &lt;code&gt;&quot;0b&quot;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;0b0&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;0b110010000&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xc0ffee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Hex literal (int)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;0b110000001111111111101110&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# `int` + list comprehension&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;0b1&amp;#39;, &amp;#39;0b10&amp;#39;, &amp;#39;0b100&amp;#39;, &amp;#39;0b1000&amp;#39;, &amp;#39;0b10000&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card3ee439&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse3ee439&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse3ee439&quot;&gt;Examples: bytes()&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse3ee439&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse3ee439&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse3ee439&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card3ee439&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;&lt;code&gt;bytes()&lt;/code&gt; coerces the input to &lt;code&gt;bytes&lt;/code&gt;, representing raw binary data:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Iterable of ints&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;104&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;101&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;108&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;108&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;111&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;119&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;111&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;114&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;108&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;hello world&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;97&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Iterable of ints&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;abcdefghijklmnopqrstuvwxyz&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;real 🐍&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# String + encoding&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;real \xf0\x9f\x90\x8d&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromhex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;c0 ff ee&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;\xc0\xff\xee&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromhex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;72 65 61 6c 70 79 74 68 6f 6e&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;realpython&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card3ba718&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse3ba718&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse3ba718&quot;&gt;Examples: chr()&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse3ba718&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse3ba718&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse3ba718&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card3ba718&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;&lt;code&gt;chr()&lt;/code&gt; converts an integer code point to a single Unicode character:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;97&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;a&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7048&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;ᮈ&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1114111&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;\U0010ffff&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x10FFFF&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Hex literal (int)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;\U0010ffff&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mb&quot;&gt;0b01100100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Binary literal (int)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;d&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card4b834e&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse4b834e&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse4b834e&quot;&gt;Examples: hex()&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse4b834e&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse4b834e&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse4b834e&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card4b834e&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;&lt;code&gt;hex()&lt;/code&gt; gives the hexadecimal representation of an integer, with the prefix &lt;code&gt;&quot;0x&quot;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;0x64&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;0x1&amp;#39;, &amp;#39;0x2&amp;#39;, &amp;#39;0x4&amp;#39;, &amp;#39;0x8&amp;#39;, &amp;#39;0x10&amp;#39;]&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;0x0&amp;#39;, &amp;#39;0x1&amp;#39;, &amp;#39;0x2&amp;#39;, &amp;#39;0x3&amp;#39;, &amp;#39;0x4&amp;#39;, &amp;#39;0x5&amp;#39;, &amp;#39;0x6&amp;#39;, &amp;#39;0x7&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;0x8&amp;#39;, &amp;#39;0x9&amp;#39;, &amp;#39;0xa&amp;#39;, &amp;#39;0xb&amp;#39;, &amp;#39;0xc&amp;#39;, &amp;#39;0xd&amp;#39;, &amp;#39;0xe&amp;#39;, &amp;#39;0xf&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card1d2cf4&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse1d2cf4&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse1d2cf4&quot;&gt;Examples: int()&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse1d2cf4&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse1d2cf4&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse1d2cf4&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card1d2cf4&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;&lt;code&gt;int()&lt;/code&gt; coerces the input to &lt;code&gt;int&lt;/code&gt;, optionally interpreting the input in a given base:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;11.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;11&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;11&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;11&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;11&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;11&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;9&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;11&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;17&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xc0ffee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;12648429&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x0f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;little&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;15&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xc0\xff\xee&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;big&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;12648430&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_carde7f403&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsee7f403&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsee7f403&quot;&gt;Examples: ord()&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsee7f403&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsee7f403&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapsee7f403&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_carde7f403&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;&lt;code&gt;ord()&lt;/code&gt; converts a single Unicode character to its integer code point:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;97&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ę&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;281&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ᮈ&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;7048&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hello world&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card0d358d&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse0d358d&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse0d358d&quot;&gt;Examples: str()&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse0d358d&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse0d358d&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse0d358d&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card0d358d&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;&lt;code&gt;str()&lt;/code&gt; coerces the input to &lt;code&gt;str&lt;/code&gt;, representing text:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;str of string&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;str of string&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;5&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Like [1, 2, 3, 4].__str__(), but use str()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;[1, 2, 3, 4]&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xc2\xbc&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; cup of flour&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;¼ cup of flour&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0xc0ffee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;12648430&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h2 id=&quot;python-string-literals-ways-to-skin-a-cat&quot;&gt;Python String Literals: Ways to Skin a Cat&lt;/h2&gt;
&lt;p&gt;Rather than using the &lt;code&gt;str()&lt;/code&gt; constructor, it&amp;rsquo;s commonplace to type a &lt;code&gt;str&lt;/code&gt; literally:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;meal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;shrimp and grits&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That may seem easy enough.  But the interesting side of things is that, because Python 3 is Unicode-centric through and through, you can &amp;ldquo;type&amp;rdquo; Unicode characters that you probably won&amp;rsquo;t even find on your keyboard.  You can copy and paste this right into a Python 3 interpreter shell:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alphabet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;αβγδεζηθικλμνξοπρςστυφχψ&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alphabet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;αβγδεζηθικλμνξοπρςστυφχψ&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Besides placing the actual, unescaped Unicode characters in the console, there are other ways to type Unicode strings as well.&lt;/p&gt;
&lt;p&gt;One of the densest sections of Python&amp;rsquo;s documentation is the portion on lexical analysis, specifically the section on &lt;a href=&quot;https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals&quot;&gt;string and bytes literals&lt;/a&gt;.  Personally, I had to read this section about one, two, or maybe nine times for it to really sink in.&lt;/p&gt;
&lt;p&gt;Part of what it says is that there are up to six ways that Python will allow you to type the same Unicode character.&lt;/p&gt;
&lt;p&gt;The first and most common way is to type the character itself literally, as you&amp;rsquo;ve already seen.  The tough part with this method is finding the actual keystrokes.  That&amp;rsquo;s where the other methods for getting and representing characters come into play.  Here&amp;rsquo;s the full list:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Escape Sequence&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;How To Express &lt;code&gt;&quot;a&quot;&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&quot;\ooo&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Character with octal value &lt;code&gt;ooo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;\141&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&quot;\xhh&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Character with hex value &lt;code&gt;hh&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;\x61&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&quot;\N{name}&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Character named &lt;code&gt;name&lt;/code&gt; in the Unicode database&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;\N{LATIN SMALL LETTER A}&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&quot;\uxxxx&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Character with 16-bit (2-byte) hex value &lt;code&gt;xxxx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;\u0061&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&quot;\Uxxxxxxxx&quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Character with 32-bit (4-byte) hex value &lt;code&gt;xxxxxxxx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&quot;\U00000061&quot;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;Here&amp;rsquo;s some proof and validation of the above:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;a&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x61&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; 
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\N{LATIN SMALL LETTER A}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\u0061&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\U00000061&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, there are two main caveats:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Not all of these forms work for all characters.  The hex representation of the integer 300 is &lt;code&gt;0x012c&lt;/code&gt;, which simply isn&amp;rsquo;t going to fit into the 2-hex-digit escape code &lt;code&gt;&quot;\xhh&quot;&lt;/code&gt;.  The highest code point that you can squeeze into this escape sequence is &lt;code&gt;&quot;\xff&quot;&lt;/code&gt; (&lt;code&gt;&quot;ÿ&quot;&lt;/code&gt;).  Similarly for &lt;code&gt;&quot;\ooo&quot;&lt;/code&gt;, it will only work up to &lt;code&gt;&quot;\777&quot;&lt;/code&gt; (&lt;code&gt;&quot;ǿ&quot;&lt;/code&gt;).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;For &lt;code&gt;\xhh&lt;/code&gt;, &lt;code&gt;\uxxxx&lt;/code&gt;, and &lt;code&gt;\Uxxxxxxxx&lt;/code&gt;, exactly as many digits are required as are shown in these examples.  This can throw you for a loop because of the way that Unicode tables conventionally display the codes for characters, with a leading &lt;code&gt;U+&lt;/code&gt; and variable number of hex characters.  They key is that Unicode tables most often do not zero-pad these codes.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For instance, if you consult &lt;a href=&quot;https://unicode-table.com/en/10336&quot;&gt;unicode-table.com&lt;/a&gt; for information on the Gothic letter faihu (or fehu), &lt;code&gt;&quot;𐍆&quot;&lt;/code&gt;, you&amp;rsquo;ll see that it is listed as having the code &lt;code&gt;U+10346&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;How do you put this into &lt;code&gt;&quot;\uxxxx&quot;&lt;/code&gt; or &lt;code&gt;&quot;\Uxxxxxxxx&quot;&lt;/code&gt;?  Well, you can&amp;rsquo;t fit it in &lt;code&gt;&quot;\uxxxx&quot;&lt;/code&gt; because it&amp;rsquo;s a 4-byte character, and to use &lt;code&gt;&quot;\Uxxxxxxxx&quot;&lt;/code&gt; to represent this character, you&amp;rsquo;ll need to left-pad the sequence:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\U00010346&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;𐍆&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This also means that the &lt;code&gt;&quot;\Uxxxxxxxx&quot;&lt;/code&gt; form is the only escape sequence that is capable of holding &lt;em&gt;any&lt;/em&gt; Unicode character.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: Here&amp;rsquo;s a short function to convert strings that look like &lt;code&gt;&quot;U+10346&quot;&lt;/code&gt; into something Python can work with.  It uses &lt;code&gt;str.zfill()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;make_uchr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lstrip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;U+&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;zfill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_uchr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;U+10346&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;𐍆&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;make_uchr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;U+0026&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;&amp;amp;&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;h2 id=&quot;other-encodings-available-in-python&quot;&gt;Other Encodings Available in Python&lt;/h2&gt;
&lt;p&gt;So far, you&amp;rsquo;ve seen four character encodings:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;ASCII&lt;/li&gt;
&lt;li&gt;UTF-8&lt;/li&gt;
&lt;li&gt;UTF-16&lt;/li&gt;
&lt;li&gt;UTF-32&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There are a ton of other ones out there.&lt;/p&gt;
&lt;p&gt;One example is Latin-1 (also called ISO-8859-1), which is technically the default for the Hypertext Transfer Protocol (HTTP), per &lt;a href=&quot;https://tools.ietf.org/html/rfc2616#section-3.7.1&quot;&gt;RFC 2616&lt;/a&gt;.  Windows has its own Latin-1 variant called cp1252.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: ISO-8859-1 is still very much present out in the wild.  The &lt;a href=&quot;https://realpython.com/python-requests/&quot;&gt;&lt;code&gt;requests&lt;/code&gt;&lt;/a&gt; library follows RFC 2616 &amp;ldquo;to the letter&amp;rdquo; in using it as the default encoding for the content of an HTTP/HTTPS response.  If the word &amp;ldquo;text&amp;rdquo; is found in the &lt;code&gt;Content-Type&lt;/code&gt; header, and no other encoding is specified, then &lt;code&gt;requests&lt;/code&gt; &lt;a href=&quot;https://github.com/kennethreitz/requests/blob/75bdc998e2d430a35d869b2abf1779bd0d34890e/requests/utils.py#L473&quot;&gt;will use ISO-8859-1&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.python.org/3/library/codecs.html#standard-encodings&quot;&gt;complete list of accepted encodings&lt;/a&gt; is buried way down in the documentation for the &lt;code&gt;codecs&lt;/code&gt; module, which is part of Python&amp;rsquo;s Standard Library.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s one more useful recognized encoding to be aware of, which is &lt;code&gt;&quot;unicode-escape&quot;&lt;/code&gt;.  If you have a decoded &lt;code&gt;str&lt;/code&gt; and want to quickly get a representation of its escaped Unicode literal, then you can specify this encoding in &lt;code&gt;.encode()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alef&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1575&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Or &amp;quot;\u0627&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alef_hamza&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;chr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1571&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Or &amp;quot;\u0623&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;alef_hamza&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(&amp;#39;ا&amp;#39;, &amp;#39;أ&amp;#39;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alef&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;unicode-escape&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;\\u0627&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;alef_hamza&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;unicode-escape&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;b&amp;#39;\\u0623&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;you-know-what-they-say-about-assumptions&quot;&gt;You Know What They Say About Assumptions&amp;hellip;&lt;/h2&gt;
&lt;p&gt;Just because Python makes the assumption of UTF-8 encoding for files and code that &lt;em&gt;you&lt;/em&gt; generate doesn&amp;rsquo;t mean that you, the programmer, should operate with the same assumption for external data.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say that again because it&amp;rsquo;s a rule to live by: when you receive binary data (bytes) from a third party source, whether it be from a file or over a network, the best practice is to check that the data specifies an encoding.  If it doesn&amp;rsquo;t, then it&amp;rsquo;s on you to ask.&lt;/p&gt;
&lt;p&gt;All I/O happens in bytes, not text, and bytes are just ones and zeros to a computer until you tell it otherwise by informing it of an encoding.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of where things can go wrong.  You&amp;rsquo;re subscribed to an API that sends you a recipe of the day, which you receive in &lt;code&gt;bytes&lt;/code&gt; and have always decoded using &lt;code&gt;.decode(&quot;utf-8&quot;)&lt;/code&gt; with no problem.  On this particular day, part of the recipe looks like this:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xbc&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; cup of flour&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It looks as if the recipe calls for some flour, but we don&amp;rsquo;t know how much:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;utf-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;UnicodeDecodeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;utf-8&amp;#39; codec can&amp;#39;t decode byte 0xbc in position 0: invalid start byte&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;Uh oh&lt;/em&gt;.  There&amp;rsquo;s that pesky &lt;code&gt;UnicodeDecodeError&lt;/code&gt; that can bite you when you make assumptions about encoding.  You check with the API host. Lo and behold, the data is actually sent over encoded in Latin-1:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;latin-1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;¼ cup of flour&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There we go.  In &lt;a href=&quot;https://en.wikipedia.org/wiki/ISO/IEC_8859-1#Code_page_layout&quot;&gt;Latin-1&lt;/a&gt;, every character fits into a single byte, whereas the &amp;ldquo;¼&amp;rdquo; character takes up two bytes in UTF-8 (&lt;code&gt;&quot;\xc2\xbc&quot;&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;The lesson here is that it can be dangerous to assume the encoding of any data that is handed off to you.  It&amp;rsquo;s &lt;em&gt;usually&lt;/em&gt; UTF-8 these days, but it&amp;rsquo;s the small percentage of cases where it&amp;rsquo;s not that will blow things up.&lt;/p&gt;
&lt;p&gt;If you really do need to abandon ship and guess an encoding, then have a look at the &lt;a href=&quot;https://chardet.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;chardet&lt;/code&gt;&lt;/a&gt; library, which uses methodology from Mozilla to make an educated guess about ambiguously encoded text.  That said, a tool like &lt;code&gt;chardet&lt;/code&gt; should be your last resort, not your first.&lt;/p&gt;
&lt;h2 id=&quot;odds-and-ends-unicodedata&quot;&gt;Odds and Ends: &lt;code&gt;unicodedata&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;We would be remiss not to mention &lt;a href=&quot;https://docs.python.org/3/library/unicodedata.html&quot;&gt;&lt;code&gt;unicodedata&lt;/code&gt;&lt;/a&gt; from the Python Standard Library, which lets you interact with and do lookups on the Unicode Character Database (UCD):&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;unicodedata&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unicodedata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;€&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;EURO SIGN&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unicodedata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lookup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;EURO SIGN&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;€&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;In this article, you&amp;rsquo;ve decoded the wide and imposing subject of character encoding in Python.  &lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve covered a lot of ground here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fundamental concepts of character encodings and numbering systems&lt;/li&gt;
&lt;li&gt;Integer, binary, octal, hex, str, and bytes literals in Python&lt;/li&gt;
&lt;li&gt;Python&amp;rsquo;s built-in functions related to character encoding and numbering systems&lt;/li&gt;
&lt;li&gt;Python 3&amp;rsquo;s treatment of text versus binary data&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, go forth and encode!&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;Resources&lt;/h2&gt;
&lt;p&gt;For even more detail about the topics covered here, check out these resources: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Joel Spolsky:&lt;/strong&gt; &lt;a href=&quot;https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/&quot;&gt;The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;David Zentgraf:&lt;/strong&gt; &lt;a href=&quot;http://kunststube.net/encoding/&quot;&gt;What every programmer absolutely, positively needs to know about encodings and character sets to work with text&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mozilla:&lt;/strong&gt; &lt;a href=&quot;https://www-archive.mozilla.org/projects/intl/UniversalCharsetDetection.html&quot;&gt;A composite approach to language/encoding detection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Wikipedia:&lt;/strong&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/UTF-8&quot;&gt;UTF-8&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;John Skeet:&lt;/strong&gt; &lt;a href=&quot;http://csharpindepth.com/Articles/General/Unicode.aspx&quot;&gt;Unicode and .NET&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Charles Petzold:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/asins/073560505X&quot;&gt;&lt;em&gt;Code: The Hidden Language of Computer Hardware and Software&lt;/em&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Network Working Group, RFC 3629:&lt;/strong&gt; &lt;a href=&quot;https://tools.ietf.org/html/rfc3629&quot;&gt;UTF-8, a transformation format of ISO 10646&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unicode Technical Standard #18:&lt;/strong&gt; &lt;a href=&quot;https://unicode.org/reports/tr18/&quot;&gt;Unicode Regular Expressions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Python docs have two pages on the subject:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3.0/whatsnew/3.0.html#text-vs-data-instead-of-unicode-vs-8-bit&quot;&gt;What&amp;rsquo;s New in Python 3.0&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/howto/unicode.html#unicode-howto&quot;&gt;Unicode HOWTO&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Installing Python on Windows, macOS, and Linux</title>
      <id>https://realpython.com/courses/installing-python-windows-macos-linux/</id>
      <link href="https://realpython.com/courses/installing-python-windows-macos-linux/"/>
      <updated>2019-05-16T14:00:00+00:00</updated>
      <summary>To get started working with Python, you&#39;ll need to have access to the Python interpreter. There are several common ways to accomplish this and in this course, you will learn how to install the latest version of Python on your computer.</summary>
      <content type="html">
        &lt;p&gt;To get started working with Python, you&amp;rsquo;ll need to have access to the Python interpreter. There are several common ways to accomplish this. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this course, you will learn how to install the latest version of Python 3 on your computer.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Many operating systems, such as macOS and Linux, come with Python pre-installed. The version of Python that comes with your operating system is called your &lt;em&gt;system Python&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;The system Python is almost always out-of-date, and may not even be a full Python installation. It&amp;rsquo;s essential that you have the most recent version of Python so that you can follow along successfully with the examples in this book.&lt;/p&gt;
&lt;p&gt;There are two major versions of Python available: Python 2, also known as legacy Python, and Python 3.  Python 2 was released in the year 2000 and will reach its end-of-life &lt;a href=&quot;https://pythonclock.org/&quot;&gt;on January 1, 2020&lt;/a&gt;. This course focuses on Python 3.&lt;/p&gt;
&lt;p&gt;It is split into three sections: Windows, macOS, and Linux. Just find the section for your operating system and follow the steps to get your computer set-up.&lt;/p&gt;
&lt;p&gt;If you have a different operating system, check out the &lt;a href=&quot;https://realpython.com/installing-python/&quot;&gt;Python 3 Installation &amp;amp; Setup Guide&lt;/a&gt; maintained on &lt;a href=&quot;https://realpython.com&quot;&gt;realpython.com&lt;/a&gt; to see if your OS is covered.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Three Ways of Storing and Accessing Lots of Images in Python</title>
      <id>https://realpython.com/storing-images-in-python/</id>
      <link href="https://realpython.com/storing-images-in-python/"/>
      <updated>2019-05-15T14:00:00+00:00</updated>
      <summary>In this tutorial, you&#39;ll cover three ways of storing and accessing lots of images in Python. You&#39;ll also see  experimental evidence for the performance benefits and drawbacks of each one.</summary>
      <content type="html">
        &lt;p&gt;Why would you want to know more about different ways of storing and accessing images in Python? If you&amp;rsquo;re &lt;a href=&quot;https://realpython.com/python-opencv-color-spaces/&quot;&gt;segmenting a handful of images by color&lt;/a&gt; or &lt;a href=&quot;https://realpython.com/face-recognition-with-python/&quot;&gt;detecting faces one by one&lt;/a&gt; using OpenCV, then you don&amp;rsquo;t need to worry about it. Even if you&amp;rsquo;re using the &lt;a href=&quot;https://pillow.readthedocs.io/&quot;&gt;Python Imaging Library (PIL)&lt;/a&gt; to draw on a few hundred photos, you still don&amp;rsquo;t need to. Storing images on disk, as &lt;code&gt;.png&lt;/code&gt; or &lt;code&gt;.jpg&lt;/code&gt; files, is both suitable and appropriate.&lt;/p&gt;
&lt;p&gt;Increasingly, however, the number of images required for a given task is getting larger and larger. Algorithms like convolutional neural networks, also known as convnets or CNNs, can handle enormous datasets of images and even learn from them. If you&amp;rsquo;re interested, you can read more about how convnets can be used for &lt;a href=&quot;https://karpathy.github.io/2015/10/25/selfie/&quot;&gt;ranking selfies&lt;/a&gt; or for &lt;a href=&quot;https://realpython.com/python-keras-text-classification/&quot;&gt;sentiment analysis&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://image-net.org&quot;&gt;ImageNet&lt;/a&gt; is a well-known public image database put together for training models on tasks like object classification, detection, and segmentation, and it consists of &lt;em&gt;over 14 million images.&lt;/em&gt; &lt;/p&gt;
&lt;p&gt;Think about how long it would take to load all of them into memory for training, in batches, perhaps hundreds or thousands of times. Keep reading, and you&amp;rsquo;ll be convinced that it would take quite awhile&amp;mdash;at least long enough to leave your computer and do many other things while you wish you worked at Google or NVIDIA.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this tutorial, you&amp;rsquo;ll learn about:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Storing images on disk as &lt;code&gt;.png&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;Storing images in lightning memory-mapped databases (LMDB)&lt;/li&gt;
&lt;li&gt;Storing images in hierarchical data format (HDF5)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;You&amp;rsquo;ll also explore the following:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Why alternate storage methods are worth considering&lt;/li&gt;
&lt;li&gt;What the performance differences are when you&amp;rsquo;re reading and writing single images&lt;/li&gt;
&lt;li&gt;What the performance differences are when you&amp;rsquo;re reading and writing &lt;em&gt;many&lt;/em&gt; images&lt;/li&gt;
&lt;li&gt;How the three methods compare in terms of disk usage&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If none of the storage methods ring a bell, don&amp;rsquo;t worry: for this article, all you need is a reasonably solid foundation in Python and a basic understanding of images (that they are really composed of multi-dimensional arrays of numbers) and relative memory, such as the difference between 10MB and 10GB.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s get started!&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-opencv-examples-experiment&quot; data-focus=&quot;false&quot;&gt;Click here to get the Python Face Detection &amp; OpenCV Examples Mini-Guide&lt;/a&gt; that shows you practical code examples of real-world Python computer vision techniques.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;setup&quot;&gt;Setup&lt;/h2&gt;
&lt;p&gt;You will need an image dataset to experiment with, as well as a few Python packages.&lt;/p&gt;
&lt;h3 id=&quot;a-dataset-to-play-with&quot;&gt;A Dataset to Play With&lt;/h3&gt;
&lt;p&gt;We will be using the Canadian Institute for Advanced Research image dataset, better known as &lt;a href=&quot;https://en.wikipedia.org/wiki/CIFAR-10&quot;&gt;CIFAR-10&lt;/a&gt;, which consists of 60,000 32x32 pixel color images belonging to different object classes, such as dogs, cats, and airplanes. Relatively, CIFAR is not a very large dataset, but if we were to use the full &lt;a href=&quot;https://groups.csail.mit.edu/vision/TinyImages/&quot;&gt;TinyImages dataset&lt;/a&gt;, then you would need about 400GB of free disk space, which would probably be a limiting factor.&lt;/p&gt;
&lt;p&gt;Credits for the dataset as described in &lt;a href=&quot;https://www.cs.toronto.edu/~kriz/learning-features-2009-TR.pdf&quot;&gt;chapter 3 of this tech report&lt;/a&gt; go to Alex Krizhevsky, Vinod Nair, and Geoffrey Hinton.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;d like to follow along with the code examples in this article, you can &lt;a href=&quot;https://www.cs.toronto.edu/~kriz/cifar.html&quot;&gt;download CIFAR-10 here&lt;/a&gt;, selecting the Python version. You&amp;rsquo;ll be sacrificing 163MB of disk space:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/cifar_10.e77ef0cd86df.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-75&quot; src=&quot;https://files.realpython.com/media/cifar_10.e77ef0cd86df.png&quot; width=&quot;964&quot; height=&quot;738&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cifar_10.e77ef0cd86df.png&amp;amp;w=241&amp;amp;sig=e510384d0787f189f977fefb7d27c91b74ebb467 241w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/cifar_10.e77ef0cd86df.png&amp;amp;w=482&amp;amp;sig=603b87769ac3fd7651c7d18e0eed22e83bfcf421 482w, https://files.realpython.com/media/cifar_10.e77ef0cd86df.png 964w&quot; sizes=&quot;75vw&quot; alt=&quot;cifar-10-dataset&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Image: A. Krizhevsky&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;When you download and unzip the folder, you&amp;rsquo;ll discover that the files are not human-readable image files. They have actually been serialized and saved in batches using &lt;a href=&quot;https://docs.python.org/2/library/pickle.html&quot;&gt;cPickle&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;While we won&amp;rsquo;t consider &lt;code&gt;pickle&lt;/code&gt; or &lt;code&gt;cPickle&lt;/code&gt; in this article, other than to extract the CIFAR dataset, it&amp;rsquo;s worth mentioning that the Python &lt;code&gt;pickle&lt;/code&gt; module has the key advantage of being able to serialize any Python object without any extra code or transformation on your part. It also has a potentially serious disadvantage of posing a security risk and not coping well when dealing with very large quantities of data.&lt;/p&gt;
&lt;p&gt;The following code unpickles each of the five batch files and loads all of the images into a NumPy array:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pickle&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pathlib&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Path to the unzipped CIFAR data&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;data/cifar-10-batches-py/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Unpickle function provided by the CIFAR hosts&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;unpickle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;rb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pickle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;encoding&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;bytes&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;batch&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data_dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;glob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;data_batch_*&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;batch_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;unpickle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flat_im&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;data&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;im_channels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Each image is flattened, with channels in order of R, G, B&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;im_channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;flat_im&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reshape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Reconstruct the original image&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dstack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;im_channels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Save the label&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;batch_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;labels&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Loaded CIFAR-10 training set:&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot; - np.shape(images)     {np.shape(images)}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot; - np.shape(labels)     {np.shape(labels)}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All the images are now in RAM in the &lt;code&gt;images&lt;/code&gt; variable, with their corresponding meta data in &lt;code&gt;labels&lt;/code&gt;, and are ready for you to manipulate. Next, you can install the Python packages you&amp;rsquo;ll use for the three methods.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; That last code block used f-strings. You can read more about them in &lt;a href=&quot;https://realpython.com/python-f-strings/&quot;&gt;Python 3&amp;rsquo;s f-Strings: An Improved String Formatting Syntax (Guide)&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;setup-for-storing-images-on-disk&quot;&gt;Setup for Storing Images on Disk&lt;/h3&gt;
&lt;p&gt;You&amp;rsquo;ll need to set up your environment for the default method of saving and accessing these images from disk. This article will assume you have Python 3.x installed on your system, and will use &lt;code&gt;Pillow&lt;/code&gt; for the image manipulation:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pip install Pillow
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Alternatively, if you prefer, you can install it using &lt;a href=&quot;https://anaconda.org/conda-forge/pillow&quot;&gt;Anaconda&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; conda install -c conda-forge pillow
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;PIL&lt;/code&gt; is the original version of the Python Imaging Library, which is no longer maintained and is not compatible with Python 3.x. If you have previously installed &lt;code&gt;PIL&lt;/code&gt;, make sure to uninstall it before installing &lt;code&gt;Pillow&lt;/code&gt;, as they can&amp;rsquo;t exist together.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now you&amp;rsquo;re ready for storing and reading images from disk.&lt;/p&gt;
&lt;h3 id=&quot;getting-started-with-lmdb&quot;&gt;Getting Started With LMDB&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Lightning_Memory-Mapped_Database&quot;&gt;LMDB&lt;/a&gt;, sometimes referred to as the &amp;ldquo;Lightning Database,&amp;rdquo; stands for Lightning Memory-Mapped Database because it&amp;rsquo;s fast and uses memory-mapped files. It&amp;rsquo;s a key-value store, not a relational database.&lt;/p&gt;
&lt;p&gt;In terms of implementation, LMDB is a B+ tree, which basically means that it is a tree-like graph structure stored in memory where each key-value element is a node, and nodes can have many children. Nodes on the same level are linked to one another for fast traversal. &lt;/p&gt;
&lt;p&gt;Critically, key components of the B+ tree are set to correspond to the page size of the host operating system, maximizing efficiency when accessing any key-value pair in the database. Since LMDB high-performance heavily relies on this particular point, LMDB efficiency has been shown to be dependent on the underlying file system and its implementation.&lt;/p&gt;
&lt;p&gt;Another key reason for the efficiency of LMDB is that it is memory-mapped. This means that &lt;strong&gt;it returns direct pointers to the memory addresses of both keys and values&lt;/strong&gt;, without needing to copy anything in memory as most other databases do.&lt;/p&gt;
&lt;p&gt;Those who want to dive into a bit more of the internal implementation details of B+ trees can check out &lt;a href=&quot;http://www.cburch.com/cs/340/reading/btree/index.html&quot;&gt;this article on B+ trees&lt;/a&gt; and then play with &lt;a href=&quot;https://www.cs.usfca.edu/~galles/visualization/BPlusTree.html&quot;&gt;this visualization of node insertion&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If B+ trees don&amp;rsquo;t interest you, don&amp;rsquo;t worry. You don&amp;rsquo;t need to know much about their internal implementation in order to use LMDB. We will be using the Python binding for the LMDB C library, which can be installed via pip:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pip install lmdb
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You also have the option of installing via &lt;a href=&quot;https://anaconda.org/conda-forge/python-lmdb&quot;&gt;Anaconda&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; conda install -c conda-forge python-lmdb
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Check that you can &lt;code&gt;import lmdb&lt;/code&gt; from a Python shell, and you&amp;rsquo;re good to go.&lt;/p&gt;
&lt;h3 id=&quot;getting-started-with-hdf5&quot;&gt;Getting Started With HDF5&lt;/h3&gt;
&lt;p&gt;HDF5 stands for Hierarchical Data Format, a file format referred to as HDF4 or HDF5. We don&amp;rsquo;t need to worry about HDF4, as HDF5 is the current maintained version. &lt;/p&gt;
&lt;p&gt;Interestingly, HDF has &lt;a href=&quot;https://www.hdfgroup.org/about-us/&quot;&gt;its origins&lt;/a&gt; in the National Center for Supercomputing Applications, as a portable, compact scientific data format. If you&amp;rsquo;re wondering if it&amp;rsquo;s widely used, check out &lt;a href=&quot;https://earthdata.nasa.gov/user-resources/standards-and-references/hdf-eos5&quot;&gt;NASA&amp;rsquo;s blurb on HDF5&lt;/a&gt; from their Earth Data project.&lt;/p&gt;
&lt;p&gt;HDF files consist of two types of objects: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Datasets&lt;/li&gt;
&lt;li&gt;Groups&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Datasets are multidimensional arrays, and groups consist of datasets or other groups. Multidimensional arrays of any size and type can be stored as a dataset, but the dimensions and type have to be uniform within a dataset. Each dataset must contain a homogeneous N-dimensional array. That said, because groups and datasets may be nested, you can still get the heterogeneity you may need:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pip install h5py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As with the other libraries, you can alternately install via &lt;a href=&quot;https://anaconda.org/conda-forge/h5py&quot;&gt;Anaconda&lt;/a&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; conda install -c conda-forge h5py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you can &lt;code&gt;import h5py&lt;/code&gt; from a Python shell, everything is set up properly.&lt;/p&gt;
&lt;h2 id=&quot;storing-a-single-image&quot;&gt;Storing a Single Image&lt;/h2&gt;
&lt;p&gt;Now that you have a general overview of the methods, let&amp;rsquo;s dive straight in and look at a quantitative comparison of the basic tasks we care about: &lt;strong&gt;how long it takes to read and write files, and how much disk memory will be used.&lt;/strong&gt; This will also serve as a basic introduction to how the methods work, with code examples of how to use them.&lt;/p&gt;
&lt;p&gt;When I refer to &amp;ldquo;files,&amp;rdquo; I generally mean a lot of them. However, it is important to make a distinction since some methods may be optimized for different operations and quantities of files. &lt;/p&gt;
&lt;p&gt;For the purposes of experimentation, &lt;strong&gt;we can compare the performance between various quantities of files, by factors of 10 from a single image to 100,000 images.&lt;/strong&gt; Since our five batches of CIFAR-10 add up to 50,000 images, we can use each image twice to get to 100,000 images.&lt;/p&gt;
&lt;p&gt;To prepare for the experiments, you will want to create a folder for each method, which will contain all the database files or images, and save the paths to those directories in variables:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pathlib&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;disk_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;data/disk/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lmdb_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;data/lmdb/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hdf5_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;data/hdf5/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;Path&lt;/code&gt; does not automatically create the folders for you unless you specifically ask it to:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mkdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exist_ok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lmdb_dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mkdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exist_ok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hdf5_dir&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mkdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parents&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exist_ok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you can move on to running the actual experiments, with code examples of how to perform basic tasks with the three different methods. We can use the &lt;code&gt;timeit&lt;/code&gt; module, which is included in the Python standard library, to help time the experiments.&lt;/p&gt;
&lt;p&gt;Although the main purpose of this article is not to learn the APIs of the different Python packages, it is helpful to have an understanding of how they can be implemented. We will go through the general principles alongside all the code used to conduct the storing experiments.&lt;/p&gt;
&lt;h3 id=&quot;storing-to-disk&quot;&gt;Storing to Disk&lt;/h3&gt;
&lt;p&gt;Our input for this experiment is a single image &lt;code&gt;image&lt;/code&gt;, currently in memory as a NumPy array. You want to save it first to disk as a &lt;code&gt;.png&lt;/code&gt; image, and name it using a unique image ID &lt;code&gt;image_id&lt;/code&gt;. This can be done using the &lt;code&gt;Pillow&lt;/code&gt; package you installed earlier:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PIL&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;csv&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;store_single_disk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Stores a single image as a .png file on disk.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        image       image array, (32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        image_id    integer unique ID for image&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        label       image label&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromarray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{image_id}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{image_id}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.csv&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;wt&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csvfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csvfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delimiter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quotechar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;|&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quoting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QUOTE_MINIMAL&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writerow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This saves the image. In all realistic applications, you also care about the meta data attached to the image, which in our example dataset is the image label. When you&amp;rsquo;re  storing images to disk, there are several options for saving the meta data.&lt;/p&gt;
&lt;p&gt;One solution is to encode the labels into the image name. This has the advantage of not requiring any extra files. &lt;/p&gt;
&lt;p&gt;However, it also has the big disadvantage of forcing you to deal with all the files whenever you do anything with labels. Storing the labels in a separate file allows you to play around with the labels alone, without having to load the images. Above, I have stored the labels in a separate &lt;code&gt;.csv&lt;/code&gt; files for this experiment.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s move on to doing the exact same task with LMDB.&lt;/p&gt;
&lt;h3 id=&quot;storing-to-lmdb&quot;&gt;Storing to LMDB&lt;/h3&gt;
&lt;p&gt;Firstly, LMDB is a key-value storage system where each entry is saved as a byte array, so in our case, keys will be a unique identifier for each image, and the value will be the image itself. &lt;strong&gt;Both the keys and values are expected to be strings&lt;/strong&gt;, so the common usage is to serialize the value as a string, and then unserialize it when reading it back out.&lt;/p&gt;
&lt;p&gt;You can use &lt;code&gt;pickle&lt;/code&gt; for the serializing. Any Python object can be serialized, so you might as well include the image meta data in the database as well. This saves you the trouble of attaching meta data back to the image data when we load the dataset from disk.&lt;/p&gt;
&lt;p&gt;You can create a basic &lt;a href=&quot;https://realpython.com/lessons/what-object-oriented-programming-oop/&quot;&gt;Python class&lt;/a&gt; for the image and its meta data:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;CIFAR_Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Dimensions of image for reconstruction - not really necessary &lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# for this dataset, but some datasets may include images of &lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# varying sizes&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tobytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Returns the image as a numpy array. &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frombuffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uint8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reshape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Secondly, because LMDB is memory-mapped, new databases need to know how much memory they are expected to use up. This is relatively straightforward in our case, but it can be a massive pain in other cases, which you will see in more depth in a later section. LMDB calls this variable the &lt;code&gt;map_size&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Finally, read and write operations with LMDB are performed in &lt;code&gt;transactions&lt;/code&gt;. You can think of them as similar to those of a traditional database, consisting of a group of operations on the database. This may look already significantly more complicated than the disk version, but hang on and keep reading!&lt;/p&gt;
&lt;p&gt;With those three points in mind, let&amp;rsquo;s look at the code to save a single image to a LMDB:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;lmdb&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pickle&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;store_single_lmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Stores a single image to a LMDB.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        image       image array, (32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        image_id    integer unique ID for image&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        label       image label&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;map_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nbytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Create a new LMDB environment&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lmdb_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;single_lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Start a new write transaction&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# All key-value pairs need to be strings&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CIFAR_Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{image_id:08}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;txn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ascii&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pickle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; It&amp;rsquo;s a good idea to calculate the exact number of bytes each key-value pair will take up. &lt;/p&gt;
&lt;p&gt;With a dataset of images of varying size, this will be an approximation, but you can use &lt;code&gt;sys.getsizeof()&lt;/code&gt; to get a reasonable approximation. Keep in mind that &lt;code&gt;sys.getsizeof(CIFAR_Image)&lt;/code&gt; will only return the size of a class definition, which is 1056, &lt;em&gt;not&lt;/em&gt; the size of an instantiated object.&lt;/p&gt;
&lt;p&gt;The function will also not be able to fully calculate nested items, lists, or objects containing references to other objects. &lt;/p&gt;
&lt;p&gt;Alternately, you could use &lt;a href=&quot;https://pythonhosted.org/Pympler/#usage-examples&quot;&gt;&lt;code&gt;pympler&lt;/code&gt;&lt;/a&gt; to save you some calculations by determining the exact size of an object.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You are now ready to save an image to LMDB. Lastly, let&amp;rsquo;s look at the final method, HDF5.&lt;/p&gt;
&lt;h3 id=&quot;storing-with-hdf5&quot;&gt;Storing With HDF5&lt;/h3&gt;
&lt;p&gt;Remember that an HDF5 file can contain more than one dataset. In this rather trivial case, you can create two datasets, one for the image, and one for its meta data:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;h5py&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;store_single_hdf5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Stores a single image to an HDF5 file.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        image       image array, (32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        image_id    integer unique ID for image&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        label       image label&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Create a new HDF5 file&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h5py&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hdf5_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{image_id}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.h5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;w&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Create a dataset in the file&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dataset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;image&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h5py&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h5t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STD_U8BE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;meta_set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;meta&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h5py&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h5t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STD_U8BE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;h5py.h5t.STD_U8BE&lt;/code&gt; specifies the type of data that will be stored in the dataset, which in this case is unsigned 8-bit integers. You can see a full &lt;a href=&quot;http://api.h5py.org/h5t.html&quot;&gt;list of HDF&amp;rsquo;s predefined datatypes here&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; The choice of datatype will strongly affect the runtime and storage requirements of HDF5, so it is best to choose your minimum requirements.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now that we have reviewed the three methods of saving a single image, let&amp;rsquo;s move on to the next step.&lt;/p&gt;
&lt;h3 id=&quot;experiments-for-storing-a-single-image&quot;&gt;Experiments for Storing a Single Image&lt;/h3&gt;
&lt;p&gt;Now you can put all three functions for saving a single image into a dictionary, which can be called later during the timing experiments:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_store_single_funcs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;disk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_single_disk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_single_lmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_single_hdf5&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, everything is ready for conducting the timed experiment. Let&amp;rsquo;s try saving the first image from CIFAR and its corresponding label, and storing it in the three different ways:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;timeit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeit&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;store_single_timings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;disk&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hdf5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;_store_single_funcs[method](image, 0, label)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;image=images[0]; label=labels[0]&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;store_single_timings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Method: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{method}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, Time usage: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{t}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; While you&amp;rsquo;re playing around with LMDB, you may see a &lt;code&gt;MapFullError: mdb_txn_commit: MDB_MAP_FULL: Environment mapsize limit reached&lt;/code&gt; error. It&amp;rsquo;s important to note that LMDB does &lt;strong&gt;not&lt;/strong&gt; overwrite preexisting values, even if they have the same key.&lt;/p&gt;
&lt;p&gt;This contributes to the fast write time, but it also means that if you store an image more than once in the same LMDB file, then you will use up the map size. If you run a store function, be sure to delete any preexisting LMDB files first.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Remember that we&amp;rsquo;re interested in runtime, displayed here in seconds, and also the memory usage:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th class=&quot;text-center&quot;&gt;Method&lt;/th&gt;
&lt;th class=&quot;text-center&quot;&gt;Save Single Image + Meta&lt;/th&gt;
&lt;th class=&quot;text-center&quot;&gt;Memory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;Disk&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;1.915 ms&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;8 K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;LMDB&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;1.203 ms&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;32 K&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;HDF5&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;8.243 ms&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;8 K&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;There are two takeaways here: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;All of the methods are trivially quick.&lt;/li&gt;
&lt;li&gt;In terms of disk usage, LMDB uses more. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Clearly, despite LMDB having a slight performance lead, we haven&amp;rsquo;t convinced anyone why to not just store images on disk. After all, it&amp;rsquo;s a human readable format, and you can open and view them from any file system browser! Well, it&amp;rsquo;s time to look at a lot more images&amp;hellip;&lt;/p&gt;
&lt;h2 id=&quot;storing-many-images&quot;&gt;Storing Many Images&lt;/h2&gt;
&lt;p&gt;You have seen the code for using the various storage methods to save a single image, so now we need to adjust the code to save many images and then run the timed experiment. &lt;/p&gt;
&lt;h3 id=&quot;adjusting-the-code-for-many-images&quot;&gt;Adjusting the Code for Many Images&lt;/h3&gt;
&lt;p&gt;Saving &lt;em&gt;multiple&lt;/em&gt; images as &lt;code&gt;.png&lt;/code&gt; files is as straightforward as calling &lt;code&gt;store_single_method()&lt;/code&gt; multiple times. But this isn&amp;rsquo;t true for LMDB or HDF5, since you don&amp;rsquo;t want a different database file for each image. Rather, you want to put all of the images into one or more files.&lt;/p&gt;
&lt;p&gt;You will need to slightly alter the code and create three new functions that accept multiple images, &lt;code&gt;store_many_disk()&lt;/code&gt;, &lt;code&gt;store_many_lmdb()&lt;/code&gt;, and &lt;code&gt;store_many_hdf5&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store_many_disk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Stores an array of images to disk&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        images       images array, (N, 32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        labels       labels array, (N, 1) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;num_images&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Save all the images one by one&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromarray&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{i}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Save all the labels to the csv file&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{num_images}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.csv&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;w&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csvfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csvfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delimiter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quotechar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;|&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quoting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QUOTE_MINIMAL&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# This typically would be more than just one value per row&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;writer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writerow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;store_many_lmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Stores an array of images to LMDB.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        images       images array, (N, 32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        labels       labels array, (N, 1) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;num_images&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;map_size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_images&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;nbytes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Create a new LMDB DB for all the images&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lmdb_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{num_images}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;map_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;map_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Same as before — but let&amp;#39;s write all the images in a single transaction&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# All key-value pairs need to be Strings&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CIFAR_Image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{i:08}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;txn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;put&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ascii&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pickle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dumps&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;store_many_hdf5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Stores an array of images to HDF5.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        images       images array, (N, 32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        labels       labels array, (N, 1) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;num_images&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Create a new HDF5 file&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h5py&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hdf5_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{num_images}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_many.h5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;w&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Create a dataset in the file&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;dataset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;images&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h5py&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h5t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STD_U8BE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;meta_set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;meta&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h5py&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h5t&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;STD_U8BE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So you could store more than one file to disk, the image files method was altered to loop over each image in the list. For LMDB, a loop is also needed since we are creating a &lt;code&gt;CIFAR_Image&lt;/code&gt; object for each image and its meta data.&lt;/p&gt;
&lt;p&gt;The smallest adjustment is with the HDF5 method. In fact, there&amp;rsquo;s hardly an adjustment at all! HFD5 files have no limitation on file size aside from external restrictions or dataset size, so all the images were stuffed into a single dataset, just like before.&lt;/p&gt;
&lt;p&gt;Next, you will need to prepare the dataset for the experiments by increasing its size.&lt;/p&gt;
&lt;h3 id=&quot;preparing-the-dataset&quot;&gt;Preparing the Dataset&lt;/h3&gt;
&lt;p&gt;Before running the experiments again, let&amp;rsquo;s first double our dataset size so that we can test with up to 100,000 images:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cutoffs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Let&amp;#39;s double our images so that we have 100,000&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concatenate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;concatenate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Make sure you actually have 100,000 images and labels&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;shape&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that there are enough images, it&amp;rsquo;s time for the experiment.&lt;/p&gt;
&lt;h3 id=&quot;experiment-for-storing-many-images&quot;&gt;Experiment for Storing Many Images&lt;/h3&gt;
&lt;p&gt;As you did with reading many images, you can create a dictionary handling all the functions with &lt;code&gt;store_many_&lt;/code&gt; and run the experiments:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_store_many_funcs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;disk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_many_disk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_many_lmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;store_many_hdf5&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;timeit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeit&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;store_many_timings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;disk&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hdf5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cutoff&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cutoffs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;disk&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hdf5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;_store_many_funcs[method](images_, labels_)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;images_=images[:cutoff]; labels_=labels[:cutoff]&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;store_many_timings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Print out the method, cutoff, and elapsed time&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Method: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{method}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, Time usage: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{t}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you&amp;rsquo;re following along and running the code yourself, you&amp;rsquo;ll need to sit back a moment in suspense and wait for 111,110 images to be stored three times each to your disk, in three different formats. You&amp;rsquo;ll also need to say goodbye to approximately 2 GB of disk space.&lt;/p&gt;
&lt;p&gt;Now for the moment of truth! &lt;strong&gt;How long did all of that storing take?&lt;/strong&gt; A picture is worth a thousand words:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/store_many.273573157770.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-75&quot; src=&quot;https://files.realpython.com/media/store_many.273573157770.png&quot; width=&quot;629&quot; height=&quot;464&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/store_many.273573157770.png&amp;amp;w=157&amp;amp;sig=957f58cfcef02f5beea36463bf7f78da3cbf35ea 157w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/store_many.273573157770.png&amp;amp;w=314&amp;amp;sig=e875ba210d947762c8e2de5ef564343cdcb44e01 314w, https://files.realpython.com/media/store_many.273573157770.png 629w&quot; sizes=&quot;75vw&quot; alt=&quot;store-many&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/store_many_log.29e8ae980ab6.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-75&quot; src=&quot;https://files.realpython.com/media/store_many_log.29e8ae980ab6.png&quot; width=&quot;638&quot; height=&quot;474&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/store_many_log.29e8ae980ab6.png&amp;amp;w=159&amp;amp;sig=a6f287f3516ba2f3254374102ec20fe3502646b1 159w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/store_many_log.29e8ae980ab6.png&amp;amp;w=319&amp;amp;sig=b0a77114ed4734d41dd0337f71dd87fff4b50c1e 319w, https://files.realpython.com/media/store_many_log.29e8ae980ab6.png 638w&quot; sizes=&quot;75vw&quot; alt=&quot;store-many-log&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The first graph shows the normal, unadjusted storage time, highlighting the drastic difference between storing to &lt;code&gt;.png&lt;/code&gt; files and LMDB or HDF5. &lt;/p&gt;
&lt;p&gt;The second graph shows the &lt;code&gt;log&lt;/code&gt; of the timings, highlighting that HDF5 starts out slower than LMDB but, with larger quantities of images, comes out slightly ahead.&lt;/p&gt;
&lt;p&gt;While exact results may vary depending on your machine, &lt;strong&gt;this is why LMDB and HDF5 are worth thinking about.&lt;/strong&gt; Here&amp;rsquo;s the code that generated the above graph:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;matplotlib.pyplot&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;plt&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;plot_with_legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;x_range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;legend_labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x_label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y_label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Displays a single plot with multiple datasets and matching legends.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        --------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        x_range         list of lists containing x data&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        y_data          list of lists containing y values&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        legend_labels   list of string legend labels&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        x_label         x axis label&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        y_label         y axis label&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;style&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;use&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;seaborn-whitegrid&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figure&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend_labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;TypeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;Error: number of data sets does not match number of labels.&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;all_plots&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;zip&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;legend_labels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loglog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;all_plots&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;temp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xlabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x_label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y_label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;handles&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;all_plots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Getting the store timings data to display&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;disk_x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store_many_timings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;disk&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lmdb_x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store_many_timings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hdf5_x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;store_many_timings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hdf5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plot_with_legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cutoffs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb_x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5_x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;PNG files&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;LMDB&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;HDF5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Number of images&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Seconds to store&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Storage time&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plot_with_legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cutoffs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb_x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5_x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;PNG files&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;LMDB&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;HDF5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Number of images&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Seconds to store&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Log storage time&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now let&amp;rsquo;s go on to reading the images back out.&lt;/p&gt;
&lt;h2 id=&quot;reading-a-single-image&quot;&gt;Reading a Single Image&lt;/h2&gt;
&lt;p&gt;First, let&amp;rsquo;s consider the case for reading a single image back into an array for each of the three methods.&lt;/p&gt;
&lt;h3 id=&quot;reading-from-disk&quot;&gt;Reading From Disk&lt;/h3&gt;
&lt;p&gt;Of the three methods, LMDB requires the most legwork when reading image files back out of memory, because of the serialization step. Let&amp;rsquo;s walk through these functions that read a single image out for each of the three storage formats. &lt;/p&gt;
&lt;p&gt;First, read a single image and its meta from a &lt;code&gt;.png&lt;/code&gt; and &lt;code&gt;.csv&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_single_disk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Stores a single image to disk.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        image_id    integer unique ID for image&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;        Returns:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ----------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        image       image array, (32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        label       associated meta data, int label&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{image_id}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{image_id}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.csv&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csvfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csvfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delimiter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quotechar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;|&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quoting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QUOTE_MINIMAL&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;reading-from-lmdb&quot;&gt;Reading From LMDB&lt;/h3&gt;
&lt;p&gt;Next, read the same image and meta from an LMDB by opening the environment and starting a read transaction:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_single_lmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Stores a single image to LMDB.&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;        image_id    integer unique ID for image&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;        Returns:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;        ----------&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;        image       image array, (32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;        label       associated meta data, int label&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Open the LMDB environment&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lmdb_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;single_lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;readonly&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Start a new read transaction&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Encode the key the same way as we stored it&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{image_id:08}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ascii&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Remember it&amp;#39;s a CIFAR_Image object that is loaded&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;cifar_image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pickle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Retrieve the relevant bits&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cifar_image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cifar_image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here are a couple points to not about the code snippet above:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 13:&lt;/strong&gt; The &lt;code&gt;readonly=True&lt;/code&gt; flag specifies that no writes will be allowed on the LMDB file until the transaction is finished. In database lingo, it&amp;rsquo;s equivalent to taking a read lock.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 20:&lt;/strong&gt; To retrieve the CIFAR_Image object, you need to reverse the steps we took to pickle it when we were writing it. This is where the &lt;code&gt;get_image()&lt;/code&gt; of the object is helpful.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This wraps up reading the image back out from LMDB. Finally, you will want to do the same with HDF5.&lt;/p&gt;
&lt;h3 id=&quot;reading-from-hdf5&quot;&gt;Reading From HDF5&lt;/h3&gt;
&lt;p&gt;Reading from HDF5 looks very similar to the writing process. Here is the code to open and read the HDF5 file and parse the same image and meta:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_single_hdf5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Stores a single image to HDF5.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        image_id    integer unique ID for image&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;        Returns:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ----------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        image       image array, (32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        label       associated meta data, int label&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Open the HDF5 file&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h5py&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hdf5_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{image_id}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.h5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;r+&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/image&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;astype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;uint8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/meta&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;astype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;uint8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that you access the various datasets in the file by indexing the &lt;code&gt;file&lt;/code&gt; object using the dataset name preceded by a forward slash &lt;code&gt;/&lt;/code&gt;. As before, you can create a dictionary containing all the read functions:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_read_single_funcs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;disk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_single_disk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_single_lmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_single_hdf5&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this dictionary prepared, you are ready for running the experiment.&lt;/p&gt;
&lt;h3 id=&quot;experiment-for-reading-a-single-image&quot;&gt;Experiment for Reading a Single Image&lt;/h3&gt;
&lt;p&gt;You might expect that the experiment for reading a single image in will have somewhat trivial results, but here&amp;rsquo;s the experiment code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;timeit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeit&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;read_single_timings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;disk&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hdf5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;_read_single_funcs[method](0)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;image=images[0]; label=labels[0]&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;read_single_timings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Method: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{method}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, Time usage: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{t}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here are the results of the experiment for reading a single image:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th class=&quot;text-center&quot;&gt;Method&lt;/th&gt;
&lt;th class=&quot;text-center&quot;&gt;Read Single Image + Meta&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;Disk&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;1.61970 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;LMDB&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;4.52063 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td class=&quot;text-center&quot;&gt;HDF5&lt;/td&gt;
&lt;td class=&quot;text-center&quot;&gt;1.98036 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s slightly faster to read the &lt;code&gt;.png&lt;/code&gt; and &lt;code&gt;.csv&lt;/code&gt; files directly from disk, but all three methods perform trivially quickly. The experiments we&amp;rsquo;ll do next are much more interesting.&lt;/p&gt;
&lt;h2 id=&quot;reading-many-images&quot;&gt;Reading Many Images&lt;/h2&gt;
&lt;p&gt;Now you can adjust the code to read many images at once. This is likely the action you&amp;rsquo;ll be performing most often, so the runtime performance is essential.&lt;/p&gt;
&lt;h3 id=&quot;adjusting-the-code-for-many-images_1&quot;&gt;Adjusting the Code for Many Images&lt;/h3&gt;
&lt;p&gt;Extending the functions above, you can create functions with &lt;code&gt;read_many_&lt;/code&gt;, which can be used for the next experiments. Like before, it is interesting to compare performance when reading different quantities of images, which are repeated in the code below for reference:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_many_disk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Reads image from disk.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        num_images   number of images to read&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;        Returns:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ----------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        images      images array, (N, 32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        labels      associated meta data, int label (N, 1)&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Loop over all IDs and read each image in one by one&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{image_id}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.png&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{num_images}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.csv&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;r&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csvfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;csvfile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;delimiter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot; &amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quotechar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;|&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;quoting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;csv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QUOTE_MINIMAL&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]))&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_many_lmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Reads image from LMDB.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        num_images   number of images to read&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;        Returns:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ----------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        images      images array, (N, 32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        labels      associated meta data, int label (N, 1)&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lmdb_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{num_images}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;readonly&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Start a new read transaction&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;begin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Read all images in one single transaction, with one lock&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# We could split this up into multiple transactions if needed&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;image_id&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{image_id:08}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ascii&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Remember that it&amp;#39;s a CIFAR_Image object &lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# that is stored as the value&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;cifar_image&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pickle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loads&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Retrieve the relevant bits&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cifar_image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_image&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cifar_image&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_many_hdf5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot; Reads image from HDF5.&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        Parameters:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ---------------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        num_images   number of images to read&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;        Returns:&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        ----------&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        images      images array, (N, 32, 32, 3) to be stored&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;        labels      associated meta data, int label (N, 1)&lt;/span&gt;
&lt;span class=&quot;sd&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Open the HDF5 file&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;h5py&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hdf5_dir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{num_images}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;_many.h5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;r+&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/images&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;astype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;uint8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/meta&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;astype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;uint8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;labels&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;_read_many_funcs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;dict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;disk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_many_disk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_many_lmdb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_many_hdf5&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the reading functions stored in a dictionary as with the writing functions, you&amp;rsquo;re all set for the experiment.&lt;/p&gt;
&lt;h3 id=&quot;experiment-for-reading-many-images&quot;&gt;Experiment for Reading Many Images&lt;/h3&gt;
&lt;p&gt;You can now run the experiment for reading many images out:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;timeit&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeit&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;read_many_timings&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;disk&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hdf5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cutoff&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cutoffs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;disk&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;hdf5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;s2&quot;&gt;&amp;quot;_read_many_funcs[method](num_images)&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;setup&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;num_images=cutoff&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;number&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;read_many_timings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Print out the method, cutoff, and elapsed time&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Method: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{method}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, No. images: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{cutoff}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, Time usage: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{t}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As we did previously, you can graph the read experiment results:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/read_many.9c4a6dc5bdc0.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-75&quot; src=&quot;https://files.realpython.com/media/read_many.9c4a6dc5bdc0.png&quot; width=&quot;629&quot; height=&quot;464&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/read_many.9c4a6dc5bdc0.png&amp;amp;w=157&amp;amp;sig=2817a607a35bf3b569a6d532ce5821bcdbaa604e 157w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/read_many.9c4a6dc5bdc0.png&amp;amp;w=314&amp;amp;sig=7cc2cf221eb8238fd02f99e47112e695eac6908b 314w, https://files.realpython.com/media/read_many.9c4a6dc5bdc0.png 629w&quot; sizes=&quot;75vw&quot; alt=&quot;read-many-image&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/read_many_log.594dac8746ad.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-75&quot; src=&quot;https://files.realpython.com/media/read_many_log.594dac8746ad.png&quot; width=&quot;638&quot; height=&quot;474&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/read_many_log.594dac8746ad.png&amp;amp;w=159&amp;amp;sig=5c76fd59e67b849a7c06662cbae54be391784571 159w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/read_many_log.594dac8746ad.png&amp;amp;w=319&amp;amp;sig=e5fe9a82f2b3421f2a65c8f2ff5a50a3a3b23362 319w, https://files.realpython.com/media/read_many_log.594dac8746ad.png 638w&quot; sizes=&quot;75vw&quot; alt=&quot;read-many-log&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The top graph shows the normal, unadjusted read times, showing the drastic difference between reading from &lt;code&gt;.png&lt;/code&gt; files and LMDB or HDF5. &lt;/p&gt;
&lt;p&gt;In contrast, the graph on the bottom shows the &lt;code&gt;log&lt;/code&gt; of the timings, highlighting the relative differences with fewer images. Namely, we can see how HDF5 starts out behind but, with more images, becomes consistently faster than LMDB by a small margin.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card0b7b96&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse0b7b96&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse0b7b96&quot;&gt;Plot the Read Timings&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse0b7b96&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse0b7b96&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse0b7b96&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card0b7b96&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;Using the same plotting function as for the write timings, we have the following:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_x_r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read_many_timings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;disk&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lmdb_x_r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read_many_timings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;lmdb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hdf5_x_r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read_many_timings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;hdf5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plot_with_legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cutoffs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_x_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb_x_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5_x_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;PNG files&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;LMDB&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;HDF5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Number of images&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Seconds to read&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Read time&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plot_with_legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cutoffs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_x_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb_x_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5_x_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;PNG files&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;LMDB&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;HDF5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Number of images&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Seconds to read&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Log read time&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;In practice, the write time is often less critical than the read time.&lt;/strong&gt; Imagine that you are training a deep neural network on images, and only half of your entire image dataset fits into RAM at once. Each epoch of training a network requires the entire dataset, and the model needs a few hundred epochs to converge. You will essentially be reading half of the dataset into memory every epoch.&lt;/p&gt;
&lt;p&gt;There are several tricks people do, such as training pseudo-epochs to make this slightly better, but you get the idea.&lt;/p&gt;
&lt;p&gt;Now, look again at the read graph above. The difference between a 40-second and 4-second read time suddenly is the difference between waiting six hours for your model to train, or forty minutes!&lt;/p&gt;
&lt;p&gt;If we view the read and write times on the same chart, we have the following:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/read_write.a4f87d39489d.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-75&quot; src=&quot;https://files.realpython.com/media/read_write.a4f87d39489d.png&quot; width=&quot;629&quot; height=&quot;464&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/read_write.a4f87d39489d.png&amp;amp;w=157&amp;amp;sig=aecde3bdcda3a7abbb446596f96cce7b42d00f45 157w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/read_write.a4f87d39489d.png&amp;amp;w=314&amp;amp;sig=aba207635d5dc60b79563cb87df73fe8f454e1a8 314w, https://files.realpython.com/media/read_write.a4f87d39489d.png 629w&quot; sizes=&quot;75vw&quot; alt=&quot;read-write&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardf4a00f&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsef4a00f&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsef4a00f&quot;&gt;Plot the Read and Write Timings&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsef4a00f&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsef4a00f&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapsef4a00f&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardf4a00f&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;You can plot all the read and write timings on a single graph using the same plotting function:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot_with_legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cutoffs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_x_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb_x_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5_x_r&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;disk_x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb_x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5_x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;Read PNG&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;Read LMDB&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;Read HDF5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;Write PNG&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;Write LMDB&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s2&quot;&gt;&amp;quot;Write HDF5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Number of images&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Seconds&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;Log Store and Read Times&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;When you&amp;rsquo;re storing images as &lt;code&gt;.png&lt;/code&gt; files, there is a big difference between write and read times. However, with LMDB and HDF5, the difference is much less marked. Overall, even if read time is more critical than write time, there is a strong argument for storing images using LMDB or HDF5.&lt;/p&gt;
&lt;p&gt;Now that you&amp;rsquo;ve seen the performance benefits of LMDB and HDF5, let&amp;rsquo;s look at another crucial metric: disk usage.&lt;/p&gt;
&lt;h2 id=&quot;considering-disk-usage&quot;&gt;Considering Disk Usage&lt;/h2&gt;
&lt;p&gt;Speed is not the only performance metric you may be interested in. We&amp;rsquo;re already dealing with very large datasets, so disk space is also a very valid and relevant concern.&lt;/p&gt;
&lt;p&gt;Suppose you have an image dataset of 3TB. Presumably, you have them already on disk somewhere, unlike our CIFAR example, so by using an alternate storage method, you are essentially making a copy of them, which also has to be stored. Doing so will give you huge performance benefits when you use the images, but you&amp;rsquo;ll need to make sure you have enough disk space.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How much disk space do the various storage methods use?&lt;/strong&gt; Here&amp;rsquo;s the disk space used for each method for each quantity of images:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/store_mem.dadff24e67e3.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-75&quot; src=&quot;https://files.realpython.com/media/store_mem.dadff24e67e3.png&quot; width=&quot;554&quot; height=&quot;604&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/store_mem.dadff24e67e3.png&amp;amp;w=138&amp;amp;sig=0815866dbe443ab043a73fbfbc2e4f9dc0efc5a1 138w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/store_mem.dadff24e67e3.png&amp;amp;w=277&amp;amp;sig=2a566c7f8e20ee0b872cc24637639499743c2b53 277w, https://files.realpython.com/media/store_mem.dadff24e67e3.png 554w&quot; sizes=&quot;75vw&quot; alt=&quot;store-mem-image&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_cardf88fff&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsef88fff&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsef88fff&quot;&gt;Generating the Bar Plot for Disk Space Usage&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsef88fff&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsef88fff&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapsef88fff&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_cardf88fff&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;I used the Linux &lt;code&gt;du -h -c folder_name/*&lt;/code&gt; command to compute the disk usage on my system. There is some approximation inherent with this method due to rounding, but here&amp;rsquo;s the general comparison:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Memory used in KB&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;disk_mem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;204&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2004&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20032&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;200296&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;lmdb_mem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;420&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;39000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;393000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;hdf5_mem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;304&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2900&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;29000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;293000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;X&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;disk_mem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lmdb_mem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hdf5_mem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;ind&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;width&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.35&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;subplots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;figsize&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plots&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cutoffs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;plots&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;ind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bottom&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;row&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ylabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Memory in KB&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Disk memory used by method&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xticks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;PNG&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;LMDB&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;HDF5&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;yticks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;400000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;legend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plot&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;plots&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;10&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;100&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1,000&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;10,000&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;100,000&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;plt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;Both HDF5 and LMDB take up more disk space than if you store using normal &lt;code&gt;.png&lt;/code&gt; images. It&amp;rsquo;s important to note that both LMDB and HDF5 disk usage and performance &lt;strong&gt;depend highly on various factors, including operating system and, more critically, the size of the data you store.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;LMDB gains its efficiency from caching and taking advantage of OS page sizes. You don&amp;rsquo;t need to understand its inner workings, but note that &lt;strong&gt;with larger images, you will end up with significantly more disk usage with LMDB,&lt;/strong&gt; because images won&amp;rsquo;t fit on LMDB&amp;rsquo;s leaf pages, the regular storage location in the tree, and instead you will have many overflow pages. The LMDB bar in the chart above will shoot off the chart.&lt;/p&gt;
&lt;p&gt;Our 32x32x3 pixel images are relatively small compared to the average images you may use, and they allow for optimal LMDB performance.&lt;/p&gt;
&lt;p&gt;While we won&amp;rsquo;t explore it here experimentally, in my own experience with images of 256x256x3 or 512x512x3 pixels, HDF5 is usually slightly more efficient in terms of disk usage than LMDB. This is a good transition into the final section, a qualitative discussion of the differences between the methods.&lt;/p&gt;
&lt;h2 id=&quot;discussion&quot;&gt;Discussion&lt;/h2&gt;
&lt;p&gt;There are other distinguishing features of LMDB and HDF5 that are worth knowing about, and it&amp;rsquo;s also important to briefly discuss some of the criticisms of both methods. Several links are included along with the discussion if you want to learn more.&lt;/p&gt;
&lt;h3 id=&quot;parallel-access&quot;&gt;Parallel Access&lt;/h3&gt;
&lt;p&gt;A key comparison that we didn&amp;rsquo;t test in the experiments above is concurrent reads and writes. &lt;strong&gt;Often, with such large datasets, you may want to speed up your operation through parallelization.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In the majority of cases, you won&amp;rsquo;t be interested in reading parts of the same image at the same time, but you &lt;em&gt;will&lt;/em&gt; want to read multiple images at once. With this definition of concurrency, storing to disk as &lt;code&gt;.png&lt;/code&gt; files actually allows for complete concurrency. Nothing prevents you from reading several images at once from different threads, or writing multiple files at once, as long as the image names are different.&lt;/p&gt;
&lt;p&gt;How about LMDB? There can be multiple readers on an LMDB environment at a time, but only one writer, and writers do not block readers. You can read more about that at the &lt;a href=&quot;http://www.lmdb.tech/doc/&quot;&gt;LMDB technology website&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Multiple applications can access the same LMDB database at the same time, and multiple threads from the same process can also concurrently access the LMDB for reads. This allows for even quicker read times: if you divided all of CIFAR into ten sets, then you could set up ten processes to each read in one set, and it would divide the loading time by ten.&lt;/p&gt;
&lt;p&gt;HDF5 also offers parallel I/O, allowing concurrent reads and writes. However, in implementation, a write lock is held, and access is sequential, unless you have a parallel file system.&lt;/p&gt;
&lt;p&gt;There are two main options if you are working on such a system, which are discussed more in depth in &lt;a href=&quot;https://www.hdfgroup.org/2015/04/parallel-io-why-how-and-where-to-hdf5/&quot;&gt;this article by the HDF Group on parallel IO&lt;/a&gt;. It can get quite complicated, and the simplest option is to intelligently split your dataset into multiple HDF5 files, such that each process can deal with one &lt;code&gt;.h5&lt;/code&gt; file independently of the others.&lt;/p&gt;
&lt;h3 id=&quot;documentation&quot;&gt;Documentation&lt;/h3&gt;
&lt;p&gt;If you Google &lt;code&gt;lmdb&lt;/code&gt;, at least in the United Kingdom, the third search result is IMDb, the Internet Movie Database. That&amp;rsquo;s not what you were looking for! &lt;/p&gt;
&lt;p&gt;Actually, there is one main source of documentation for the Python binding of LMDB, which is hosted on &lt;a href=&quot;https://lmdb.readthedocs.io/en/release/#&quot;&gt;Read the Docs LMDB&lt;/a&gt;. While the Python package hasn&amp;rsquo;t even reached version &amp;gt; 0.94, it &lt;em&gt;is&lt;/em&gt; quite widely used and is considered stable.&lt;/p&gt;
&lt;p&gt;As for the LMDB technology itself, there is more detailed documentation &lt;a href=&quot;http://www.lmdb.tech/doc/index.html&quot;&gt;at the LMDB technology website&lt;/a&gt;, which can feel a bit like learning calculus in second grade, unless you start from their &lt;a href=&quot;http://www.lmdb.tech/doc/starting.html&quot;&gt;Getting Started&lt;/a&gt; page.&lt;/p&gt;
&lt;p&gt;For HDF5, there is very clear documentation at the &lt;a href=&quot;http://docs.h5py.org/en/stable/&quot;&gt;h5py docs&lt;/a&gt; site, as well as &lt;a href=&quot;https://www.christopherlovell.co.uk/blog/2016/04/27/h5py-intro.html&quot;&gt;a helpful blog post by Christopher Lovell&lt;/a&gt;, which is an excellent overview of how to use the &lt;code&gt;h5py&lt;/code&gt; package. The O&amp;rsquo;Reilly book, &lt;a href=&quot;https://realpython.com/asins/1449367836/&quot;&gt;Python and HDF5&lt;/a&gt; also is a good way to get started.&lt;/p&gt;
&lt;p&gt;While not as documented as perhaps a beginner would appreciate, both LMDB and HDF5 have large user communities, so a deeper Google search usually yields helpful results.&lt;/p&gt;
&lt;h3 id=&quot;a-more-critical-look-at-implementation&quot;&gt;A More Critical Look at Implementation&lt;/h3&gt;
&lt;p&gt;There is no utopia in storage systems, and both LMDB and HDF5 have their share of pitfalls.&lt;/p&gt;
&lt;p&gt;A key point to understand about LMDB is that new data is written &lt;strong&gt;without overwriting or moving existing data.&lt;/strong&gt; This is a design decision that allows for the extremely quick reads you witnessed in our experiments, and also guarantees data integrity and reliability without the additional need of keeping transaction logs.&lt;/p&gt;
&lt;p&gt;Remember, however, that you needed to define the &lt;code&gt;map_size&lt;/code&gt; parameter for memory allocation &lt;em&gt;before&lt;/em&gt; writing to a new database? This is where LMDB can be a hassle. Suppose you have created an LMDB database, and everything is wonderful. You&amp;rsquo;ve waited patiently for your enormous dataset to be packed into a LMDB.&lt;/p&gt;
&lt;p&gt;Then, later down the line, you remember that you need to add new data. Even with the buffer you specified on your &lt;code&gt;map_size&lt;/code&gt;, you may easily expect to see the &lt;code&gt;lmdb.MapFullError&lt;/code&gt; error. Unless you want to re-write your entire database, with the updated &lt;code&gt;map_size&lt;/code&gt;, you&amp;rsquo;ll have to store that new data in a separate LMDB file. Even though one transaction can span multiple LMDB files, having multiple files can still be a pain.&lt;/p&gt;
&lt;p&gt;Additionally, some systems have restrictions on how much memory may be claimed at once. In my own experience, working with high-performance computing (HPC) systems, this has proved extremely frustrating, and has often made me prefer HDF5 over LMDB.&lt;/p&gt;
&lt;p&gt;With both LMDB and HDF5, only the requested item is read into memory at once. With LMDB, key-unit pairs are read into memory one by one, while with HDF5, the &lt;code&gt;dataset&lt;/code&gt; object can be accessed like a Python array, with indexing &lt;code&gt;dataset[i]&lt;/code&gt;, ranges, &lt;code&gt;dataset[i:j]&lt;/code&gt; and other splicing &lt;code&gt;dataset[i:j:interval]&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Because of the way the systems are optimized, and depending on your operating system, the order in which you access items can impact performance. &lt;/p&gt;
&lt;p&gt;In my experience, it&amp;rsquo;s generally true that for LMDB, you may get better performance when accessing items sequentially by key (key-value pairs being kept in memory ordered alphanumerically by key), and that for HDF5, accessing large ranges will perform better than reading every element of the dataset one by one using the following:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Slightly slower&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Read the ith value in the dataset, one at a time&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;do_something_with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# This is better&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dataset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:]&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;do_something_with&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you are considering a choice of file storage format to write your software around, it would be remiss not to mention &lt;a href=&quot;https://cyrille.rossant.net/moving-away-hdf5/&quot;&gt;Moving away from HDF5&lt;/a&gt; by Cyrille Rossant on the pitfalls of HDF5, and Konrad Hinsen&amp;rsquo;s response &lt;a href=&quot;http://blog.khinsen.net/posts/2016/01/07/on-hdf5-and-the-future-of-data-management/&quot;&gt;On HDF5 and the future of data management&lt;/a&gt;, which shows how some of the pitfalls can be avoided in his own use cases with many smaller datasets rather than a few enormous ones. Note that a relatively smaller dataset is still several GB in size.&lt;/p&gt;
&lt;h3 id=&quot;integration-with-other-libraries&quot;&gt;Integration With Other Libraries&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;re dealing with really large datasets, it&amp;rsquo;s highly likely that you&amp;rsquo;ll be doing something significant with them. It&amp;rsquo;s worthwhile to consider deep learning libraries and what kind of integration there is with LMDB and HDF5.&lt;/p&gt;
&lt;p&gt;First of all, all libraries support reading images from disk as &lt;code&gt;.png&lt;/code&gt; files, as long as you convert them into NumPy arrays of the expected format. This holds true for all the methods, and we have already seen above that it is relatively straightforward to read in images as arrays.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Here are several of the most popular deep learning libraries and their LMDB and HDF5 integration:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://caffe.berkeleyvision.org/&quot;&gt;&lt;strong&gt;Caffe&lt;/strong&gt;&lt;/a&gt; has a stable, well-supported LMDB integration, and it handles the reading step transparently. The LMDB layer can also easily be replaced with a HDF5 database.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.tensorflow.org/tutorials/keras/save_and_restore_models&quot;&gt;&lt;strong&gt;Keras&lt;/strong&gt;&lt;/a&gt; uses the HDF5 format to save and restore models. This implies that TensorFlow can as well.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://www.tensorflow.org/api_docs/python/tf/contrib/data/LMDBDataset&quot;&gt;&lt;strong&gt;TensorFlow&lt;/strong&gt;&lt;/a&gt; has a built-in class &lt;code&gt;LMDBDataset&lt;/code&gt; that provides an interface for reading in input data from an LMDB file and can produce iterators and tensors in batches. TensorFlow does &lt;em&gt;not&lt;/em&gt; have a built-in class for HDF5, but one can be written that inherits from the &lt;code&gt;Dataset&lt;/code&gt; class. I personally use a custom class altogether that is designed for optimal read access based on the way I structure my HDF5 files.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;http://deeplearning.net/software/theano/&quot;&gt;&lt;strong&gt;Theano&lt;/strong&gt;&lt;/a&gt; does not natively support any particular file format or database, but as previously stated, can use anything as long as it is read in as an N-dimensional array.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;While far from comprehensive, this hopefully gives you a feel for the LMDB/HDF5 integration by some key deep learning libraries.&lt;/p&gt;
&lt;h2 id=&quot;a-few-personal-insights-on-storing-images-in-python&quot;&gt;A Few Personal Insights on Storing Images in Python&lt;/h2&gt;
&lt;p&gt;In my own daily work analyzing terabytes of medical images, I use both LMDB and HDF5, and have learned that, with any storage method, &lt;strong&gt;forethought is critical&lt;/strong&gt;. &lt;/p&gt;
&lt;p&gt;Often, models need to be trained using k-fold cross validation, which involves splitting the entire dataset into k-sets (k typically being 10), and k models being trained, each with a different k-set used as test set. This ensures that the model is not overfitting the dataset, or, in other words, unable to make good predictions on unseen data.&lt;/p&gt;
&lt;p&gt;A standard way to craft a k-set is to put an equal representation of each type of data represented in the dataset in each k-set. Thus, saving each k-set into a separate HDF5 dataset maximizes efficiency. Sometimes, a single k-set cannot be loaded into memory at once, so even the ordering of data within a dataset requires some forethought.&lt;/p&gt;
&lt;p&gt;With LMDB, I similarly am careful to plan ahead before creating the database(s). There are a few good questions worth asking before you save images:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How can I save the images such that most of the reads will be sequential? &lt;/li&gt;
&lt;li&gt;What are good keys? &lt;/li&gt;
&lt;li&gt;How can I calculate a good &lt;code&gt;map_size&lt;/code&gt;, anticipating potential future changes in the dataset? &lt;/li&gt;
&lt;li&gt;How large can a single transaction be, and how should transactions be subdivided?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Regardless of the storage method, when you&amp;rsquo;re dealing with large image datasets, a little planning goes a long way.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ve made it to the end! You&amp;rsquo;ve now had a bird&amp;rsquo;s eye view of a large topic.&lt;/p&gt;
&lt;p&gt;In this article, you&amp;rsquo;ve been introduced to three ways of storing and accessing lots of images in Python, and perhaps had a chance to play with some of them. All the code for this article is in a &lt;a href=&quot;https://github.com/realpython/materials/blob/storing-images/storing-images/storing_images.ipynb&quot;&gt;Jupyter notebook here&lt;/a&gt; or &lt;a href=&quot;https://github.com/realpython/materials/blob/storing-images/storing-images/storing_images.py&quot;&gt;Python script here&lt;/a&gt;. Run at your own risk, as a few GB of your disk space will be overtaken by little square images of cars, boats, and so on.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve seen evidence of how various storage methods can drastically affect read and write time, as well as a few pros and cons of the three methods considered in this article. While storing images as &lt;code&gt;.png&lt;/code&gt; files may be the most intuitive, there are large performance benefits to considering methods such as HDF5 or LMDB.&lt;/p&gt;
&lt;p&gt;Feel free to discuss in the comment section the excellent storage methods not covered in this article, such as &lt;a href=&quot;https://github.com/google/leveldb&quot;&gt;LevelDB&lt;/a&gt;, &lt;a href=&quot;https://github.com/wesm/feather&quot;&gt;Feather&lt;/a&gt;, &lt;a href=&quot;https://tiledb.io/&quot;&gt;TileDB&lt;/a&gt;, &lt;a href=&quot;https://blog.dgraph.io/post/badger/&quot;&gt;Badger&lt;/a&gt;, &lt;a href=&quot;https://godoc.org/github.com/boltdb/bolt&quot;&gt;BoltDB&lt;/a&gt;, or anything else. &lt;strong&gt;There is no perfect storage method, and the best method depends on your specific dataset and use cases.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;Here are some references related to the three methods covered in this article:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://lmdb.readthedocs.io/en/release/#&quot;&gt;Python binding for LMDB&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.lmdb.tech/doc/starting.html&quot;&gt;LMDB documentation: Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.h5py.org/&quot;&gt;Python binding for HDF5 (h5py)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.hdfgroup.org/solutions/hdf5/&quot;&gt;The HDF5 Group&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/asins/1449367836/&quot;&gt;&amp;ldquo;Python and HDF5&amp;rdquo; from O&amp;rsquo;Reilly&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pillow.readthedocs.io/en/stable/&quot;&gt;Pillow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You may also appreciate  &lt;a href=&quot;https://www.osti.gov/biblio/1335300&quot;&gt;&amp;ldquo;An analysis of image storage systems for scalable training of deep neural networks&amp;rdquo;&lt;/a&gt; by Lim, Young, and Patton. That paper covers experiments similar to the ones in this article, but on a much larger scale, considering cold and warm cache as well as other factors.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Writing Cleaner Python Code With PyLint</title>
      <id>https://realpython.com/courses/writing-cleaner-python-code-pylint/</id>
      <link href="https://realpython.com/courses/writing-cleaner-python-code-pylint/"/>
      <updated>2019-05-14T14:00:00+00:00</updated>
      <summary>In this video series you&#39;ll see how to install and set up the PyLint code linter tool. You&#39;ll learn why you should use code linters like PyLint, Flake8, PyFlakes, or other static analysis tools—and how they can help you write cleaner and more Pythonic code.</summary>
      <content type="html">
        &lt;p&gt;PyLint is a well-known static analysis tool for Python 2 and 3. It has a number of useful features, like checking your code for compliance with the PEP 8 Python style guide. It makes sure that your code follows the code style guide and it can also automatically identify common bugs and errors in your Python code.&lt;/p&gt;
&lt;p&gt;In this video series you&amp;rsquo;ll see how to install and set up the PyLint code linter tool. You&amp;rsquo;ll learn why you should use code linters like PyLint, Flake8, PyFlakes, or other static analysis tools&amp;mdash;and how they can help you write cleaner and more Pythonic code. &lt;/p&gt;
&lt;p&gt;You can get this setup up and running in a few minutes and it&amp;rsquo;ll quickly help you write better and cleaner Python code.&lt;/p&gt;
&lt;h3 id=&quot;additional-resources&quot;&gt;Additional Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/learning-paths/writing-pythonic-code/&quot;&gt;&amp;ldquo;Write More Pythonic Code&amp;rdquo; Learning Path&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-code-quality/&quot;&gt;Python Code Quality: Tools &amp;amp; Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.pylint.org/&quot;&gt;PyLint Website&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Playing and Recording Sound in Python</title>
      <id>https://realpython.com/playing-and-recording-sound-python/</id>
      <link href="https://realpython.com/playing-and-recording-sound-python/"/>
      <updated>2019-05-13T14:00:00+00:00</updated>
      <summary>In this tutorial, you&#39;ll learn about libraries that can be used for playing and recording sound in Python, such as PyAudio and python-sounddevice. You&#39;ll also see code snippets for playing and recording sound files and arrays, as well as for converting between different sound file formats.</summary>
      <content type="html">
        &lt;p&gt;If you want to use Python to play or record sound, then you&amp;rsquo;ve come to the right place! In this tutorial, you&amp;rsquo;ll learn how to play and record sound in Python using some of the most popular audio libraries. You will learn about the most straight-forward methods for playing and recording sound first, and then you&amp;rsquo;ll learn about some libraries that offer some more functionality in exchange for a few extra lines of code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this tutorial, you&amp;rsquo;ll know how to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Play MP3 and WAV files, as well as a range of other audio formats&lt;/li&gt;
&lt;li&gt;Play NumPy and Python arrays containing sound&lt;/li&gt;
&lt;li&gt;Record sound using Python&lt;/li&gt;
&lt;li&gt;Save your recordings or audio files in a range of different file formats&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a comprehensive list of audio-related Python libraries, have a look at the &lt;a href=&quot;https://wiki.python.org/moin/Audio/&quot;&gt;wiki page on audio in Python&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-tricks-sample&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a chapter from Python Tricks: The Book&lt;/a&gt; that shows you Python&#39;s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;playing-audio-files&quot;&gt;Playing Audio Files&lt;/h2&gt;
&lt;p&gt;Below, you&amp;rsquo;ll see how to play audio files with a selection of Python libraries. A few of these libraries let you play a range of audio formats, including MP3 and NumPy arrays. All of the libraries below let you play WAV files, some with a few more lines of code than others:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;playsound&lt;/code&gt;&lt;/strong&gt; is the most straightforward package to use if you simply want to play a WAV or MP3 file. It offers no functionality other than simple playback. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;simpleaudio&lt;/code&gt;&lt;/strong&gt; lets you play WAV files and NumPy arrays, and gives you options to check whether a file is still playing. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;winsound&lt;/code&gt;&lt;/strong&gt; allows you to play WAV files or beep your speakers, but it works only on Windows. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;python-sounddevice&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;pyaudio&lt;/code&gt;&lt;/strong&gt; provide bindings for the PortAudio library for cross-platform playback of WAV files. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;pydub&lt;/code&gt;&lt;/strong&gt; requires &lt;strong&gt;&lt;code&gt;pyaudio&lt;/code&gt;&lt;/strong&gt; for audio playback, but with &lt;code&gt;ffmpeg&lt;/code&gt; installed, it lets you play a large range of audio formats with only a few lines of code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s have a look at these libraries for audio playback one by one.&lt;/p&gt;
&lt;h3 id=&quot;playsound&quot;&gt;&lt;code&gt;playsound&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://pypi.org/project/playsound/&quot;&gt;&lt;code&gt;playsound&lt;/code&gt;&lt;/a&gt; is a &lt;a href=&quot;https://pypi.org/project/playsound/&quot;&gt;&amp;ldquo;pure Python, cross platform, single function module with no dependencies for playing sounds.&amp;rdquo;&lt;/a&gt;
With this module, you can play a sound file with a single line of code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;playsound&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;playsound&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;playsound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.wav&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;a href=&quot;https://pypi.org/project/playsound/&quot;&gt;documentation&lt;/a&gt; of &lt;code&gt;playsound&lt;/code&gt; states that it has been tested on WAV and MP3 files, but it may work for other file formats as well.&lt;/p&gt;
&lt;p&gt;This library was last updated in June 2017. It seems to work well at the time of writing this article, but it&amp;rsquo;s not clear whether it will still support newer Python releases.&lt;/p&gt;
&lt;h3 id=&quot;simpleaudio&quot;&gt;&lt;code&gt;simpleaudio&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://simpleaudio.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;simpleaudio&lt;/code&gt;&lt;/a&gt; is a cross-platform library for playback of (mono and stereo) WAV files with no dependencies. The following code can be used to play a WAV file, and wait for the file to finish playing before terminating the script:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;simpleaudio&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sa&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.wav&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wave_obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sa&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WaveObject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_wave_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;play_obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wave_obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;play_obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait_done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Wait until sound has finished playing&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;WAV files contain a &lt;strong&gt;sequence of bits&lt;/strong&gt; representing the raw audio data, as well as &lt;strong&gt;headers with metadata&lt;/strong&gt; in RIFF (Resource Interchange File Format) format. &lt;/p&gt;
&lt;p&gt;For CD recordings, the industry standard is to store each audio sample (an individual audio datapoint relating to air pressure) as a &lt;strong&gt;16-bit&lt;/strong&gt; value, at &lt;strong&gt;44100&lt;/strong&gt; samples per second. &lt;/p&gt;
&lt;p&gt;To reduce file size, it may be sufficient to store some recordings (for example of human speech) at a lower sampling rate, such as 8000 samples per second, although this does mean that higher sound frequencies may not be as accurately represented.&lt;/p&gt;
&lt;p&gt;A few of the libraries discussed in this tutorial play and record &lt;strong&gt;&lt;code&gt;bytes&lt;/code&gt;&lt;/strong&gt; objects, whereas others use &lt;strong&gt;NumPy arrays&lt;/strong&gt; to store raw audio data. &lt;/p&gt;
&lt;p&gt;Both correspond to a sequence of data points that can be played back at a specified sample rate in order to play a sound. For a &lt;strong&gt;&lt;code&gt;bytes&lt;/code&gt;&lt;/strong&gt; object, each sample is stored as a set of two 8-bit values, whereas in a NumPy array, each element can contain a 16-bit value corresponding to a single sample. &lt;/p&gt;
&lt;p&gt;An important difference between these two data types is that &lt;strong&gt;&lt;code&gt;bytes&lt;/code&gt; objects are immutable&lt;/strong&gt;, whereas &lt;strong&gt;NumPy arrays are mutable&lt;/strong&gt;, making the latter more suitable for generating sounds and for more complex signal processing. For more information on how to work with NumPy, have a look at our &lt;a href=&quot;https://realpython.com/tutorials/numpy/&quot;&gt;NumPy tutorials&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;simpleaudio&lt;/code&gt; allows you to play NumPy and Python arrays and &lt;code&gt;bytes&lt;/code&gt; objects using &lt;code&gt;simpleaudio.play_buffer()&lt;/code&gt;. Make sure you have NumPy installed for the following example to work, as well as &lt;code&gt;simpleaudio&lt;/code&gt;. (With &lt;code&gt;pip&lt;/code&gt; installed, you can do this by running &lt;code&gt;pip install numpy&lt;/code&gt; from your console.) &lt;/p&gt;
&lt;p&gt;For more information on how to use &lt;code&gt;pip&lt;/code&gt; for installing packages, have a look at &lt;a href=&quot;https://realpython.com/pipenv-guide/&quot;&gt;Pipenv: A Guide to the New Python Packaging Tool&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Below you&amp;rsquo;ll see how to generate a NumPy array corresponding to a 440 Hz tone and play it back using &lt;code&gt;simpleaudio.play_buffer()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;numpy&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;np&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;simpleaudio&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sa&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;frequency&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;440&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Our played note will be 440 Hz&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44100&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 44100 samples per second&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Note duration of 3 seconds&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Generate array with seconds*sample_rate steps, ranging between 0 and seconds&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;linspace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Generate a 440 Hz sine wave&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;note&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frequency&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Ensure that highest value is in 16-bit range&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;audio&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;note&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;note&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Convert to 16-bit data&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;audio&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;audio&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;astype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;int16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Start playback&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;play_obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sa&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play_buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;audio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Wait for playback to finish before exiting&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;play_obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait_done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, let&amp;rsquo;s see how you can use &lt;code&gt;winsound&lt;/code&gt; to play WAV files on a Windows machine.&lt;/p&gt;
&lt;h3 id=&quot;winsound&quot;&gt;&lt;code&gt;winsound&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;If you use Windows, you can use the built-in &lt;a href=&quot;https://docs.python.org/3.6/library/winsound.html&quot;&gt;&lt;code&gt;winsound&lt;/code&gt;&lt;/a&gt; module to access its basic sound-playing machinery. Playing a WAV file can be done in a few lines of code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;winsound&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.wav&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;winsound&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PlaySound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;winsound&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SND_FILENAME&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;winsound&lt;/code&gt; does not support playback of any files other than WAV files. It does allow you to beep your speakers using &lt;code&gt;winsound.Beep(frequency, duration)&lt;/code&gt;. For example, you can beep a 1000 Hz tone for 100 milliseconds with the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;winsound&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;winsound&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Beep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Beep at 1000 Hz for 100 ms&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, you&amp;rsquo;ll learn how to use the &lt;code&gt;python-sounddevice&lt;/code&gt; module for cross-platform audio playback.&lt;/p&gt;
&lt;h3 id=&quot;python-sounddevice&quot;&gt;&lt;code&gt;python-sounddevice&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;As stated in its documentation, &lt;a href=&quot;https://python-sounddevice.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;python-sounddevice&lt;/code&gt;&lt;/a&gt; &amp;ldquo;provides bindings for the PortAudio library and a few convenience functions to play and record NumPy arrays containing audio signals&amp;rdquo;. In order to play WAV files, &lt;code&gt;numpy&lt;/code&gt; and &lt;code&gt;soundfile&lt;/code&gt; need to be installed, to open WAV files as NumPy arrays. &lt;/p&gt;
&lt;p&gt;With &lt;code&gt;python-sounddevice&lt;/code&gt;, &lt;code&gt;numpy&lt;/code&gt;, and &lt;code&gt;soundfile&lt;/code&gt; installed, you can now read a WAV file as a NumPy array and play it back:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;soundfile&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sf&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.wav&amp;#39;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Extract data and sampling rate from file&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dtype&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;float32&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  
&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Wait until file is done playing&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The line containing &lt;code&gt;sf.read()&lt;/code&gt; extracts the raw audio data, as well as the sampling rate of the file as stored in its RIFF header, and &lt;code&gt;sounddevice.wait()&lt;/code&gt; ensures that the script is only terminated after the sound finishes playing.&lt;/p&gt;
&lt;p&gt;Next, we&amp;rsquo;ll learn how to use &lt;code&gt;pydub&lt;/code&gt; to play sound. With the right dependencies installed, it allows you to play a wide range of audio files, and it offers you more options for working with audio than &lt;code&gt;python-soundevice&lt;/code&gt; does.&lt;/p&gt;
&lt;h3 id=&quot;pydub&quot;&gt;&lt;code&gt;pydub&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Although &lt;a href=&quot;https://www.github.com/jiaaro/pydub&quot;&gt;&lt;code&gt;pydub&lt;/code&gt;&lt;/a&gt; can open and save WAV files without any dependencies, you need to have an audio playback package installed to play audio. &lt;code&gt;simpleaudio&lt;/code&gt; is strongly recommended, but &lt;code&gt;pyaudio&lt;/code&gt;, &lt;code&gt;ffplay&lt;/code&gt;, and &lt;code&gt;avplay&lt;/code&gt; are alternative options. &lt;/p&gt;
&lt;p&gt;The following code can be used to play a WAV file with &lt;code&gt;pydub&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AudioSegment&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydub.playback&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AudioSegment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_wav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.wav&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In order to play back other audio types, such as MP3 files, &lt;a href=&quot;https://www.ffmpeg.org/download.html&quot;&gt;&lt;code&gt;ffmpeg&lt;/code&gt;&lt;/a&gt; or &lt;a href=&quot;https://libav.org/download/&quot;&gt;&lt;code&gt;libav&lt;/code&gt;&lt;/a&gt; should be installed. Have a look at the &lt;a href=&quot;https://github.com/jiaaro/pydub#getting-ffmpeg-set-up&quot;&gt;documentation&lt;/a&gt; of &lt;code&gt;pydub&lt;/code&gt; for instructions. As an alternative to the steps described in the documentation, &lt;a href=&quot;https://github.com/kkroening/ffmpeg-python&quot;&gt;&lt;code&gt;ffmpeg-python&lt;/code&gt;&lt;/a&gt; provides bindings for &lt;code&gt;ffmpeg&lt;/code&gt;, and can be installed using pip:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pip install ffmpeg-python
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With &lt;code&gt;ffmpeg&lt;/code&gt; installed, playing back an MP3 file requires only a small change in our earlier code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AudioSegment&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydub.playback&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AudioSegment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_mp3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.mp3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;play&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using the &lt;code&gt;AudioSegment.from_file(filename, filetype)&lt;/code&gt; construction, you can play any type of &lt;a href=&quot;http://www.ffmpeg.org/general.html#File-Formats&quot;&gt;audio file that &lt;code&gt;ffmpeg&lt;/code&gt; supports&lt;/a&gt;. For example, you may play a WMA file using the ollowing: &lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AudioSegment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.wma&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;wma&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In addition to playing back sound files, &lt;code&gt;pydub&lt;/code&gt; lets you save audio in different file formats (more on this later), slice audio, calculate the length of audio files, fade in or out, and apply cross-fades. &lt;/p&gt;
&lt;p&gt;&lt;code&gt;AudioSegment.reverse()&lt;/code&gt; creates a copy of the AudioSegment that plays backwards, which the documentation describes as &lt;a href=&quot;https://github.com/jiaaro/pydub/blob/master/API.markdown&quot;&gt;&amp;ldquo;useful for Pink Floyd, screwing around, and some audio processing algorithms.&amp;rdquo;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;pyaudio&quot;&gt;&lt;code&gt;pyaudio&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://people.csail.mit.edu/hubert/pyaudio/&quot;&gt;&lt;code&gt;pyaudio&lt;/code&gt;&lt;/a&gt; provides bindings for PortAudio, the cross-platform audio I/O library. This means that you can use &lt;code&gt;pyaudio&lt;/code&gt; to play and record audio on a variety of platforms, including Windows, Linux, and Mac. With &lt;code&gt;pyaudio&lt;/code&gt;, playing audio is done by writing to a &lt;code&gt;.Stream&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyaudio&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;wave&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.wav&amp;#39;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Set chunk size of 1024 samples per data frame&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;  

&lt;span class=&quot;c1&quot;&gt;# Open the sound file &lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wave&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;rb&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create an interface to PortAudio&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyaudio&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyAudio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Open a .Stream object to write the WAV file to&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# &amp;#39;output = True&amp;#39; indicates that the sound will be played rather than recorded&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_format_from_width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getsampwidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getnchannels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;rate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getframerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;output&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Read data in chunks&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readframes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Play the sound by writing the audio data to the stream&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readframes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Close and terminate the stream&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;terminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you may have noticed, playing sounds with &lt;code&gt;pyaudio&lt;/code&gt; is a bit more complex than playing sounds with the libraries you&amp;rsquo;ve seen earlier. This means that it may not be your first choice if you just want to play a sound effect in your Python application. &lt;/p&gt;
&lt;p&gt;However, because &lt;code&gt;pyaudio&lt;/code&gt; gives you more low-level control, it is possible to get and set parameters for your input and output devices, and to check your CPU load and input or output latency. &lt;/p&gt;
&lt;p&gt;It also allows you to play and record audio in callback mode, where a specified callback function is called when new data is required for playback, or available for recording. These options make &lt;code&gt;pyaudio&lt;/code&gt; a suitable library to use if your audio needs go beyond simple playback.&lt;/p&gt;
&lt;p&gt;Now that you&amp;rsquo;ve seen how you can use a number of different libraries to play audio, it&amp;rsquo;s time to see how you can use Python to record audio yourself.&lt;/p&gt;
&lt;h2 id=&quot;recording-audio&quot;&gt;Recording Audio&lt;/h2&gt;
&lt;p&gt;The &lt;a href=&quot;https://python-sounddevice.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;python-sounddevice&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://people.csail.mit.edu/hubert/pyaudio/&quot;&gt;&lt;code&gt;pyaudio&lt;/code&gt;&lt;/a&gt; libraries provide ways to record audio with Python. &lt;code&gt;python-sounddevice&lt;/code&gt; records to NumPy arrays and &lt;code&gt;pyaudio&lt;/code&gt; records to &lt;code&gt;bytes&lt;/code&gt; objects. Both of these can be stored as WAV files using the &lt;code&gt;scipy&lt;/code&gt; and &lt;code&gt;wave&lt;/code&gt; libraries, respectively.&lt;/p&gt;
&lt;h3 id=&quot;python-sounddevice_1&quot;&gt;&lt;code&gt;python-sounddevice&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://python-sounddevice.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;python-sounddevice&lt;/code&gt;&lt;/a&gt; allows you to record audio from your microphone and store it as a NumPy array. This is a handy datatype for sound processing that can be converted to WAV format for storage using the &lt;a href=&quot;https://docs.scipy.org/doc/scipy/reference/generated/scipy.io.wavfile.write.html&quot;&gt;&lt;code&gt;scipy.io.wavfile&lt;/code&gt;&lt;/a&gt; module. Make sure to install the &lt;code&gt;scipy&lt;/code&gt; module for the following example (&lt;code&gt;pip install scipy&lt;/code&gt;). This automatically installs NumPy as one of its dependencies:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sounddevice&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sd&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;scipy.io.wavfile&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44100&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Sample rate&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Duration of recording&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;myrecording&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rec&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;samplerate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sd&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Wait until recording is finished&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;output.wav&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myrecording&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Save as WAV file &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;pyaudio_1&quot;&gt;&lt;code&gt;pyaudio&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;#pyaudio&quot;&gt;Earlier in this article&lt;/a&gt;, you learned how to play sounds by reading a &lt;a href=&quot;https://people.csail.mit.edu/hubert/pyaudio/docs/#class-stream&quot;&gt;&lt;code&gt;pyaudio.Stream()&lt;/code&gt;&lt;/a&gt;. Recording audio can be done by writing to this stream instead:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyaudio&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;wave&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1024&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Record in chunks of 1024 samples&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sample_format&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyaudio&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;paInt16&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# 16 bits per sample&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44100&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Record at 44100 samples per second&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;output.wav&amp;quot;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyaudio&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyAudio&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Create an interface to PortAudio&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Recording&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;rate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;frames_per_buffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;nb&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;frames&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Initialize array to store frames&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Store data in chunks for 3 seconds&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;frames&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Stop and close the stream &lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stop_stream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;stream&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Terminate the PortAudio interface&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;terminate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Finished recording&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Save the recorded data as a WAV file&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wave&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;wb&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setnchannels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;channels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setsampwidth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_sample_size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sample_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setframerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;writeframes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;frames&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;wf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that you&amp;rsquo;ve seen how to record audio with &lt;code&gt;python-sounddevice&lt;/code&gt; and &lt;code&gt;pyaudio&lt;/code&gt;, you&amp;rsquo;ll learn how to convert your recording (or any other audio files) to a range of different audio formats.&lt;/p&gt;
&lt;h2 id=&quot;saving-and-converting-audio&quot;&gt;Saving and Converting Audio&lt;/h2&gt;
&lt;p&gt;You &lt;a href=&quot;#python-sounddevice&quot;&gt;saw earlier&lt;/a&gt; that you can use the &lt;code&gt;scipy.io.wavfile&lt;/code&gt; module to store NumPy arrays as WAV files. The &lt;a href=&quot;https://pypi.org/project/wavio/&quot;&gt;&lt;code&gt;wavio&lt;/code&gt; module&lt;/a&gt; similarly lets you convert between WAV files and NumPy arrays. If you want to store your audio in a different file format, &lt;a href=&quot;https://github.com/jiaaro/pydub&quot;&gt;&lt;code&gt;pydub&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://pypi.org/project/SoundFile/&quot;&gt;&lt;code&gt;soundfile&lt;/code&gt;&lt;/a&gt; come in handy, as they allow you to read and write a range of popular file formats (such as MP3, FLAC, WMA and FLV).&lt;/p&gt;
&lt;h3 id=&quot;wavio&quot;&gt;&lt;code&gt;wavio&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;This module depends on &lt;code&gt;numpy&lt;/code&gt; and lets you read WAV files as NumPy arrays, and save NumPy arrays as WAV files.&lt;/p&gt;
&lt;p&gt;To save a NumPy array as a WAV file, you can use &lt;code&gt;wavio.write()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;wavio&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;wavio&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;myfile.wav&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_np_array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sampwidth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, &lt;code&gt;my_np_array&lt;/code&gt; is a NumPy array containing audio, &lt;code&gt;fs&lt;/code&gt; is the sample rate of the recording (usually 44100 or 44800 Hz), and &lt;code&gt;sampwidth&lt;/code&gt; is the sampling width of the audio (the number of bytes per sample, typically 1 or 2 bytes).&lt;/p&gt;
&lt;h3 id=&quot;soundfile&quot;&gt;&lt;code&gt;soundfile&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;a href=&quot;https://pypi.org/project/SoundFile/&quot;&gt;&lt;code&gt;soundfile&lt;/code&gt;&lt;/a&gt; library can read and write all &lt;a href=&quot;http://www.mega-nerd.com/libsndfile/#Features&quot;&gt;file formats supported by &lt;code&gt;libsndfile&lt;/code&gt;&lt;/a&gt;. Although it can&amp;rsquo;t play back audio, it allows you to convert audio from and to FLAC, AIFF, and a few audio formats that are less common . To convert a WAV file to FLAC, you can use the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;soundfile&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sf&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Extract audio data and sampling rate from file &lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.wav&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; 
&lt;span class=&quot;c1&quot;&gt;# Save as FLAC file at correct sampling rate&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.flac&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Similar code will work for converting between other file formats supported by &lt;code&gt;libsndfile&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;pydub_1&quot;&gt;&lt;code&gt;pydub&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/jiaaro/pydub&quot;&gt;&lt;code&gt;pydub&lt;/code&gt;&lt;/a&gt; lets you save audio in &lt;a href=&quot;https://www.ffmpeg.org/general.html#File-Formats&quot;&gt;any format that &lt;code&gt;ffmpeg&lt;/code&gt; supports&lt;/a&gt;, which includes nearly all audio types you might encounter in your daily life. For example, you can convert your WAV file to MP3 with the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AudioSegment&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AudioSegment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_wav&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.wav&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;export&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.mp3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;mp3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using &lt;code&gt;AudioSegment.from_file()&lt;/code&gt; is a more general way of loading audio files. For example, if you want to convert your file back from MP3 to WAV, you can do the following:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pydub&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AudioSegment&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AudioSegment&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.mp3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;mp3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sound&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;export&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myfile.wav&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;wav&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code should work for any audio file format &lt;a href=&quot;https://www.ffmpeg.org/general.html#File-Formats&quot;&gt;that &lt;code&gt;ffmpeg&lt;/code&gt; supports&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;comparison-of-audio-libraries&quot;&gt;Comparison of Audio Libraries&lt;/h2&gt;
&lt;p&gt;Below is handy table that compares the functionality of the libraries discussed in this tutorial:&lt;/p&gt;
&lt;div class=&quot;table-responsive&quot;&gt;
&lt;table class=&quot;table table-hover&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Library&lt;/th&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Playback&lt;/th&gt;
&lt;th&gt;Record&lt;/th&gt;
&lt;th&gt;Convert&lt;/th&gt;
&lt;th&gt;Dependencies&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://pypi.org/project/playsound/&quot;&gt;&lt;code&gt;playsound&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cross-platform&lt;/td&gt;
&lt;td&gt;WAV, MP3&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://simpleaudio.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;simpleaudio&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cross-platform&lt;/td&gt;
&lt;td&gt;WAV, array, &lt;code&gt;bytes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://docs.python.org/3.6/library/winsound.html&quot;&gt;&lt;code&gt;winsound&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;WAV&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://python-sounddevice.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;sounddevice&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cross-platform&lt;/td&gt;
&lt;td&gt;NumPy array&lt;/td&gt;
&lt;td&gt;NumPy array&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;code&gt;numpy&lt;/code&gt;, &lt;code&gt;soundfile&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;[pydub](https://github.com/jiaaro/pydub)&quot;&gt;&lt;code&gt;pydub&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cross-platform&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;http://www.ffmpeg.org/general.html#File-Formats&quot;&gt;Any type supported by &lt;code&gt;ffmpeg&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;http://www.ffmpeg.org/general.html#File-Formats&quot;&gt;Any type supported by &lt;code&gt;ffmpeg&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;simpleaudio&lt;/code&gt;, &lt;code&gt;ffmpeg&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://people.csail.mit.edu/hubert/pyaudio/&quot;&gt;&lt;code&gt;pyaudio&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cross-platform&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bytes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bytes&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;code&gt;wave&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://pypi.org/project/wavio/&quot;&gt;&lt;code&gt;wavio&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cross-platform&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;WAV, NumPy array&lt;/td&gt;
&lt;td&gt;&lt;code&gt;numpy&lt;/code&gt;, &lt;code&gt;wave&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href=&quot;https://pypi.org/project/SoundFile/&quot;&gt;&lt;code&gt;soundfile&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;Cross-platform&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;&lt;a href=&quot;http://www.mega-nerd.com/libsndfile/#Features&quot;&gt;Any type supported by &lt;code&gt;libsndfile&lt;/code&gt;&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CFFI&lt;/code&gt;, &lt;code&gt;libsndfile&lt;/code&gt;, &lt;code&gt;numpy&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;The libraries that are included in this tutorial are chosen for their ease of use and popularity. For a more comprehensive list of audio libraries for Python, have a look at the &lt;a href=&quot;https://wiki.python.org/moin/Audio/&quot;&gt;wiki page on audio in Python&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;conclusion-playing-and-recording-sound-in-python&quot;&gt;Conclusion: Playing and Recording Sound in Python&lt;/h2&gt;
&lt;p&gt;In this tutorial, you learned how to use some of the most popular audio libraries to play and record audio in Python. You also saw how to save your audio in a range of different formats.&lt;/p&gt;
&lt;p&gt;You are now able to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Play&lt;/strong&gt; a large range of audio formats, including WAV, MP3 and NumPy arrays&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Record&lt;/strong&gt; audio from your microphone to a NumPy or Python array&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Store&lt;/strong&gt; your recorded audio a range of different formats, including WAV and MP3&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Convert&lt;/strong&gt; your sound files to a range of different audio formats&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You now have the information you need to help you decide which libraries to use to start working with audio in Python. Go forth, and develop some awesome audio applications!&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Python Community Interview With Bob and Julian of PyBites</title>
      <id>https://realpython.com/python-community-interview-bob-and-julian-pybites/</id>
      <link href="https://realpython.com/python-community-interview-bob-and-julian-pybites/"/>
      <updated>2019-05-08T14:00:00+00:00</updated>
      <summary>Bob Belderbos and Julian Sequeira are the co-founders of PyBites. In this interview, we discuss how PyBites got started and what they have in store for its future. We’ll also look into Bob’s secret love of drawing and Julian’s not so secret love of a good pint!</summary>
      <content type="html">
        &lt;p&gt;This week, I&amp;rsquo;m joined by &lt;a href=&quot;https://twitter.com/bbelderbos&quot;&gt;Bob Belderbos&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/_juliansequeira&quot;&gt;Julian Sequeira&lt;/a&gt; of PyBites fame. Bob is a Software Developer at Oracle, Spain. Julian is a Data Center Technician at Amazon Web Services, in Australia. &lt;/p&gt;
&lt;p&gt;Join us as we discuss how &lt;a href=&quot;https://pybit.es/&quot;&gt;PyBites&lt;/a&gt; got started and what they have in store for its future. We&amp;rsquo;ll also look into Bob&amp;rsquo;s secret love of drawing and Julian&amp;rsquo;s not so secret love of a good pint. &lt;/p&gt;
&lt;p mt-5=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;Welcome, Bob and Julian! Or is it Julian and Bob? In either case, thank you for joining me for this interview. Let&amp;rsquo;s start with the usual first questions. How&amp;rsquo;d you get into programming? When did you start using Python?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;img-fluid w-25 float-right ml-3 rounded-circle&quot; src=&quot;https://files.realpython.com/media/julian.22aa39d2be75.jpg&quot; width=&quot;192&quot; height=&quot;191&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/julian.22aa39d2be75.jpg&amp;amp;w=48&amp;amp;sig=6c2d6ceaabff2aeb4651fedf373fe4a4f3e2bb95 48w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/julian.22aa39d2be75.jpg&amp;amp;w=96&amp;amp;sig=11aa5d09bcfdb39f0062c4efe52ff7b92096b425 96w, https://files.realpython.com/media/julian.22aa39d2be75.jpg 192w&quot; sizes=&quot;75vw&quot; alt=&quot;Julian Sequeira&quot;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Julian:&lt;/strong&gt; We prefer to go by &amp;ldquo;Boolean.&amp;rdquo; Not really, but let&amp;rsquo;s make it stick.&lt;/p&gt;
&lt;p&gt;I was first bitten by the programming bug (pun intended!) back in high school but really dove into coding in late 2015. &lt;/p&gt;
&lt;p&gt;I needed a way to track the overtime hours I was clocking in my Field Engineer role at Oracle to ensure I was being paid correctly. Enter Python (at Bob&amp;rsquo;s recommendation). &lt;/p&gt;
&lt;p&gt;I made myself a CLI overtime tracker that comprised of a rudimentary menu system with simple options to calculate my post-tax overtime pay. It was basic, worked a treat, and got me hooked on Python. &lt;/p&gt;
&lt;p&gt;Tip: It&amp;rsquo;s the real-world use cases that make the learning stick!&lt;/p&gt;
&lt;p&gt;The speed and simplicity of Python compared to my high school days using C++ had me hooked. Then we started PyBites, and the Python got real. (&lt;em&gt;Real Python&lt;/em&gt;, get it?)&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;img-fluid w-25 float-right ml-3 rounded-circle&quot; src=&quot;https://files.realpython.com/media/bob.19ee3627656d.jpg&quot; width=&quot;191&quot; height=&quot;191&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/bob.19ee3627656d.jpg&amp;amp;w=47&amp;amp;sig=9ed9e131f6a2be706181bddacae925ccbb606dd8 47w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/bob.19ee3627656d.jpg&amp;amp;w=95&amp;amp;sig=1eee03bd2c649f7130fd0908d680ac92b9a6dc02 95w, https://files.realpython.com/media/bob.19ee3627656d.jpg 191w&quot; sizes=&quot;75vw&quot; alt=&quot;Bob Belderbos&quot;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bob:&lt;/strong&gt; For me, it all started at Sun Microsystems back in 2009. I moved into the Systems support group and found a niche to develop a web app to parse diagnostic outputs, of which we were getting thousands every month. This became a staple tool for the support organization, saving them countless hours of tedious work every day. &lt;/p&gt;
&lt;p&gt;This diagnostic tool was a wild mix of shell scripting (bash/sed/awk), Perl, PHP, and some jQuery. The business decided to move to full automation of service requests, for which I wrote a new framework in Perl, which soon became a maintenance nightmare, so I started looking for other solutions. &lt;/p&gt;
&lt;p&gt;This was back in 2012. I stumbled on Python and started learning it. It was love at first sight: with its clean and elegant design (&lt;em&gt;type import this in your REPL&lt;/em&gt;), lack of braces, and other C-like syntax, it just reads like English! It&amp;rsquo;s simple to learn the basics of Python, yet under the covers, it&amp;rsquo;s very versatile. &lt;/p&gt;
&lt;p&gt;There is a great article by Eric Raymond in Linux Journal titled &lt;a href=&quot;https://www.linuxjournal.com/article/3882&quot;&gt;&lt;em&gt;Why Python?&lt;/em&gt;&lt;/a&gt;, which describes his revelation when he changed from Perl to Python. &lt;/p&gt;
&lt;p&gt;I experienced something similar. After a fast rewrite of the automation framework in Python, it became relatively &amp;ldquo;easy&amp;rdquo; to make changes, and we expanded it with many exciting new features, all without major headaches. Although I transitioned into another role, the solution is still actively maintained. Since then, I have been fortunate to use Python for almost all my work.&lt;/p&gt;
&lt;p mt-5=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;You are both most famous (for better or worse) for being the co-founders of &lt;a href=&quot;https://pybit.es/&quot;&gt;PyBites&lt;/a&gt;. For those who don&amp;rsquo;t know about PyBites, what is it, and how did it get started?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Boolean:&lt;/strong&gt; PyBites just started out as a simple blog  to share what we were learning in the Python space. (We use a static site generator called &lt;a href=&quot;https://github.com/getpelican/pelican&quot;&gt;Pelican&lt;/a&gt;.) We were keen to push ourselves past just reading books and watching videos. Writing blog posts made us really dive deep to ensure we were communicating the right concepts.&lt;/p&gt;
&lt;p&gt;Shortly after its inception, we started to test out some ideas. One was to challenge ourselves, as inspired by &lt;a href=&quot;https://www.smartpassiveincome.com/podcasts/noah-kagan-appsumo/&quot;&gt;Noah Kagan&amp;rsquo;s coffee challenge&lt;/a&gt;. So one day Bob came up with a Python exercise for us to solve by the end of the week. &lt;/p&gt;
&lt;p&gt;We found a JavaScript course page with &lt;code&gt;mm:ss&lt;/code&gt; timings per video, but not the total duration. The task was to scrape the site and add up all the video timestamps, calculating the total duration of the course. &lt;/p&gt;
&lt;p&gt;At the end of the week (sprint), we compared our solutions and retrospected on our learnings. We had this &amp;ldquo;Fight Club moment&amp;rdquo; (maybe not as violent&amp;hellip;) of &amp;ldquo;we should do this again sometime,&amp;rdquo; and that&amp;rsquo;s how our blog/community code challenges line was born. &lt;/p&gt;
&lt;p&gt;We looked into GitHub, set up a challenges repo for us to publish our challenges and solutions to, and then created a separate community branch to have others pull request their work to. &lt;/p&gt;
&lt;p&gt;The traction we gained from this sparked the idea that became our coding platform: &lt;a href=&quot;https://codechalleng.es&quot;&gt;CodeChalleng.es&lt;/a&gt;. It comprises of a growing collection of almost 200 Python exercises (called &lt;em&gt;Bites of Py&lt;/em&gt;), which you can code in the comfort of your browser.&lt;/p&gt;
&lt;p&gt;Another huge thing for us was completing the &lt;a href=&quot;https://www.100daysofcode.com/&quot;&gt;#100DaysOfCode&lt;/a&gt; challenge, which we actively shared on our blog and social media. This got us interviewed on the &lt;em&gt;Talk Python&lt;/em&gt; podcast and, in turn, led to us producing the &lt;a href=&quot;https://training.talkpython.fm/courses/explore_100days_in_python/100-days-of-code-in-python&quot;&gt;#100DaysOfCode in Python course&lt;/a&gt; together with &lt;a href=&quot;https://realpython.com/interview-michael-kennedy/&quot;&gt;Michael Kennedy&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;An important lesson for us here was that you just need to get started and drop perfectionism. A lot of awesome stuff that happened was not planned but came to us because we put something out there that generated interest, and we acted upon the valuable feedback we received in the process!&lt;/p&gt;
&lt;p mt-5=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;Julian, you&amp;rsquo;re not a programmer by day, and you work as a Data Center Technician at Amazon Web Services. How has it been learning to code alongside someone as accomplished as Bob? I would assume it would help to have someone more experienced as your business partner? Is there anything that you were surprised by or found difficult as you learned to code?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Julian:&lt;/strong&gt; The Pythonic gap between Bob and me has been the cornerstone of PyBites. It&amp;rsquo;s actually what we figured would give our blog a unique spin! &lt;/p&gt;
&lt;p&gt;To that end, it&amp;rsquo;s been a bit of a mixed bag. When you code alongside someone as capable as Bob, the first feeling is that of awe. You see the elegance of their code and their ability to solve problems you&amp;rsquo;ve spent hours on, in mere moments. It&amp;rsquo;s truly inspirational!&lt;/p&gt;
&lt;p&gt;But not always. It becomes easy to fall into the Imposter Syndrome trap: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&amp;ldquo;Is my code ever going to be as good?&amp;rdquo; &lt;/li&gt;
&lt;li&gt;&amp;ldquo;Why do I even bother?&amp;rdquo; &lt;/li&gt;
&lt;li&gt;&amp;ldquo;He&amp;rsquo;s just always going to be better!&amp;rdquo;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The reality is that there&amp;rsquo;s always going to be someone better when it comes to code, and life in general! I quickly learned that rather than focusing on the skill gap, I should be focusing on my own code, being proud of my achievements, and embracing what I bring to the table.&lt;/p&gt;
&lt;p&gt;Funnily enough, and this applies to both of us, the difficulties we hit with learning and managing code were negligible. That is, we accept it and love it. (I say this now but never in the moment!) &lt;/p&gt;
&lt;p&gt;The surprisingly difficult part has been the actual business side of PyBites! I&amp;rsquo;ll also add that my days of not being a professional coder may be coming to an end! (&lt;em&gt;Shhh!&lt;/em&gt;)&lt;/p&gt;
&lt;p mt-5=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;Bob, in your own words, when you&amp;rsquo;re &amp;ldquo;not hard at work for the Man&amp;rdquo; in your day job, you love to tinker and build projects in your spare time. What kind of projects do you have on the go currently?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bob:&lt;/strong&gt; Currently, almost all of my time goes into producing course content and improving our platform by adding more exercises and features. With increased use, there are more questions and feedback/requests, but I enjoy every minute of it because it provides a great way to teach Python and mentor other developers, something I really enjoy. &lt;/p&gt;
&lt;p&gt;I am also taking the Coursera Applied Data Science specialization because I love data and want to integrate this more in my day-to-day work. &lt;/p&gt;
&lt;p&gt;When this and our upcoming course (&lt;em&gt;suspense&amp;hellip;&lt;/em&gt;) is done, my default workflow will still be similar: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Take a new concept (Python module, data, web technology, automation opportunity, and so on)&lt;/li&gt;
&lt;li&gt;Study it&lt;/li&gt;
&lt;li&gt;Build something cool and blog/share the process &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It&amp;rsquo;s what I am passionate about and adds to PyBites&amp;rsquo; growing body of content. &lt;/p&gt;
&lt;p&gt;This is actually something I recommend for any programmer/dev. CVs are legacy. Start building your blog/GitHub/brand so you have a portfolio you can show. It also enables you to re-use what you build for future projects, and it&amp;rsquo;s a great way to network/collaborate with others. &lt;/p&gt;
&lt;p mt-5=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;It&amp;rsquo;s obvious you both share the entrepreneurial gene. (You only have to look at &lt;a href=&quot;https://bobbelderbos.com/books/&quot;&gt;Bob&amp;rsquo;s bookshelf&lt;/a&gt; to see the evidence.) What&amp;rsquo;s been the hardest or most challenging part for you with starting your own business/side-hustle (PyBites)? Do you find your respective talents offset each other?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Boolean:&lt;/strong&gt; Hands down the most challenging part has been managing our priorities.&lt;/p&gt;
&lt;p&gt;The key priorities in both of our lives happen to be very similar: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Family/kids&lt;/li&gt;
&lt;li&gt;Full-time day jobs&lt;/li&gt;
&lt;li&gt;Learning&lt;/li&gt;
&lt;li&gt;PyBites&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As PyBites grows, so too does the required time investment. We can&amp;rsquo;t take that time away from our day jobs or our families, so it&amp;rsquo;s definitely been the greatest hurdle trying to find an acceptable balance.&lt;/p&gt;
&lt;p&gt;The outlook we&amp;rsquo;ve adopted is that &amp;ldquo;if we have time to watch Netflix, then we have time to work on PyBites.&amp;rdquo; &lt;/p&gt;
&lt;p&gt;To that end, more often than not, we consciously make the choice to not watch TV, play games, or go out, and make that time our PyBites time. It doesn&amp;rsquo;t sound like much, but after a long day at work and getting the kids to bed, getting back on the tools to work on PyBites can be extremely challenging!&lt;/p&gt;
&lt;p&gt;That said, we openly tell anyone who&amp;rsquo;ll listen that we wouldn&amp;rsquo;t be where we are without our mutual support of one another.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re taking on anything worthwhile, then get yourself an accountability partner. We hold each other accountable for the items we take on and build each other up when things don&amp;rsquo;t exactly go our way.&lt;/p&gt;
&lt;p&gt;Our different talents most definitely offset each other. Julian tends to be more of the writer, storyteller, marketer, business manager, and &amp;ldquo;mouth,&amp;rdquo; whereas Bob pushes deep into code, builds and maintains the tools, comes up with incredible ideas, and supports the community technically. Combine these two talent sets, and you have a well-oiled PyBites machine.&lt;/p&gt;
&lt;p&gt;The best part (and sticking to our core belief that you learn by doing) is that we learn from one another. We push each other to continuously improve, to live outside the box, and always try something new.&lt;/p&gt;
&lt;p mt-5=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;Now for my last questions. What else do you get up to in your spare time? What other hobbies and interests do you have, aside from Python and coding?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bob:&lt;/strong&gt; Haha Python and coding is a big chunk, but outside of that I love every minute I get to spend with my wife and two kids. &lt;/p&gt;
&lt;p&gt;I am also keen on sticking to a daily fitness routine, especially as our work requires so much sitting and screen time! I love reading books and consuming podcasts. When I free up more time, language learning and drawing are two other things I really enjoy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Julian:&lt;/strong&gt; Okay, cutting out coding and Python, phew!&lt;/p&gt;
&lt;p&gt;Like Bob, the priority is spending time with my wife and two kids as well. Anyone with young kids will know that you really don&amp;rsquo;t have much time after they&amp;rsquo;re done and dusted, so hobby time is limited these days.&lt;/p&gt;
&lt;p&gt;When I do grab a few rare, non-PyBites minutes, I love to play my electric guitar, play video games, read, and tinker with my Raspberry Pi and home automation.&lt;/p&gt;
&lt;p&gt;Additionally, being the social butterfly I am, I love to hang out with mates and enjoy a few beers. Get me to a pub, shout me a nice Pilsner, and I&amp;rsquo;ll be your best mate!&lt;/p&gt;
&lt;p&gt;(Wait a sec. Did Bob just say he likes to draw?)&lt;/p&gt;
&lt;p mt-5=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky&lt;/strong&gt; &lt;em&gt;Are there any projects you wish to share with our readers? Where can we find out more about you guys and what you&amp;rsquo;re up to?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;img class=&quot;img-fluid w-25 float-right ml-3 rounded-circle&quot; src=&quot;https://files.realpython.com/media/pybites.2f4ff2617d25.png&quot; width=&quot;240&quot; height=&quot;240&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pybites.2f4ff2617d25.png&amp;amp;w=60&amp;amp;sig=e7ba3cfac385fbaa6d0d34a311e083f4f79a1944 60w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pybites.2f4ff2617d25.png&amp;amp;w=120&amp;amp;sig=0af3cc38837bbe1047216759a5eeb501f30ede8a 120w, https://files.realpython.com/media/pybites.2f4ff2617d25.png 240w&quot; sizes=&quot;75vw&quot; alt=&quot;PyBites Logo&quot;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Boolean:&lt;/strong&gt; Other than the &lt;a href=&quot;https://pybit.es&quot;&gt;blog&lt;/a&gt;, our current pride and joy is &lt;a href=&quot;https://codechalleng.es&quot;&gt;our online Python Coding Exercises platform&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We also created the &lt;a href=&quot;https://training.talkpython.fm/courses/explore_100days_in_python/100-days-of-code-in-python&quot;&gt;#100DaysOfCode in Python course with Michael Kennedy&lt;/a&gt; and have become trainers on the &lt;em&gt;Talk Python to Me&lt;/em&gt; training platform. Again, something we&amp;rsquo;re super proud of. (More to come in this space!)&lt;/p&gt;
&lt;p&gt;You can find and follow &lt;strong&gt;Julian&lt;/strong&gt; in the dark places below:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Twitter:&lt;/strong&gt; &lt;a href=&quot;https://twitter.com/_juliansequeira&quot;&gt;@_juliansequeira&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a href=&quot;https://www.linkedin.com/in/juliansequeira/&quot;&gt;https://www.linkedin.com/in/juliansequeira/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Udemy:&lt;/strong&gt; I also created an &lt;a href=&quot;https://www.udemy.com/python-flask-for-beginners/&quot;&gt;introductory Flask course on Udemy&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Personal blog:&lt;/strong&gt; &lt;a href=&quot;https://www.techmoneykids.com/&quot;&gt;https://www.techmoneykids.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Bob:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Twitter:&lt;/strong&gt; &lt;a href=&quot;https://twitter.com/bbelderbos&quot;&gt;@bbelderbos&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LinkedIn:&lt;/strong&gt; &lt;a href=&quot;https://www.linkedin.com/in/bbelderbos/&quot;&gt;https://www.linkedin.com/in/bbelderbos/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Personal blog:&lt;/strong&gt; &lt;a href=&quot;https://bobbelderbos.com&quot;&gt;https://bobbelderbos.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;Thank you Julian and Bob for an entertaining interview. If you haven&amp;rsquo;t checked out PyBites lately, then I encourage you to do so. If you have someone you&amp;rsquo;d like me to interview as part of this series, then leave a comment below. Happy coding!&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Python Context Managers and the &quot;with&quot; Statement</title>
      <id>https://realpython.com/courses/python-context-managers-and-with-statement/</id>
      <link href="https://realpython.com/courses/python-context-managers-and-with-statement/"/>
      <updated>2019-05-07T14:00:00+00:00</updated>
      <summary>In this course you&#39;ll learn how context managers and the &quot;with&quot; statement work in Python, including the difference between class-based and function-based context managers.</summary>
      <content type="html">
        &lt;p&gt;Python&amp;rsquo;s &lt;code&gt;with&lt;/code&gt; statement is powered by a language feature called &lt;em&gt;context managers&lt;/em&gt;. It helps you simplify some common resource management patterns by abstracting their functionality and allowing them to be factored out and reused.&lt;/p&gt;
&lt;p&gt;In this course you&amp;rsquo;ll learn how context managers and the &lt;code&gt;with&lt;/code&gt; statement work in Python, including the difference between class-based and function-based context managers, as well as some other tricks that will make you a more efficient Python developer.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>How to Use sorted() and sort() in Python</title>
      <id>https://realpython.com/python-sort/</id>
      <link href="https://realpython.com/python-sort/"/>
      <updated>2019-05-06T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you’ll learn how to sort in Python. You&#39;ll know how to sort various types of data in different data structures, customize the order, and work with two different ways of sorting in Python.</summary>
      <content type="html">
        &lt;p&gt;All programmers will have to write code to sort items or data at some point. Sorting can be critical to the user experience in your application, whether it&amp;rsquo;s ordering a user&amp;rsquo;s most recent activity by timestamp, or putting a list of email recipients in alphabetical order by last name. Python sorting functionality offers robust features to do basic sorting or customize ordering at a granular level. &lt;/p&gt;
&lt;p&gt;In this guide, you&amp;rsquo;ll learn how to sort various types of data in different data structures, customize the order, and work with two different methods of sorting in Python. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this tutorial, you&amp;rsquo;ll know how to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Implement basic Python sorting and ordering on data structures&lt;/li&gt;
&lt;li&gt;Differentiate between &lt;code&gt;sorted()&lt;/code&gt; and &lt;code&gt;.sort()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Customize a complex sort order in your code based on unique requirements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this tutorial, you&amp;rsquo;ll need a basic understanding of &lt;a href=&quot;https://realpython.com/python-lists-tuples/&quot;&gt;lists and tuples&lt;/a&gt; as well as &lt;a href=&quot;https://realpython.com/quizzes/python-sets/&quot;&gt;sets&lt;/a&gt;. Those data structures will be used in this tutorial, and some basic operations will be performed on them. Also, this tutorial uses Python 3, so example output in this tutorial might vary slightly if you&amp;rsquo;re using Python 2.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-tricks-sample&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a chapter from Python Tricks: The Book&lt;/a&gt; that shows you Python&#39;s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;ordering-values-with-sorted&quot;&gt;Ordering Values With &lt;code&gt;sorted()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To get started with Python sorting, you&amp;rsquo;re first going to see how to sort both numeric data and string data.&lt;/p&gt;
&lt;h3 id=&quot;sorting-numbers&quot;&gt;Sorting Numbers&lt;/h3&gt;
&lt;p&gt;You can use Python to sort a list by using &lt;code&gt;sorted()&lt;/code&gt;. In this example, a list of integers is defined, and then &lt;code&gt;sorted()&lt;/code&gt; is called with the &lt;code&gt;numbers&lt;/code&gt; variable as the argument:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 3, 6, 9]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[6, 9, 3, 1]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The output from this code is a new, sorted list. When the original variable is printed, the initial values are unchanged.&lt;/p&gt;
&lt;p&gt;This example shows four important characteristics of &lt;code&gt;sorted()&lt;/code&gt;: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The function &lt;code&gt;sorted()&lt;/code&gt; did not have to be defined. It&amp;rsquo;s a built-in function that is available in a standard installation of Python.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sorted()&lt;/code&gt;, with no additional arguments or parameters, is ordering the values in &lt;code&gt;numbers&lt;/code&gt; in an ascending order, meaning smallest to largest. &lt;/li&gt;
&lt;li&gt;The original &lt;code&gt;numbers&lt;/code&gt; variable is unchanged because &lt;code&gt;sorted()&lt;/code&gt; provides sorted output and does not change the original value in place. &lt;/li&gt;
&lt;li&gt;When &lt;code&gt;sorted()&lt;/code&gt; is called, it provides an ordered list as a return value. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This last point means that &lt;code&gt;sorted()&lt;/code&gt; can be used on a list, and the output can immediately be assigned to a variable:  &lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_sorted&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 3, 6, 9]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[6, 9, 3, 1]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, there is now a new variable &lt;code&gt;numbers_sorted&lt;/code&gt; that stored the output of &lt;code&gt;sorted()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can confirm all of these observations by calling &lt;code&gt;help()&lt;/code&gt; on &lt;code&gt;sorted()&lt;/code&gt;. The optional arguments &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;reverse&lt;/code&gt; will be covered later in the tutorial:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python 3&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Help on built-in function sorted in module builtins:&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;sorted(iterable, /, *, key=None, reverse=False)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    Return a new list containing all items from the iterable in ascending order.&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    A custom key function can be supplied to customize the sort order, and the&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    reverse flag can be set to request the result in descending order.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Technical Detail:&lt;/strong&gt; If you&amp;rsquo;re transitioning from Python 2 and are familiar with its function of the same name, you should be aware of a couple important changes in Python 3:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Python 3&amp;rsquo;s &lt;code&gt;sorted()&lt;/code&gt; does not have a &lt;code&gt;cmp&lt;/code&gt; parameter. Instead, only &lt;code&gt;key&lt;/code&gt; is used to introduce custom sorting logic.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;key&lt;/code&gt; and &lt;code&gt;reverse&lt;/code&gt; must be passed as keyword arguments, unlike in Python 2, where they could be passed as positional arguments.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you need to convert a Python 2 &lt;code&gt;cmp&lt;/code&gt; function to a &lt;code&gt;key&lt;/code&gt; function, then check out &lt;code&gt;functools.cmp_to_key()&lt;/code&gt;. This tutorial will not cover any examples using Python 2.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;sorted()&lt;/code&gt; can be used on tuples and sets very similarly:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_tuple&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_tuple_sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_set_sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_tuple_sorted&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 3, 6, 9]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_set_sorted&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[0, 1, 5, 10]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice how even though the input was a set and a tuple, the output is a list because &lt;code&gt;sorted()&lt;/code&gt; returns a new list by definition. The returned object can be cast to a new type if it needs to match the input type. Be careful if attempting to cast the resulting list back to a set, as a set by definition is unordered:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_tuple&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_set&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_tuple_sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_set_sorted&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_tuple_sorted&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 3, 6, 9]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_set_sorted&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[0, 1, 5, 10]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;tuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_tuple_sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(1, 3, 6, 9)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers_set_sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{0, 1, 10, 5}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;numbers_set_sorted&lt;/code&gt; value when cast to a &lt;code&gt;set&lt;/code&gt; is not ordered, as expected. The other variable, &lt;code&gt;numbers_tuple_sorted&lt;/code&gt;, retained the sorted order.&lt;/p&gt;
&lt;h3 id=&quot;sorting-strings&quot;&gt;Sorting Strings&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;str&lt;/code&gt; types sort similarly to other iterables, like list and tuple. The example below shows how &lt;code&gt;sorted()&lt;/code&gt; iterates through each character in the value passed to it and orders them in the output:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_number_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;34521&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;I like to sort&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_string_number&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_number_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_string_number&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;1&amp;#39;, &amp;#39;2&amp;#39;, &amp;#39;3&amp;#39;, &amp;#39;4&amp;#39;, &amp;#39;5&amp;#39;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_string&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39; &amp;#39;, &amp;#39; &amp;#39;, &amp;#39; &amp;#39;, &amp;#39;I&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;i&amp;#39;, &amp;#39;k&amp;#39;, &amp;#39;l&amp;#39;, &amp;#39;o&amp;#39;, &amp;#39;o&amp;#39;, &amp;#39;r&amp;#39;, &amp;#39;s&amp;#39;, &amp;#39;t&amp;#39;, &amp;#39;t&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;sorted()&lt;/code&gt; will treat a &lt;code&gt;str&lt;/code&gt; like a list and iterate through each element. In a &lt;code&gt;str&lt;/code&gt;, each element means each character in the &lt;code&gt;str&lt;/code&gt;. &lt;code&gt;sorted()&lt;/code&gt; will not treat a sentence differently, and it will sort each character, including spaces. &lt;/p&gt;
&lt;p&gt;&lt;code&gt;.split()&lt;/code&gt; can change this behavior and clean up the output, and &lt;code&gt;.join()&lt;/code&gt; can put it all back together. We will cover the specific order of the output and why it is that way shortly:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;I like to sort&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_string&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;string_value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_string&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;I&amp;#39;, &amp;#39;like&amp;#39;, &amp;#39;sort&amp;#39;, &amp;#39;to&amp;#39;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39; &amp;#39;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;I like sort to&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The original sentence in this example is converted into a list of words instead of leaving it as a &lt;code&gt;str&lt;/code&gt;. That list is then sorted and combined to form a &lt;code&gt;str&lt;/code&gt; again instead of a list.&lt;/p&gt;
&lt;h2 id=&quot;limitations-and-gotchas-with-python-sorting&quot;&gt;Limitations and Gotchas With Python Sorting&lt;/h2&gt;
&lt;p&gt;It is worth noting some limitations and odd behavior that can arise when you&amp;rsquo;re using Python to sort values besides integers. &lt;/p&gt;
&lt;h3 id=&quot;lists-with-non-comparable-data-types-cant-be-sorted&quot;&gt;Lists With Non-Comparable Data Types Can&amp;rsquo;t Be &lt;code&gt;sorted()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;There are data types that can&amp;rsquo;t be compared to each other using just &lt;code&gt;sorted()&lt;/code&gt; because they are too different. Python will return an error if you attempt to use &lt;code&gt;sorted()&lt;/code&gt; on a list containing non-comparable data. In this example, a &lt;code&gt;None&lt;/code&gt; and an &lt;code&gt;int&lt;/code&gt; in the same list can&amp;rsquo;t be sorted because of their incompatibility: &lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mixed_types&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mixed_types&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;&amp;lt;&amp;#39; not supported between instances of &amp;#39;int&amp;#39; and &amp;#39;NoneType&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This error shows why Python can&amp;rsquo;t sort the values given to it. It&amp;rsquo;s trying to put the values in order by using the less than operator (&lt;code&gt;&amp;lt;&lt;/code&gt;) to determine which value is lower in sorting order. You can replicate this error by manually comparing the two values:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;&amp;lt;&amp;#39; not supported between instances of &amp;#39;NoneType&amp;#39; and &amp;#39;int&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The same &lt;code&gt;TypeError&lt;/code&gt; is thrown when you try to compare two non-comparable values without using &lt;code&gt;sorted()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If the values within the list can be compared and will not throw a &lt;code&gt;TypeError&lt;/code&gt;, then the list can be sorted. This prevents sorting iterables with intrinsically unorderable values and producing output that may not make sense. &lt;/p&gt;
&lt;p&gt;For example, should the number &lt;code&gt;1&lt;/code&gt; come before the word &lt;code&gt;apple&lt;/code&gt;? However, if a iterable contains a combination of integers and strings that are all numbers, they can be cast to comparable data types by using a list comprehension:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mixed_numbers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;34&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mixed_numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;&amp;lt;&amp;#39; not supported between instances of &amp;#39;str&amp;#39; and &amp;#39;int&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# List comprehension to convert all values to integers&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mixed_numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[5, 1, 100, 34]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mixed_numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 5, 34, 100]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each element in &lt;code&gt;mixed_numbers&lt;/code&gt; has &lt;code&gt;int()&lt;/code&gt; called on it to convert any &lt;code&gt;str&lt;/code&gt; values to &lt;code&gt;int&lt;/code&gt; values. &lt;code&gt;sorted()&lt;/code&gt; is then called and can successfully compare each element and provide a sorted output.&lt;/p&gt;
&lt;p&gt;Python can also implicitly convert a value to another type. In the example below, the evaluation of &lt;code&gt;1 &amp;lt;= 0&lt;/code&gt; is a false statement, so the output of the evaluation will be &lt;code&gt;False&lt;/code&gt;. The number &lt;code&gt;1&lt;/code&gt; can be converted to &lt;code&gt;True&lt;/code&gt; as a &lt;code&gt;bool&lt;/code&gt; type, while &lt;code&gt;0&lt;/code&gt; converts to &lt;code&gt;False&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Even though the elements in the list look different, they can all be converted to Booleans (&lt;code&gt;True&lt;/code&gt; or &lt;code&gt;False&lt;/code&gt;) and compared to each other using &lt;code&gt;sorted()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;similar_values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;A&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;similar_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[False, 0, False, False, 1]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;&#39;A&#39; == &#39;B&#39;&lt;/code&gt; and &lt;code&gt;1 &amp;lt;= 0&lt;/code&gt; are converted to &lt;code&gt;False&lt;/code&gt; and returned in the ordered output. &lt;/p&gt;
&lt;p&gt;This example illustrates an important aspect of sorting: &lt;strong&gt;sort stability&lt;/strong&gt;. In Python, when you sort equal values, they will retain their original order in the output. Even though the &lt;code&gt;1&lt;/code&gt; moved, all the other values are equal so they retain their original order relative to each other. In the example below, all the values are considered equal and will retain their original positions: &lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;false_values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;false_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[False, 0, 0, False, 0, False, False]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you inspect the original order and the sorted output, you will see that &lt;code&gt;1 == 2&lt;/code&gt; is converted to &lt;code&gt;False&lt;/code&gt;, and all sorted output is in the original order.&lt;/p&gt;
&lt;h3 id=&quot;when-youre-sorting-strings-case-matters&quot;&gt;When You&amp;rsquo;re Sorting Strings, Case Matters&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;sorted()&lt;/code&gt; can be used on a list of strings to sort the values in ascending order, which appears to be alphabetically by default:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Harry&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Suzy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Al&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Mark&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Al&amp;#39;, &amp;#39;Harry&amp;#39;, &amp;#39;Mark&amp;#39;, &amp;#39;Suzy&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, Python is using the &lt;a href=&quot;https://en.wikipedia.org/wiki/Code_point&quot;&gt;Unicode Code Point&lt;/a&gt; of the first letter in each string to determine ascending sort order. This means that &lt;code&gt;sorted()&lt;/code&gt; will not treat the names &lt;code&gt;Al&lt;/code&gt; and &lt;code&gt;al&lt;/code&gt; the same. This example uses &lt;code&gt;ord()&lt;/code&gt; to return the Unicode Code Point of the first letter in each string:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names_with_case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;harry&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Suzy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;al&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Mark&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names_with_case&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Mark&amp;#39;, &amp;#39;Suzy&amp;#39;, &amp;#39;al&amp;#39;, &amp;#39;harry&amp;#39;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# List comprehension for Unicode Code Point of first letter in each word&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ord&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;name&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names_with_case&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[(77, &amp;#39;M&amp;#39;), (83, &amp;#39;S&amp;#39;), (97, &amp;#39;a&amp;#39;), (104, &amp;#39;h&amp;#39;)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;name[0]&lt;/code&gt; is returning the first character in each element of &lt;code&gt;sorted(names_with_case)&lt;/code&gt;, and &lt;code&gt;ord()&lt;/code&gt; is providing the Unicode Code Point. Even though &lt;code&gt;a&lt;/code&gt; comes before &lt;code&gt;M&lt;/code&gt; in the alphabet, the code point for &lt;code&gt;M&lt;/code&gt; comes before &lt;code&gt;a&lt;/code&gt;, so the sorted output has &lt;code&gt;M&lt;/code&gt; first.&lt;/p&gt;
&lt;p&gt;If the first letter is the same, then &lt;code&gt;sorted()&lt;/code&gt; will use the second character to determine order, and the third character if that is the same, and so on, all the way to the end of the string:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;very_similar_strs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hhhhhd&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;hhhhha&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;hhhhhc&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hhhhhb&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;very_similar_strs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;hhhhha&amp;#39;, &amp;#39;hhhhhb&amp;#39;, &amp;#39;hhhhhc&amp;#39;, &amp;#39;hhhhhd&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each value of &lt;code&gt;very_similar_strs&lt;/code&gt; is identical except for the last character. &lt;code&gt;sorted()&lt;/code&gt; will compare the strings, and because the first five characters are the same, the output will be based on the sixth character.&lt;/p&gt;
&lt;p&gt;Strings that contain identical values will end up sorted shortest to longest due to the shorter strings not having elements to compare to with the longer strings:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;different_lengths&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;hhhh&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;hh&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;hhhhh&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;h&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;different_lengths&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;h&amp;#39;, &amp;#39;hh&amp;#39;, &amp;#39;hhhh&amp;#39;, &amp;#39;hhhhh&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The shortest string, &lt;code&gt;h&lt;/code&gt;, is ordered first with the longest, &lt;code&gt;hhhhh&lt;/code&gt;, ordered last.&lt;/p&gt;
&lt;h2 id=&quot;using-sorted-with-a-reverse-argument&quot;&gt;Using &lt;code&gt;sorted()&lt;/code&gt; With a &lt;code&gt;reverse&lt;/code&gt; Argument&lt;/h2&gt;
&lt;p&gt;As shown in the &lt;code&gt;help()&lt;/code&gt; documentation for &lt;code&gt;sorted()&lt;/code&gt;, there is an optional keyword argument called &lt;code&gt;reverse&lt;/code&gt;, which will change the sorting behavior based on the Boolean assigned to it. If &lt;code&gt;reverse&lt;/code&gt; is assigned &lt;code&gt;True&lt;/code&gt;, then the sorting will be in descending order:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Harry&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Suzy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Al&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Mark&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Al&amp;#39;, &amp;#39;Harry&amp;#39;, &amp;#39;Mark&amp;#39;, &amp;#39;Suzy&amp;#39;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Suzy&amp;#39;, &amp;#39;Mark&amp;#39;, &amp;#39;Harry&amp;#39;, &amp;#39;Al&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The sorting logic remains the same, meaning that the names are still being sorted by their first letter. But the output has been reversed with the &lt;code&gt;reverse&lt;/code&gt; keyword set to &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;False&lt;/code&gt; is assigned, the ordering will remain ascending. Any of the previous examples can be used to see the behavior of reverse using both &lt;code&gt;True&lt;/code&gt; or &lt;code&gt;False&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names_with_case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;harry&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Suzy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;al&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Mark&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names_with_case&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;harry&amp;#39;, &amp;#39;al&amp;#39;, &amp;#39;Suzy&amp;#39;, &amp;#39;Mark&amp;#39;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;similar_values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;A&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;B&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;similar_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, False, False, False]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;numbers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 3, 6, 9]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;h2 id=&quot;sorted-with-a-key-argument&quot;&gt;&lt;code&gt;sorted()&lt;/code&gt; With a &lt;code&gt;key&lt;/code&gt; Argument&lt;/h2&gt;
&lt;p&gt;One of the most powerful components of &lt;code&gt;sorted()&lt;/code&gt; is the keyword argument called &lt;code&gt;key&lt;/code&gt;. This argument expects a function to be passed to it, and that function will be used on each value in the list being sorted to determine the resulting order. &lt;/p&gt;
&lt;p&gt;To demonstrate a basic example, let&amp;rsquo;s assume the requirement for ordering a specific list is the length of the strings in the list, shortest to longest. The function to return the length of a string, &lt;code&gt;len()&lt;/code&gt;, will be used with the &lt;code&gt;key&lt;/code&gt; argument: &lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;paper&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pie&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Washington&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;book&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;pie&amp;#39;, &amp;#39;book&amp;#39;, &amp;#39;banana&amp;#39;, &amp;#39;Washington&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The resulting order is a list with a string order of shortest to longest. The length of each element in the list is determined by &lt;code&gt;len()&lt;/code&gt; and then returned in ascending order. &lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s return to the earlier example of sorting by first letter when the case is different. &lt;code&gt;key&lt;/code&gt; can be used to solve that problem by converting the entire string to lowercase:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names_with_case&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;harry&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Suzy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;al&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Mark&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names_with_case&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Mark&amp;#39;, &amp;#39;Suzy&amp;#39;, &amp;#39;al&amp;#39;, &amp;#39;harry&amp;#39;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;names_with_case&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lower&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;al&amp;#39;, &amp;#39;harry&amp;#39;, &amp;#39;Mark&amp;#39;, &amp;#39;Suzy&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The output values have not been converted to lowercase because &lt;code&gt;key&lt;/code&gt; does not manipulate the data in the original list. During sorting, the function passed to &lt;code&gt;key&lt;/code&gt; is being called on each element to determine sort order, but the original values will be in the output.&lt;/p&gt;
&lt;p&gt;There are two main limitations when you&amp;rsquo;re using functions with the &lt;code&gt;key&lt;/code&gt; argument. &lt;/p&gt;
&lt;p&gt;First, the number of required arguments in the function passed to &lt;code&gt;key&lt;/code&gt; must be one. &lt;/p&gt;
&lt;p&gt;The example below shows the definition of an addition function that takes two arguments. When that function is used in &lt;code&gt;key&lt;/code&gt; on a list of numbers, it fails because it is missing a second argument. Each time &lt;code&gt;add()&lt;/code&gt; is called during the sort, it is only receiving one element from the list at a time:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values_to_add&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values_to_add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;add() missing 1 required positional argument: &amp;#39;y&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The second limitation is that the function used with &lt;code&gt;key&lt;/code&gt; must be able to handle all the values in the iterable. For example, you have a list of numbers represented as strings to be used in &lt;code&gt;sorted()&lt;/code&gt;, and &lt;code&gt;key&lt;/code&gt; is going to attempt to convert them to numbers using &lt;code&gt;int&lt;/code&gt;. If a value in the iterable can&amp;rsquo;t be cast to an integer, then the function will fail: &lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values_to_cast&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;four&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values_to_cast&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;ValueError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;invalid literal for int() with base 10: &amp;#39;four&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each numeric value as a &lt;code&gt;str&lt;/code&gt; can be converted to &lt;code&gt;int&lt;/code&gt;, but &lt;code&gt;four&lt;/code&gt; can&amp;rsquo;t. This causes a &lt;code&gt;ValueError&lt;/code&gt; to be raised and explain that &lt;code&gt;four&lt;/code&gt; can&amp;rsquo;t be converted to &lt;code&gt;int&lt;/code&gt; because it is invalid.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;key&lt;/code&gt; functionality is extremely powerful because almost any function, built-in or user-defined, can be used to manipulate the output order. &lt;/p&gt;
&lt;p&gt;If the ordering requirement is to order an iterable by the last letter in each string (and if the letter is the same, then to use the next letter), then a &lt;a href=&quot;https://realpython.com/lessons/example-function/&quot;&gt;function&lt;/a&gt; can be defined and then used in the sorting. The example below defines a function that reverses the string passed to it, and then that function is used as the argument for &lt;code&gt;key&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;reverse_word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pie&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Washington&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;book&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reverse_word&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;banana&amp;#39;, &amp;#39;pie&amp;#39;, &amp;#39;book&amp;#39;, &amp;#39;Washington&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;word[::-1]&lt;/code&gt; slice syntax is used to reverse a string. Each element will have &lt;code&gt;reverse_word()&lt;/code&gt; applied to it, and the sorting order will be based on the characters in the backwards word.&lt;/p&gt;
&lt;p&gt;Instead of writing a standalone function, you can use a &lt;code&gt;lambda&lt;/code&gt; function defined in the &lt;code&gt;key&lt;/code&gt; argument. &lt;/p&gt;
&lt;p&gt;A &lt;code&gt;lambda&lt;/code&gt; is an anonymous function that:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Must be defined inline &lt;/li&gt;
&lt;li&gt;Doesn&amp;rsquo;t have a name &lt;/li&gt;
&lt;li&gt;Can&amp;rsquo;t contain &lt;a href=&quot;https://docs.python.org/3/reference/simple_stmts.html&quot;&gt;statements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Will execute just like a function&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In the example below, the &lt;code&gt;key&lt;/code&gt; is defined as a &lt;code&gt;lambda&lt;/code&gt; with no name, the argument taken by the &lt;code&gt;lambda&lt;/code&gt; is &lt;code&gt;x&lt;/code&gt;, and &lt;code&gt;x[::-1]&lt;/code&gt; is the operation that will be performed on the argument:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pie&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Washington&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;book&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;banana&amp;#39;, &amp;#39;pie&amp;#39;, &amp;#39;book&amp;#39;, &amp;#39;Washington&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;x[::-1]&lt;/code&gt; is called on each element and reverses the word. That reversed output is then used for sorting, but the original words are still returned. &lt;/p&gt;
&lt;p&gt;If the requirement changes, and the order should be reversed as well, then the &lt;code&gt;reverse&lt;/code&gt; keyword can be used alongside the &lt;code&gt;key&lt;/code&gt; argument: &lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;banana&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;pie&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Washington&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;book&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;words&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Washington&amp;#39;, &amp;#39;book&amp;#39;, &amp;#39;pie&amp;#39;, &amp;#39;banana&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;lambda&lt;/code&gt; functions are also useful when you need to sort &lt;code&gt;class&lt;/code&gt; objects based on a property. If you have a group of students and need to sort them by their final grade, highest to lowest, then a &lt;code&gt;lambda&lt;/code&gt; can be used to get the &lt;code&gt;grade&lt;/code&gt; property from the &lt;code&gt;class&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;collections&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namedtuple&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StudentFinal&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namedtuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;StudentFinal&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;name grade&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bill&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StudentFinal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Bill&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;patty&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StudentFinal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Patty&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;94&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;StudentFinal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Bart&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;89&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;students&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bill&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;patty&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;students&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;grade&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[StudentFinal(name=&amp;#39;Patty&amp;#39;, grade=94), StudentFinal(name=&amp;#39;Bill&amp;#39;, grade=90), StudentFinal(name=&amp;#39;Bart&amp;#39;, grade=89)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This example uses &lt;code&gt;namedtuple&lt;/code&gt; to produce classes with &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;grade&lt;/code&gt; attributes. The &lt;code&gt;lambda&lt;/code&gt; calls &lt;code&gt;getattr()&lt;/code&gt; on each element and returns the value for &lt;code&gt;grade&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;&lt;code&gt;reverse&lt;/code&gt; is set to &lt;code&gt;True&lt;/code&gt; to make the ascending output flipped to be descending so that the highest grades are ordered first.&lt;/p&gt;
&lt;p&gt;The possibilities are endless for how ordering can be done when you leverage both the &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;reverse&lt;/code&gt; keyword arguments on &lt;code&gt;sorted()&lt;/code&gt;. Code can be kept clean and short when you use a basic &lt;code&gt;lambda&lt;/code&gt; for a small function, or you can write a whole new function, import it, and use it in the key argument. &lt;/p&gt;
&lt;h2 id=&quot;ordering-values-with-sort&quot;&gt;Ordering Values With &lt;code&gt;.sort()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The very similarly named &lt;code&gt;.sort()&lt;/code&gt; differs quite a bit from the &lt;code&gt;sorted()&lt;/code&gt; built-in. They accomplish more or less the same thing, but the &lt;code&gt;help()&lt;/code&gt; documentation for &lt;code&gt;list.sort()&lt;/code&gt; highlights two of the most critical differences between &lt;code&gt;.sort()&lt;/code&gt; and &lt;code&gt;sorted()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python2&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Help on method_descriptor:&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;sort(...)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    cmp(x, y) -&amp;gt; -1, 0, 1&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Python3&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Help on method_descriptor:&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;sort(...)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    L.sort(key=None, reverse=False) -&amp;gt; None -- stable sort *IN PLACE*&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;First, sort is a method of the &lt;code&gt;list&lt;/code&gt; class and can only be used with lists. It is not a built-in with an iterable passed to it. &lt;/p&gt;
&lt;p&gt;Second, &lt;code&gt;.sort()&lt;/code&gt; returns &lt;code&gt;None&lt;/code&gt; and modifies the values in place. Let&amp;rsquo;s take a look at the impacts of both of these differences in code: &lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values_to_sort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Try to call .sort() like sorted()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values_to_sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;NameError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;name &amp;#39;sort&amp;#39; is not defined&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Try to use .sort() on a tuple&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tuple_val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tuple_val&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;AttributeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;tuple&amp;#39; object has no attribute &amp;#39;sort&amp;#39;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Sort the list and assign to new variable&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_values&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;values_to_sort&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sorted_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;None&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Print original variable&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;values_to_sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1, 2, 5, 6]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There are some pretty dramatic differences in how &lt;code&gt;.sort()&lt;/code&gt; operates compared to &lt;code&gt;sorted()&lt;/code&gt; in this code example: &lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;There is no ordered output of &lt;code&gt;.sort()&lt;/code&gt;, so the assignment to a new variable only passes a &lt;code&gt;None&lt;/code&gt; type. &lt;/li&gt;
&lt;li&gt;The &lt;code&gt;values_to_sort&lt;/code&gt; list has been changed in place, and the original order is not maintained in any way. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These differences in behavior make &lt;code&gt;.sort()&lt;/code&gt; and &lt;code&gt;sorted()&lt;/code&gt; absolutely not interchangeable in code, and they can produce wildly unexpected outcomes if one is used in the wrong way.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.sort()&lt;/code&gt; has the same &lt;code&gt;key&lt;/code&gt; and &lt;code&gt;reverse&lt;/code&gt; optional keyword arguments that produce the same robust functionality as &lt;code&gt;sorted()&lt;/code&gt;. Here, you can sort a list of phrases by the second letter of the third word and return the list in reverse:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;phrases&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;when in rome&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39;what goes around comes around&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;s1&quot;&gt;&amp;#39;all is fair in love and war&amp;#39;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;phrases&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reverse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;phrases&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;what goes around comes around&amp;#39;, &amp;#39;when in rome&amp;#39;, &amp;#39;all is fair in love and war&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this sample, a &lt;code&gt;lambda&lt;/code&gt; is used to do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Split each phrase into a list of words&lt;/li&gt;
&lt;li&gt;Find the third element, or word in this case&lt;/li&gt;
&lt;li&gt;Find the second letter in that word &lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;when-to-use-sorted-and-when-to-use-sort&quot;&gt;When to Use &lt;code&gt;sorted()&lt;/code&gt; and When to Use &lt;code&gt;.sort()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ve seen the differences between &lt;code&gt;sorted()&lt;/code&gt; and &lt;code&gt;.sort()&lt;/code&gt;, but when do you use which? &lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s say there is a 5k race coming up: The First Annual Python 5k. The data from the race needs to be captured and sorted. The data that needs to be captured is the runner&amp;rsquo;s bib number and the number of seconds it took to finish the race:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;collections&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namedtuple&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namedtuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Runner&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;bibnumber duration&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As the runners cross the finish line, each &lt;code&gt;Runner&lt;/code&gt; will be added to a list called &lt;code&gt;runners&lt;/code&gt;. In 5k races, not all runners cross the starting line at the same time, so the first person to cross the finish line might not actually be the fastest person:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;2528567&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;7575234&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1420&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;2666234&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1600&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;2425234&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1490&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;1235234&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1620&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Thousands and Thousands of entries later...&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runner&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;2526674&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1906&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each time a runner crosses the finish line, their bib number and their total duration in seconds is added to &lt;code&gt;runners&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, the dutiful programmer in charge of handling the outcome data sees this list, knows that the top 5 fastest participants are the winners that get prizes, and the remaining runners are going to be sorted by fastest time. &lt;/p&gt;
&lt;p&gt;There are no requirements for multiple types of sorting by various attributes. The list is a reasonable size. There is no mention of storing the list somewhere. Just sort by duration and grab the five participants with the lowest duration:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sort&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;duration&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top_five_runners&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The programmer chooses to use a &lt;code&gt;lambda&lt;/code&gt; in the &lt;code&gt;key&lt;/code&gt; argument to get the &lt;code&gt;duration&lt;/code&gt; attribute from each runner and sort &lt;code&gt;runners&lt;/code&gt; in place using &lt;code&gt;.sort()&lt;/code&gt;. After &lt;code&gt;runners&lt;/code&gt; is sorted, the first 5 elements are stored in &lt;code&gt;top_five_runners&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Mission accomplished! The race director comes over and informs the programmer that since the current release of Python is 3.7, they have decided that every thirty-seventh person that crossed the finish line is going to get a free gym bag. &lt;/p&gt;
&lt;p&gt;At this point, the programmer starts to sweat because the list of runners has been irreversibly changed. There is no way to recover the original list of runners in the order they finished and find every thirty-seventh person. &lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re working with important data, and there is even a remote possibility that the original data will need to be recovered, then &lt;code&gt;.sort()&lt;/code&gt; is not the best option. If the data is a copy, of if it is unimportant working data, of if no one will mind losing it because it can be retrieved, then &lt;code&gt;.sort()&lt;/code&gt; can be a fine option. &lt;/p&gt;
&lt;p&gt;Alternatively, the runners could have been sorted using &lt;code&gt;sorted()&lt;/code&gt; and using the same &lt;code&gt;lambda&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runners_by_duration&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;sorted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;duration&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;top_five_runners&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runners_by_duration&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this scenario with &lt;code&gt;sorted()&lt;/code&gt;, the original list of runners is still intact and has not been overwritten. The impromptu requirement of finding every thirty-seventh person to cross the finish line can be accomplished by interacting with the original values:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;every_thirtyseventh_runners&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;runners&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;37&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;every_thirtyseventh_runners&lt;/code&gt; is created by using a stride in the list slice syntax on &lt;code&gt;runners&lt;/code&gt;, which still contains the original order in which the runners crossed the finish line.&lt;/p&gt;
&lt;h2 id=&quot;how-to-sort-in-python-conclusion&quot;&gt;How to Sort in Python: Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;.sort()&lt;/code&gt; and &lt;code&gt;sorted()&lt;/code&gt; can provide exactly the sort order you need if you use them properly with both the &lt;code&gt;reverse&lt;/code&gt; and &lt;code&gt;key&lt;/code&gt; optional keyword arguments. &lt;/p&gt;
&lt;p&gt;Both have very different characteristics when it comes to output and in-place modifications, so make sure you think through any application functionality or program that will be using &lt;code&gt;.sort()&lt;/code&gt; as it can irrevocably overwrite data. &lt;/p&gt;
&lt;p&gt;For the avid Pythonistas looking for a challenge with sorting, try using more complex data types in sorting: nested iterables. Also, feel free to dive into the open source Python code implementations for the built-ins and read about the sort algorithm used in Python called &lt;a href=&quot;https://en.wikipedia.org/wiki/Timsort&quot;&gt;Timsort&lt;/a&gt;.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Defining Main Functions in Python</title>
      <id>https://realpython.com/python-main-function/</id>
      <link href="https://realpython.com/python-main-function/"/>
      <updated>2019-05-01T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn how Python main functions are used and some best practices to organize your code so it can be executed as a script and imported from another module.</summary>
      <content type="html">
        &lt;p&gt;Many programming languages have a special function that is automatically executed when an operating system starts to run a program. This function is usually called &lt;code&gt;main()&lt;/code&gt; and must have a specific return type and arguments according to the language standard. On the other hand, the Python interpreter executes scripts starting at the top of the file, and there is no specific function that Python automatically executes.&lt;/p&gt;
&lt;p&gt;Nevertheless, having a defined starting point for the execution of a program is useful for understanding how a program works. Python programmers have come up with several conventions to define this starting point.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this article, you&amp;rsquo;ll understand:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What the special &lt;code&gt;__name__&lt;/code&gt; variable is and how Python defines it&lt;/li&gt;
&lt;li&gt;Why you would want to use a &lt;code&gt;main()&lt;/code&gt; in Python&lt;/li&gt;
&lt;li&gt;What conventions there are for defining &lt;code&gt;main()&lt;/code&gt; in Python &lt;/li&gt;
&lt;li&gt;What the best-practices are for what code to put into your &lt;code&gt;main()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-tricks-sample&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a chapter from Python Tricks: The Book&lt;/a&gt; that shows you Python&#39;s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;a-basic-python-main&quot;&gt;A Basic Python main()&lt;/h2&gt;
&lt;p&gt;In some Python scripts, you may see a function definition and a conditional statement that looks like the example below:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello World!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, there is a function called &lt;code&gt;main()&lt;/code&gt; that prints the phrase &lt;code&gt;Hello World!&lt;/code&gt; when the Python interpreter executes it. There is also a conditional (or &lt;code&gt;if&lt;/code&gt;) statement that checks the value of &lt;code&gt;__name__&lt;/code&gt; and compares it to the string &lt;code&gt;&quot;__main__&quot;&lt;/code&gt;. When the &lt;code&gt;if&lt;/code&gt; statement evaluates to &lt;code&gt;True&lt;/code&gt;, the Python interpreter executes &lt;code&gt;main()&lt;/code&gt;. You can read more about conditional statements in &lt;a href=&quot;https://realpython.com/python-conditional-statements/&quot;&gt;Conditional Statements in Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This code pattern is quite common in Python files that you want to be &lt;strong&gt;executed as a script&lt;/strong&gt; and &lt;strong&gt;imported in another module&lt;/strong&gt;. To help understand how this code will execute, you should first understand how the Python interpreter sets &lt;code&gt;__name__&lt;/code&gt; depending on how the code is being executed.&lt;/p&gt;
&lt;h2 id=&quot;execution-modes-in-python&quot;&gt;Execution Modes in Python&lt;/h2&gt;
&lt;p&gt;There are two primary ways that you can instruct the Python interpreter to execute or use code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You can execute the Python file as a &lt;strong&gt;script&lt;/strong&gt; using the command line.&lt;/li&gt;
&lt;li&gt;You can &lt;strong&gt;import&lt;/strong&gt; the code from one Python file into another file or into the interactive interpreter.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can read a lot more about these approaches in &lt;a href=&quot;https://realpython.com/run-python-scripts/&quot;&gt;How to Run Your Python Scripts&lt;/a&gt;. No matter which way of running your code you&amp;rsquo;re using, Python defines a special variable called &lt;code&gt;__name__&lt;/code&gt; that contains a string whose value depends on how the code is being used.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ll use this example file, saved as &lt;code&gt;execution_methods.py&lt;/code&gt;, to explore how the behavior of the code changes depending on the context:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;This is my file to test Python&amp;#39;s execution methods.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;The variable __name__ tells me which context this file is running in.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;The value of __name__ is:&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;repr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this file, there are three calls to &lt;code&gt;print()&lt;/code&gt; defined. The first two print some introductory phrases. The third &lt;code&gt;print()&lt;/code&gt; will first print the phrase &lt;code&gt;The value of __name__ is&lt;/code&gt;, and then it will print the representation of the &lt;code&gt;__name__&lt;/code&gt; variable using Python&amp;rsquo;s built-in &lt;code&gt;repr()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In Python, &lt;code&gt;repr()&lt;/code&gt; displays the printable representation of an object. This example uses &lt;code&gt;repr()&lt;/code&gt; to emphasize that the value of &lt;code&gt;__name__&lt;/code&gt; is a string. You can read more about &lt;code&gt;repr()&lt;/code&gt; in the &lt;a href=&quot;https://docs.python.org/3/library/functions.html#repr&quot;&gt;Python documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll see the words &lt;strong&gt;file&lt;/strong&gt;, &lt;strong&gt;module&lt;/strong&gt;, and &lt;strong&gt;script&lt;/strong&gt; used throughout this article. Practically, there isn&amp;rsquo;t much difference between them. However, there are slight differences in meaning that emphasize the purpose of a piece of code:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; Typically, a Python file is any file that contains code. Most Python files have the extension &lt;code&gt;.py&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Script:&lt;/strong&gt; A Python script is a file that you intend to execute from the command line to accomplish a task.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Module:&lt;/strong&gt;  A Python module is a file that you intend to import from within another module or a script, or from the interactive interpreter. You can read more about modules in the &lt;a href=&quot;https://docs.python.org/3/tutorial/modules.html&quot;&gt;Python documentation&lt;/a&gt;. &lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This distinction is also discussed in &lt;a href=&quot;https://realpython.com/run-python-scripts/&quot;&gt;How to Run Your Python Scripts&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;executing-from-the-command-line&quot;&gt;Executing From the Command Line&lt;/h3&gt;
&lt;p&gt;In this approach, you want to execute your Python script from the command line.&lt;/p&gt;
&lt;p&gt;When you execute a script, you will not be able to interactively define the code that the Python interpreter is executing. The details of how you can execute Python from your command line are not that important for the purpose of this article, but you can expand the box below to read more about the differences between the command line on Windows, Linux, and macOS.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card711c77&quot;&gt;
&lt;div class=&quot;card-header border-0&quot;&gt;&lt;p class=&quot;m-0&quot;&gt;&lt;button class=&quot;btn&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse711c77&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse711c77&quot;&gt;Command line environments&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse711c77&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse711c77&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse711c77&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card711c77&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;The way that you tell the computer to execute code from the command line is slightly different depending on your operating system.&lt;/p&gt;
&lt;p&gt;On Linux and macOS, the command line typically looks like the example below:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;eleanor@realpython:~/Documents$&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The part before the dollar sign (&lt;code&gt;$&lt;/code&gt;) may look different, depending on your username and your computer&amp;rsquo;s name. The commands that you type will go after the &lt;code&gt;$&lt;/code&gt;. On Linux or macOS, the name of the Python 3 executable is &lt;code&gt;python3&lt;/code&gt;, so you should run Python scripts by typing &lt;code&gt;python3 script_name.py&lt;/code&gt; after the &lt;code&gt;$&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;On Windows, the command prompt typically looks like the example below:&lt;/p&gt;
&lt;div class=&quot;highlight doscon&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;C:\Users\Eleanor\Documents&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The part before the &lt;code&gt;&amp;gt;&lt;/code&gt; may look different, depending on your username. The commands that you type will go after the &lt;code&gt;&amp;gt;&lt;/code&gt;. On Windows, the name of the Python 3 executable is typically &lt;code&gt;python&lt;/code&gt;, so you should run Python scripts by typing &lt;code&gt;python script_name.py&lt;/code&gt; after the &lt;code&gt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Regardless of your operating system, the output from the Python scripts that you use in this article will be the same, so only the Linux and macOS style of input is shown in this article, and the input line will start at the &lt;code&gt;$&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;p&gt;Now you should execute the &lt;code&gt;execution_methods.py&lt;/code&gt; script from the command line, as shown below:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python3 execution_methods.py
&lt;span class=&quot;go&quot;&gt;This is my file to test Python&amp;#39;s execution methods.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The variable __name__ tells me which context this file is running in.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The value of __name__ is: &amp;#39;__main__&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you can see that &lt;code&gt;__name__&lt;/code&gt; has the value &lt;code&gt;&#39;__main__&#39;&lt;/code&gt;, where the quote symbols (&lt;code&gt;&#39;&lt;/code&gt;) tell you that the value has the string type.&lt;/p&gt;
&lt;p&gt;Remember that, in Python, there is no difference between strings defined with single quotes (&lt;code&gt;&#39;&lt;/code&gt;) and double quotes (&lt;code&gt;&quot;&lt;/code&gt;). You can read more about defining strings in &lt;a href=&quot;https://realpython.com/python-data-types/#strings&quot;&gt;Basic Data Types in Python&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You will find identical output if you include a &lt;a href=&quot;https://en.wikipedia.org/wiki/Shebang_(Unix)&quot;&gt;shebang line&lt;/a&gt; in your script and execute it directly (&lt;code&gt;./execution_methods.py&lt;/code&gt;), or use the &lt;code&gt;%run&lt;/code&gt; magic in IPython or Jupyter Notebooks.&lt;/p&gt;
&lt;p&gt;You may also see Python scripts executed from within packages by adding the &lt;code&gt;-m&lt;/code&gt; argument to the command. Most often, you will see this recommended when you&amp;rsquo;re using &lt;code&gt;pip&lt;/code&gt;: &lt;code&gt;python3 -m pip install package_name&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Adding the &lt;code&gt;-m&lt;/code&gt; argument runs the code in the &lt;code&gt;__main__.py&lt;/code&gt; module of a package. You can find more information about the &lt;code&gt;__main__.py&lt;/code&gt; file in &lt;a href=&quot;https://realpython.com/pypi-publish-python-package/#different-ways-of-calling-a-package&quot;&gt;How to Publish an Open-Source Python Package to PyPI&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In all three of these cases, &lt;code&gt;__name__&lt;/code&gt; has the same value: the string &lt;code&gt;&#39;__main__&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Technical detail:&lt;/strong&gt; The Python documentation defines specifically when &lt;code&gt;__name__&lt;/code&gt; will have the value &lt;code&gt;&#39;__main__&#39;&lt;/code&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A module&amp;rsquo;s &lt;code&gt;__name__&lt;/code&gt; is set equal to &lt;code&gt;&#39;__main__&#39;&lt;/code&gt; when read from standard input, a script, or from an interactive prompt. (&lt;a href=&quot;https://docs.python.org/3/library/__main__.html&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;__name__&lt;/code&gt; is stored in the global namespace of the module along with the &lt;code&gt;__doc__&lt;/code&gt;, &lt;code&gt;__package__&lt;/code&gt;, and other attributes. You can read more about these attributes in the &lt;a href=&quot;https://docs.python.org/3/reference/datamodel.html&quot;&gt;Python Data Model documentation&lt;/a&gt; and, specifically for modules and packages, in the &lt;a href=&quot;https://docs.python.org/3/reference/import.html#import-related-module-attributes&quot;&gt;Python Import documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;importing-into-a-module-or-the-interactive-interpreter&quot;&gt;Importing Into a Module or the Interactive Interpreter&lt;/h3&gt;
&lt;p&gt;Now let&amp;rsquo;s take a look at the second way that the Python interpreter will execute your code: imports. When you are developing a module or script, you will most likely want to take advantage of modules that someone else has already built, which you can do with the &lt;code&gt;import&lt;/code&gt; keyword.&lt;/p&gt;
&lt;p&gt;During the import process, Python executes the statements defined in the specified module (but only the &lt;em&gt;first&lt;/em&gt; time you import a module). To demonstrate the results of importing your &lt;code&gt;execution_methods.py&lt;/code&gt; file, start the interactive Python interpreter and then import your &lt;code&gt;execution_methods.py&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;execution_methods&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;This is my file to test Python&amp;#39;s execution methods.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The variable __name__ tells me which context this file is running in.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;The value of __name__ is: &amp;#39;execution_methods&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code output, you can see that the Python interpreter executes the three calls to &lt;code&gt;print()&lt;/code&gt;. The first two lines of output are exactly the same as when you executed the file as a script on the command line because there are no variables in either of the first two lines. However, there is a difference in the output from the third &lt;code&gt;print()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When the Python interpreter imports code, the value of &lt;code&gt;__name__&lt;/code&gt; is set to be the same as the name of the module that is being imported. You can see this in the third line of output above. &lt;code&gt;__name__&lt;/code&gt; has the value &lt;code&gt;&#39;execution_methods&#39;&lt;/code&gt;, which is the name of the &lt;code&gt;.py&lt;/code&gt; file that Python is importing from.&lt;/p&gt;
&lt;p&gt;Note that if you &lt;code&gt;import&lt;/code&gt; the module again without quitting Python, there will be no output.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; For more information on how importing works in Python, check out the &lt;a href=&quot;https://docs.python.org/3/reference/import.html&quot;&gt;official documentation&lt;/a&gt; as well as &lt;a href=&quot;https://realpython.com/absolute-vs-relative-python-imports/&quot;&gt;Absolute vs Relative Imports in Python&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;best-practices-for-python-main-functions&quot;&gt;Best Practices for Python Main Functions&lt;/h2&gt;
&lt;p&gt;Now that you can see the differences in how Python handles its different execution modes, it&amp;rsquo;s useful for you to know some best practices to use. These will apply whenever you want to write code that you can run as a script &lt;em&gt;and&lt;/em&gt; import in another module or an interactive session.&lt;/p&gt;
&lt;p&gt;You will learn about four best practices to make sure that your code can serve a dual purpose:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Put most code into a function or class.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;__name__&lt;/code&gt; to control execution of your code.&lt;/li&gt;
&lt;li&gt;Create a function called &lt;code&gt;main()&lt;/code&gt; to contain the code you want to run.&lt;/li&gt;
&lt;li&gt;Call other functions from &lt;code&gt;main()&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;put-most-code-into-a-function-or-class&quot;&gt;Put Most Code Into a Function or Class&lt;/h3&gt;
&lt;p&gt;Remember that the Python interpreter executes all the code in a module when it imports the module. Sometimes the code you write will have side effects that you want the user to control, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Running a computation that takes a long time&lt;/li&gt;
&lt;li&gt;Writing to a file on the disk&lt;/li&gt;
&lt;li&gt;Printing information that would clutter the user&amp;rsquo;s terminal&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In these cases, you want the user to control triggering the execution of this code, rather than letting the Python interpreter execute the code when it imports your module.&lt;/p&gt;
&lt;p&gt;Therefore, the best practice is to &lt;strong&gt;include most code inside a function or a class&lt;/strong&gt;. This is because when the Python interpreter encounters the &lt;code&gt;def&lt;/code&gt; or &lt;code&gt;class&lt;/code&gt; keywords, it only stores those definitions for later use and doesn&amp;rsquo;t actually execute them until you tell it to.&lt;/p&gt;
&lt;p&gt;Save the code below to a file called &lt;code&gt;best_practices.py&lt;/code&gt; to demonstrate this idea:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;This is my file to demonstrate best practices.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Beginning data processing...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot; that has been modified&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Data processing finished.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you first import &lt;code&gt;sleep()&lt;/code&gt; from the &lt;a href=&quot;https://realpython.com/python-time-module/&quot;&gt;&lt;code&gt;time&lt;/code&gt; module&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;&lt;code&gt;sleep()&lt;/code&gt; pauses the interpreter for however many seconds you give as an argument and will produce a function that takes a long time to run for this example. Next, you use &lt;code&gt;print()&lt;/code&gt; to print a sentence describing the purpose of this code. &lt;/p&gt;
&lt;p&gt;Then, you define a function called &lt;code&gt;process_data()&lt;/code&gt; that does five things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Prints some output to tell the user that the data processing is starting&lt;/li&gt;
&lt;li&gt;Modifies the input data&lt;/li&gt;
&lt;li&gt;Pauses the execution for three seconds using &lt;code&gt;sleep()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Prints some output to tell the user that the processing is finished&lt;/li&gt;
&lt;li&gt;Returns the modified data&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Execute the Best Practices File on the Command Line&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now, what will happen when you execute this file as a script on the command line? &lt;/p&gt;
&lt;p&gt;The Python interpreter will execute the &lt;code&gt;from time import sleep&lt;/code&gt; and &lt;code&gt;print()&lt;/code&gt; lines that are outside the function definition, then it will create the definition of the function called &lt;code&gt;process_data()&lt;/code&gt;. Then, the script will exit without doing anything further, because the script does not have any code that executes &lt;code&gt;process_data()&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;The code block below shows the result of running this file as a script:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python3 best_practices.py
&lt;span class=&quot;go&quot;&gt;This is my file to demonstrate best practices.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The output that we can see here is the result of the first &lt;code&gt;print()&lt;/code&gt;. Notice that importing from &lt;code&gt;time&lt;/code&gt; and defining &lt;code&gt;process_data()&lt;/code&gt; produce no output. Specifically, the outputs of the calls to &lt;code&gt;print()&lt;/code&gt; that are inside the definition of &lt;code&gt;process_data()&lt;/code&gt; are not printed!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Import the Best Practices File in Another Module or the Interactive Interpreter&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When you import this file in an interactive session (or another module), the Python interpreter will perform exactly the same steps as when it executes file as a script.&lt;/p&gt;
&lt;p&gt;Once the Python interpreter imports the file, you can use any variables, classes, or functions defined in the module you&amp;rsquo;ve imported. To demonstrate this, we will use the interactive Python interpreter. Start the interactive interpreter and then type &lt;code&gt;import best_practices&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;best_practices&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;This is my file to demonstrate best practices.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The only output from importing the &lt;code&gt;best_practices.py&lt;/code&gt; file is from the first &lt;code&gt;print()&lt;/code&gt; call defined outside &lt;code&gt;process_data()&lt;/code&gt;. Importing from &lt;code&gt;time&lt;/code&gt; and defining &lt;code&gt;process_data()&lt;/code&gt; produce no output, just like when you executed the code from the command line.&lt;/p&gt;
&lt;h3 id=&quot;use-__name__-to-control-the-execution-of-your-code&quot;&gt;Use &lt;code&gt;__name__&lt;/code&gt; to Control the Execution of Your Code&lt;/h3&gt;
&lt;p&gt;What if you want &lt;code&gt;process_data()&lt;/code&gt; to execute when you run the script from the command line but not when the Python interpreter imports the file? &lt;/p&gt;
&lt;p&gt;You can &lt;strong&gt;use &lt;code&gt;__name__&lt;/code&gt; to determine the execution context&lt;/strong&gt; and conditionally run &lt;code&gt;process_data()&lt;/code&gt; only when &lt;code&gt;__name__&lt;/code&gt; is equal to &lt;code&gt;&quot;__main__&quot;&lt;/code&gt;. Add the code below to the bottom of your &lt;code&gt;best_practices.py&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My data read from the Web&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;process_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you&amp;rsquo;ve added a conditional statement that checks the value of &lt;code&gt;__name__&lt;/code&gt;. This conditional will evaluate to &lt;code&gt;True&lt;/code&gt; when &lt;code&gt;__name__&lt;/code&gt; is equal to the string &lt;code&gt;&quot;__main__&quot;&lt;/code&gt;. Remember that the special value of &lt;code&gt;&quot;__main__&quot;&lt;/code&gt; for the &lt;code&gt;__name__&lt;/code&gt; variable means the Python interpreter is executing your script and not importing it.&lt;/p&gt;
&lt;p&gt;Inside the conditional block, you have added four lines of code (lines 12, 13, 14, and 15):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lines 12 and 13:&lt;/strong&gt; You are creating a variable &lt;code&gt;data&lt;/code&gt; that stores the data you&amp;rsquo;ve acquired from the Web and printing it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 14:&lt;/strong&gt; You are processing the data.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 15:&lt;/strong&gt; You are printing the modified data. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, run your &lt;code&gt;best_practices.py&lt;/code&gt; script from the command line to see how the output will change:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python3 best_practices.py
&lt;span class=&quot;go&quot;&gt;This is my file to demonstrate best practices.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;My data read from the Web&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Beginning data processing...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Data processing finished.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;My data read from the Web that has been modified&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;First, the output shows the result of the &lt;code&gt;print()&lt;/code&gt; call outside of &lt;code&gt;process_data()&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;After that, the value of &lt;code&gt;data&lt;/code&gt; is printed. This happened because the variable &lt;code&gt;__name__&lt;/code&gt; has the value &lt;code&gt;&quot;__main__&quot;&lt;/code&gt; when the Python interpreter executes the file as a script, so the conditional statement evaluated to &lt;code&gt;True&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;Next, your script called &lt;code&gt;process_data()&lt;/code&gt; and passed &lt;code&gt;data&lt;/code&gt; in for modification. When &lt;code&gt;process_data()&lt;/code&gt; executes, it prints some status messages to the output. Finally, the value of &lt;code&gt;modified_data&lt;/code&gt; is printed.&lt;/p&gt;
&lt;p&gt;Now you should check what happens when you import the &lt;code&gt;best_practices.py&lt;/code&gt; file from the interactive interpreter (or another module). The example below demonstrates this situation:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;best_practices&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;This is my file to demonstrate best practices.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice that you get the same behavior as before you added the conditional statement to the end of the file! This is because the &lt;code&gt;__name__&lt;/code&gt; variable had the value &lt;code&gt;&quot;best_practices&quot;&lt;/code&gt;, so Python did not execute the code inside the block, including &lt;code&gt;process_data()&lt;/code&gt;, because the conditional statement evaluated to &lt;code&gt;False&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;create-a-function-called-main-to-contain-the-code-you-want-to-run&quot;&gt;Create a Function Called main() to Contain the Code You Want to Run&lt;/h3&gt;
&lt;p&gt;Now you are able to write Python code that can be run from the command line as a script and imported without unwanted side effects. Next, you are going to learn about how to write your code to make it easy for other Python programmers to follow what you mean.&lt;/p&gt;
&lt;p&gt;Many languages, such as C, C++, Java, and several others, define a special function that must be called &lt;code&gt;main()&lt;/code&gt; that the operating system automatically calls when it executes the compiled program. This function is often called the &lt;strong&gt;entry point&lt;/strong&gt; because it is where execution enters the program.&lt;/p&gt;
&lt;p&gt;By contrast, Python does not have a special function that serves as the entry point to a script. You can actually give the entry point function in a Python script any name you want!&lt;/p&gt;
&lt;p&gt;Although Python does not assign any significance to a function named &lt;code&gt;main()&lt;/code&gt;, the best practice is to &lt;strong&gt;name the entry point function &lt;code&gt;main()&lt;/code&gt;&lt;/strong&gt; anyways. That way, any other programmers who read your script immediately know that this function is the starting point of the code that accomplishes the primary task of the script.&lt;/p&gt;
&lt;p&gt;In addition, &lt;code&gt;main()&lt;/code&gt; should contain any code that you want to run when the Python interpreter executes the file. This is better than putting the code directly into the conditional block because a user can reuse &lt;code&gt;main()&lt;/code&gt;if they import your module.&lt;/p&gt;
&lt;p&gt;Change the &lt;code&gt;best_practices.py&lt;/code&gt; file so that it looks like the code below:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;This is my file to demonstrate best practices.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Beginning data processing...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot; that has been modified&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Data processing finished.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My data read from the Web&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;process_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you added the definition of &lt;code&gt;main()&lt;/code&gt; that includes the code that was previously inside the conditional block. Then, you changed the conditional block so that it executes &lt;code&gt;main()&lt;/code&gt;. If you run this code as a script or import it, you will get the same output as in the previous section.&lt;/p&gt;
&lt;h3 id=&quot;call-other-functions-from-main&quot;&gt;Call Other Functions From main()&lt;/h3&gt;
&lt;p&gt;Another common practice in Python is to &lt;strong&gt;have &lt;code&gt;main()&lt;/code&gt; execute other functions&lt;/strong&gt;, rather than including the task-accomplishing code in &lt;code&gt;main()&lt;/code&gt;. This is especially useful when you can compose your overall task from several smaller sub-tasks that can execute independently.&lt;/p&gt;
&lt;p&gt;For example, you may have a script that does the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Reads a data file from a source that could be a database, a file on the disk, or a web API&lt;/li&gt;
&lt;li&gt;Processes the data&lt;/li&gt;
&lt;li&gt;Writes the processed data to another location&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you implement each of these sub-tasks in separate functions, then it is easy for a you (or another user) to re-use a few of the steps and ignore the ones you don&amp;rsquo;t want. Then you can create a default workflow in &lt;code&gt;main()&lt;/code&gt;, and you can have the best of both worlds.&lt;/p&gt;
&lt;p&gt;Whether to apply this practice to your code is a judgment call on your part. Splitting the work into several functions makes reuse easier but increases the difficulty for someone else trying to interpret your code because they have to follow several jumps in the flow of the program.&lt;/p&gt;
&lt;p&gt;Modify your &lt;code&gt;best_practices.py&lt;/code&gt; file so that it looks like the code below:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;This is my file to demonstrate best practices.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;process_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Beginning data processing...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot; that has been modified&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Data processing finished.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;read_data_from_web&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Reading data from the Web&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Data from the web&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write_data_to_database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Writing data to a database&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;read_data_from_web&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;process_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;write_data_to_database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;vm&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;__main__&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example code, the first 10 lines of the file have the same content that they had before. The second function definition on line 12 creates and returns some sample data, and the third function definition on line 17 simulates writing the modified data to a database.&lt;/p&gt;
&lt;p&gt;On line 21, &lt;code&gt;main()&lt;/code&gt; is defined. In this example, you have modified &lt;code&gt;main()&lt;/code&gt; so that it calls the data reading, data processing, and data writing functions in turn.&lt;/p&gt;
&lt;p&gt;First, the &lt;code&gt;data&lt;/code&gt; is created from &lt;code&gt;read_data_from_web()&lt;/code&gt;. This &lt;code&gt;data&lt;/code&gt; is passed to &lt;code&gt;process_data()&lt;/code&gt;, which returns the &lt;code&gt;modified_data&lt;/code&gt;. Finally, &lt;code&gt;modified_data&lt;/code&gt; is passed into &lt;code&gt;write_data_to_database()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The last two lines of the script are the conditional block that checks &lt;code&gt;__name__&lt;/code&gt; and runs &lt;code&gt;main()&lt;/code&gt; if the &lt;code&gt;if&lt;/code&gt; statement is &lt;code&gt;True&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now, you can run the whole processing pipeline from the command line, as shown below:&lt;/p&gt;
&lt;div class=&quot;highlight sh&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python3 best_practices.py
&lt;span class=&quot;go&quot;&gt;This is my file to demonstrate best practices.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Reading data from the Web&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Beginning data processing...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Data processing finished.&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing processed data to a database&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Data from the web that has been modified&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the output from this execution, you can see that the Python interpreter executed &lt;code&gt;main()&lt;/code&gt;, which executed &lt;code&gt;read_data_from_web()&lt;/code&gt;, &lt;code&gt;process_data()&lt;/code&gt;, and &lt;code&gt;write_data_to_database()&lt;/code&gt;. However, you can also import the &lt;code&gt;best_practices.py&lt;/code&gt; file and re-use &lt;code&gt;process_data()&lt;/code&gt; for a different input data source, as shown below:&lt;/p&gt;
&lt;div class=&quot;highlight python pycon&quot;&gt;&lt;span class=&quot;repl-toggle&quot; title=&quot;Toggle REPL prompts and output&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;best_practices&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;bp&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;This is my file to demonstrate best practices.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Data from a file&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;process_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Beginning data processing...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Data processing finished.&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;write_data_to_database&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;modified_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Writing processed data to a database&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Data from a file that has been modified&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you imported &lt;code&gt;best_practices&lt;/code&gt; and shortened the name to &lt;code&gt;bp&lt;/code&gt; for this code.&lt;/p&gt;
&lt;p&gt;The import process caused the Python interpreter to execute all of the lines of code in the &lt;code&gt;best_practices.py&lt;/code&gt; file, so the output shows the line explaining the purpose of the file.&lt;/p&gt;
&lt;p&gt;Then, you stored data from a file in &lt;code&gt;data&lt;/code&gt; instead of reading the data from the Web. Then, you reused &lt;code&gt;process_data()&lt;/code&gt;and &lt;code&gt;write_data_to_database()&lt;/code&gt; from the &lt;code&gt;best_practices.py&lt;/code&gt; file. In this case, you took advantage of reusing your code instead of defining all of the logic in &lt;code&gt;main()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;summary-of-python-main-function-best-practices&quot;&gt;Summary of Python Main Function Best Practices&lt;/h3&gt;
&lt;p&gt;Here are four key best practices about &lt;code&gt;main()&lt;/code&gt; in Python that you just saw:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Put code that takes a long time to run or has other effects on the computer in a function or class, so you can control exactly when that code is executed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the different values of &lt;code&gt;__name__&lt;/code&gt; to determine the context and change the behavior of your code with a conditional statement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You should name your entry point function &lt;code&gt;main()&lt;/code&gt; in order to communicate the intention of the function, even though Python does not assign any special significance to a function named &lt;code&gt;main()&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you want to reuse functionality from your code, define the logic in functions outside &lt;code&gt;main()&lt;/code&gt; and call those functions within &lt;code&gt;main()&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Congratulations! You now know how to create Python &lt;code&gt;main()&lt;/code&gt; functions.&lt;/p&gt;
&lt;p&gt;You learned the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Knowing the value of the &lt;code&gt;__name__&lt;/code&gt; variable is important to write code that serves the dual purpose of executable script and importable module.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;__name__&lt;/code&gt; takes on different values depending on how you executed your Python file. &lt;code&gt;__name__&lt;/code&gt; will be equal to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&quot;__main__&quot;&lt;/code&gt; when the file is executed from the command line or with &lt;code&gt;python -m&lt;/code&gt; (to execute a package&amp;rsquo;s &lt;code&gt;__main__.py&lt;/code&gt; file)&lt;/li&gt;
&lt;li&gt;The name of the module, if the module is being imported&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Python programmers have developed a set of good practices to use when you want to develop reusable code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you&amp;rsquo;re ready to go write some awesome Python &lt;code&gt;main()&lt;/code&gt; function code!&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Make a Location-Based Web App With Django and GeoDjango</title>
      <id>https://realpython.com/courses/make-location-based-web-app-django-and-geodjango/</id>
      <link href="https://realpython.com/courses/make-location-based-web-app-django-and-geodjango/"/>
      <updated>2019-04-30T14:00:00+00:00</updated>
      <summary>Learn how to use Django and GeoDjango to build a location-based web application from scratch. You’ll be building a simple nearby shops application that lists the shops closest to a user’s location.</summary>
      <content type="html">
        &lt;p&gt;Throughout this course, you&amp;rsquo;ll learn how to use Django and GeoDjango to build a location-based web application from scratch. You&amp;rsquo;ll be building a simple nearby shops application that lists the shops closest to a user&amp;rsquo;s location. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this course, you&amp;rsquo;ll be able to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Use Django to build a simple web application from scratch&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use the GeoDjango sub-framework to implement geolocation features in your Django application&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use a spatial database (PostgreSQL and PostGIS) to get benefits from the spatial features and easily implement location-aware web apps&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Downloadable Sample Project:&lt;/strong&gt; This course includes a downloadable sample project that demonstrates the final state of the Django app you&amp;rsquo;ll build throughout the course. You can get the source code for it &lt;a href=&quot;https://github.com/realpython/materials/tree/master/geoshops&quot;&gt;here on the &lt;code&gt;materials&lt;/code&gt; repo&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>How to Get the Most Out of PyCon</title>
      <id>https://realpython.com/pycon-guide/</id>
      <link href="https://realpython.com/pycon-guide/"/>
      <updated>2019-04-29T14:00:00+00:00</updated>
      <summary>In this article, you&#39;ll learn how you can get the most out of PyCon. Whether you&#39;re a first-timer or a seasoned attendee, this guide will help you get ready to have a great PyCon.</summary>
      <content type="html">
        &lt;p&gt;Congratulations!  You&amp;rsquo;re going to PyCon! &lt;/p&gt;
&lt;p&gt;Whether this is your first time or not, going to a conference full of people who love the same thing as you is always a fun experience. There&amp;rsquo;s so much more to PyCon than just a bunch of people talking about the Python language, and that can be intimidating for first-time attendees. This guide will help you navigate all there is to see and do at PyCon.&lt;/p&gt;
&lt;p&gt;PyCon (US/North America) is the biggest conference centered around the Python language.  Originally formed in 2003, this conference has grown exponentially and has even spawned several other &lt;a href=&quot;https://www.python.org/community/workshops/&quot;&gt;PyCons and workshops around the world&lt;/a&gt;.  &lt;/p&gt;
&lt;p&gt;This year will mark my fourth year in a row attending PyCon, so I thought that I would share some of the notes that I&amp;rsquo;ve taken over the years to help you get the most out of your PyCon experience.&lt;/p&gt;
&lt;p&gt;Everyone who attends PyCon will have a different experience, and that&amp;rsquo;s what makes the conference truly unique.  This guide is meant to help you, but you don&amp;rsquo;t need to follow it strictly.&lt;/p&gt;
&lt;p&gt;This guide will have links that are specific to PyCon 2019, but it should be useful for future PyCons as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this article, you&amp;rsquo;ll know:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What PyCon involves&lt;/li&gt;
&lt;li&gt;What to do before you go&lt;/li&gt;
&lt;li&gt;What to do while you&amp;rsquo;re at PyCon&lt;/li&gt;
&lt;li&gt;What to do after PyCon&lt;/li&gt;
&lt;li&gt;How to have a great PyCon&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-tricks-sample&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a chapter from Python Tricks: The Book&lt;/a&gt; that shows you Python&#39;s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;what-pycon-involves&quot;&gt;What PyCon Involves&lt;/h2&gt;
&lt;p&gt;Before we go into how to get the most out of PyCon, let&amp;rsquo;s first establish what PyCon involves.  &lt;/p&gt;
&lt;p&gt;PyCon is broken up into three stages, as described by the &lt;a href=&quot;https://us.pycon.org/2019/about/&quot;&gt;official PyCon site&lt;/a&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Tutorials:&lt;/strong&gt; We start with two days of 3-hour classes during which you get to learn in depth with instructors.  These are great to go to since the class sizes are small, and you can ask questions of the instructors.  I highly recommend going to at least one of these if you can, but they do have an additional cost of $150 per class.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Conference:&lt;/strong&gt; Next, we have three days of talks. Each presentation lasts for 30 to 45 minutes, and there are about 5 talks going on at a time.  But that&amp;rsquo;s not all: there are also open spaces, sponsors, lightning talks, dinners, and so much more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Sprints:&lt;/strong&gt; During this stage, you can take what you&amp;rsquo;ve learned and apply it!  This is a 3-day exercise in which people group up to work on various open source projects all related to Python.  If you&amp;rsquo;ve got the time, I highly suggest that you go to this as it&amp;rsquo;s a great way to practice what you&amp;rsquo;ve learned, become associated with an open source project, and network with very smart and talented people.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Since most PyCon attendees go to the Conference part, that will be the focus of this article.  However, don&amp;rsquo;t let that deter you from attending the Tutorials or Sprints if you can!  &lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve personally found that I&amp;rsquo;ve learned more technical skills by attending the Tutorials rather than listening to the talks.  The Sprints are great for networking and applying the skills that you&amp;rsquo;ve already got as well as learning new ones from the people you&amp;rsquo;ll be working with.&lt;/p&gt;
&lt;h2 id=&quot;what-to-do-before-you-go&quot;&gt;What to Do Before You Go&lt;/h2&gt;
&lt;p&gt;In general, the more prepared you are for something, the better your experience will be.  The same applies for PyCon.  &lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s really helpful to plan and prepare ahead of time, which you&amp;rsquo;re already doing just by reading this article! &lt;/p&gt;
&lt;p&gt;Look through the &lt;a href=&quot;https://us.pycon.org/2019/schedule/talks/&quot;&gt;talk schedule&lt;/a&gt; and see which talks sound most interesting to you.  This doesn&amp;rsquo;t mean you need to plan out all of the talks you are going to see for every slot possible, but it helps to get an idea of which topics are going to be presented so you can decide what you&amp;rsquo;re most interested in.&lt;/p&gt;
&lt;p&gt;Getting the &lt;a href=&quot;https://guidebook.com/getit/&quot;&gt;Guidebook app&lt;/a&gt; will help you plan you schedule.  This app lets you view the schedule for the talks and add reminders for the ones you want to attend.  If you&amp;rsquo;re having a hard time picking which talks to go to, you can come prepared with a question or problem you need solved.  Doing this can help you focus on the topics that are important to you.&lt;/p&gt;
&lt;p&gt;If you can, come the day before to check in and attend the opening reception.  The line up to check in on the first day is always long, so you&amp;rsquo;ll save time if you check in the day before. There&amp;rsquo;s also usually an opening reception that evening, so you can meet other attendees and speakers, as well as get a chance to check out the various sponsors and their booths.  &lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re brand new to PyCon, there&amp;rsquo;s also a &lt;a href=&quot;https://us.pycon.org/2019/events/newcomer_orientation/&quot;&gt;Newcomer Orientation&lt;/a&gt; that can help you get caught up on what the conference involves and how you can participate.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what to do before you go:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Look at the &lt;a href=&quot;https://us.pycon.org/2019/schedule/talks/&quot;&gt;talk schedule&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Get the &lt;a href=&quot;https://guidebook.com/getit/&quot;&gt;Guidebook App&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Come up with a specific question you want answered.&lt;/li&gt;
&lt;li&gt;Check in the day before the conference.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h2 id=&quot;what-to-do-at-pycon&quot;&gt;What to Do at PyCon&lt;/h2&gt;
&lt;p&gt;It&amp;rsquo;s okay if you&amp;rsquo;re nervous or excited on your first day at the conference.  &lt;/p&gt;
&lt;p&gt;There will be a lot of people from all different walks of life, and that&amp;rsquo;s what makes it so great.  You may see some of your Python heroes, such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Guido_van_Rossum&quot;&gt;Guido van Rossum&lt;/a&gt; and and have a chance to go up to them and say hello.  &lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/image_from_ios_1024.e1c21475bd73.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/image_from_ios_1024.e1c21475bd73.jpg&quot; width=&quot;768&quot; height=&quot;1024&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/image_from_ios_1024.e1c21475bd73.jpg&amp;amp;w=192&amp;amp;sig=f4111d2a2bc62514e13a8a4ed878bbd9d5f2cf87 192w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/image_from_ios_1024.e1c21475bd73.jpg&amp;amp;w=384&amp;amp;sig=b34f92fa89c6002763709f90d8ac6bd88d6ac078 384w, https://files.realpython.com/media/image_from_ios_1024.e1c21475bd73.jpg 768w&quot; sizes=&quot;75vw&quot; alt=&quot;Guido van Rossum With the Python Staff of Enlightenment&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Guido van Rossum With the Python Staff of Enlightenment&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The Python community is very welcoming! But there are also some designated quiet rooms, where speakers and others will go to work in peace.  You should refrain from talking to anyone in those rooms to allow them that safe space.  &lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s break down the conference into some key elements and see how you can get the most out of them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Talks&lt;/li&gt;
&lt;li&gt;Open spaces&lt;/li&gt;
&lt;li&gt;Sponsors&lt;/li&gt;
&lt;li&gt;Volunteering opportunities&lt;/li&gt;
&lt;li&gt;Lightning talks&lt;/li&gt;
&lt;li&gt;After hours activities&lt;/li&gt;
&lt;li&gt;Time for yourself&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;talks&quot;&gt;Talks&lt;/h3&gt;
&lt;p&gt;Go to as many of the talks as you want, but you don&amp;rsquo;t need to go to all of them.  You&amp;rsquo;ll only find yourself getting stressed as you run from room to room.  Instead, make sure that you hit up the talks that you selected before coming.  Although it&amp;rsquo;s pretty rare, the schedule can change, so check the schedule board daily to catch any changes.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/IMG_1218.d0a4f0992bbf.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/IMG_1218.d0a4f0992bbf.jpg&quot; width=&quot;4032&quot; height=&quot;3024&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/IMG_1218.d0a4f0992bbf.jpg&amp;amp;w=1008&amp;amp;sig=e717a9717f60bada8f09a85bc53ac992edb09561 1008w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/IMG_1218.d0a4f0992bbf.jpg&amp;amp;w=2016&amp;amp;sig=08a01693ed8497f1765c458533d59e78de12cdd1 2016w, https://files.realpython.com/media/IMG_1218.d0a4f0992bbf.jpg 4032w&quot; sizes=&quot;75vw&quot; alt=&quot;A talk at PyCon 2018&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;&#39;Data Visualization in Mixed Reality with Python&#39; Talk Given by Anna Nicanorova at PyCon 2018&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;If there&amp;rsquo;s a conflict between two talks that you to really want to go to, remember that each talk is recorded and &lt;a href=&quot;https://realpython.com/must-watch-pycon-talks/&quot;&gt;uploaded onto YouTube&lt;/a&gt;. Sometimes, they&amp;rsquo;re even available that same day!  Pick the talk that is going to be the most relevant to your situation and seems the most interesting to you.  Then take note of the talk that you missed to watch it later that evening or the next day when you have some free time.  &lt;/p&gt;
&lt;p&gt;Even though all talks are available online, actually going to the talks is still valuable. You&amp;rsquo;ll retain the information better if you attend, and you&amp;rsquo;ll have the opportunity to ask questions directly of the presenter.&lt;/p&gt;
&lt;p&gt;Keep in mind that you don&amp;rsquo;t need to see all of the &amp;ldquo;celebrity&amp;rdquo; speakers.  These speakers get a lot of attention in the Python community and may seem like more worthwhile speakers because of that. But the process of getting a talk approved at PyCon is rigorous and ensures that each speaker and topic are worth listening to.  &lt;/p&gt;
&lt;p&gt;In fact, sometimes it&amp;rsquo;s better to go see some of the less famous speakers because you can get better seats and have a greater chance to ask questions.&lt;/p&gt;
&lt;p&gt;When you go to a talk, remember to silence your phone and computer.  Noise can be very distracting to the audience and the speaker.  It might be helpful to put away all your devices and simply listen or take notes using a pad and paper.  &lt;/p&gt;
&lt;p&gt;Try to think of questions that you may have about what&amp;rsquo;s being discussed.  Typically, there&amp;rsquo;s time allotted at the end for questions from the audience. If that doesn&amp;rsquo;t happen, the presenters are usually very accommodating about answering questions in the hall afterwards.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what you need to know about talks at PyCon:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You don&amp;rsquo;t need to go to all of the talks and will be able to watch them on YouTube.&lt;/li&gt;
&lt;li&gt;All talks and speakers are amazing.&lt;/li&gt;
&lt;li&gt;Keep the noise to a minimum during the talks.&lt;/li&gt;
&lt;li&gt;Think of questions to ask.&lt;/li&gt;
&lt;li&gt;Talk to the speakers afterwards.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3 id=&quot;open-spaces&quot;&gt;Open Spaces&lt;/h3&gt;
&lt;p&gt;Open Spaces are rooms that can be booked by conference attendees.  There are 1-hour slots throughout the day available to anyone that wants to use them. These rooms have been used as places to teach people, hold meetups, and even do yoga classes.  They&amp;rsquo;re open for whatever activities you need them for, as long as you follow the &lt;a href=&quot;https://us.pycon.org/2019/about/code-of-conduct/&quot;&gt;Code of Conduct&lt;/a&gt; of course.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Dc39EWtX0AEzuYw.7fc9513c8818.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/Dc39EWtX0AEzuYw.7fc9513c8818.jpg&quot; width=&quot;1200&quot; height=&quot;900&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Dc39EWtX0AEzuYw.7fc9513c8818.jpg&amp;amp;w=300&amp;amp;sig=bc2e7f6252121d06c256f9e49e114b9a0d4cf471 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Dc39EWtX0AEzuYw.7fc9513c8818.jpg&amp;amp;w=600&amp;amp;sig=6259219c955012fc21580fe525ad887525b88a0d 600w, https://files.realpython.com/media/Dc39EWtX0AEzuYw.7fc9513c8818.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Example of the PyCon Open Spaces board&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Open Spaces Board at PyCon 2018&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;You might want to go to these open spaces instead of a talk or a sponsor booth. Be sure to check out the open space board each day since it constantly changes.  It might be helpful to take a picture of the board to reference later.  &lt;/p&gt;
&lt;p&gt;Feel free to create your own open space. Remember that problem or specific question that you were looking for help with?  Sign up for a room and ask for advice on that topic! You never know who might show up to help out. &lt;/p&gt;
&lt;p&gt;I did that one year. While I was working on one of my open source projects, I ran into a testing problem that I just couldn&amp;rsquo;t solve.  I grabbed an open space for an hour and asked for help. I learned all about the &lt;code&gt;mock&lt;/code&gt; module for testing. That saved me literally hours of work!&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re an expert or even have some limited knowledge about a topic that you want to share, feel free to grab an open space for that as well!  These spaces are intended to be whatever you want and need them to be, so don&amp;rsquo;t be shy about using them.  In fact, be on the lookout for a Real Python open space and feel free to join us as we talk about what we envision for the future.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what you need to know about open spaces at PyCon:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open spaces can be whatever you need them to be.&lt;/li&gt;
&lt;li&gt;Use an open space slot to ask for help.&lt;/li&gt;
&lt;li&gt;Use an open space slot to teach others.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3 id=&quot;sponsors&quot;&gt;Sponsors&lt;/h3&gt;
&lt;p&gt;Visiting sponsors is a great way to get to know some of the companies that are using Python in their everyday businesses.  There are some very big names that come almost every year: Microsoft, JetBrains, and Google, to name a few.  There are over 100 sponsors at PyCon 2019!  Going to a sponsor booth is great for many reasons, not just the wonderful SWAG that everyone gives out. Here&amp;rsquo;s some of ours:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/realpython-swag.c9e198956be2.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/realpython-swag.c9e198956be2.jpg&quot; width=&quot;1920&quot; height=&quot;1440&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/realpython-swag.c9e198956be2.jpg&amp;amp;w=480&amp;amp;sig=32af9a144752e5b147216d75ba2507c2ab2c421f 480w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/realpython-swag.c9e198956be2.jpg&amp;amp;w=960&amp;amp;sig=019cb0cf3ad3de2bb4cc491161aac79a794e3e61 960w, https://files.realpython.com/media/realpython-swag.c9e198956be2.jpg 1920w&quot; sizes=&quot;75vw&quot; alt=&quot;Real Python Swag: Stickers and a Pin&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Real Python Swag: Meet us at PyCon and get some stickers&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The greatest thing about sponsors being there is that you can speak with the actual developers of the tools and software you use.  Let&amp;rsquo;s say you have a problem with an Anaconda install on a Windows environment. You can go straight up to them and ask questions!  This is a great opportunity to talk to the developers and creators of the tools you use.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s not just developers that you get to meet either.  There are authors and content creators who come too.  O&amp;rsquo;Reily typically has an author or two a day who comes for you to meet and chat with.  &lt;a href=&quot;https://blog.jetbrains.com/pycharm/2019/04/pycharm-hosts-python-creators-at-expanded-pycon-booth/&quot;&gt;This year, JetBrains  will be hosting content creators at their booth&lt;/a&gt;, where you can meet some of the &lt;a href=&quot;https://realpython.com/team/&quot;&gt;Real Python Team&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;Finally, meeting with the sponsors could lead to an opportunity for a job.  A lot of the sponsors are also looking for talented Python developers, and you can apply directly with them at the booths or during the job fair towards the end of the conference.  If you&amp;rsquo;re not looking for a job, it&amp;rsquo;s still great to see what is out there and what skills these companies are looking for to help better choose what to focus on with your learning.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what you need to know about sponsors at PyCon:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Getting sponsor SWAG is great.&lt;/li&gt;
&lt;li&gt;Meeting with the developers and content creators is even better.&lt;/li&gt;
&lt;li&gt;You can apply for a job or see what skills companies are looking for.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3 id=&quot;volunteering-opportunities&quot;&gt;Volunteering Opportunities&lt;/h3&gt;
&lt;p&gt;Have you ever wished you could contribute or give back to the Python Community?  Well, you can at PyCon.  &lt;/p&gt;
&lt;p&gt;So much work goes into making a conference happen, and none of it would be possible without volunteers.  The 2019 PyCon conference is looking for over 300-man hours of volunteering alone!  &lt;/p&gt;
&lt;p&gt;That sounds like a lot, but you can still make a difference. An hour or two of your time can be a big help but still not take away from your learning time.  You also never know who you might rub shoulders with as a volunteer.  You can learn more about helping out in the &lt;a href=&quot;https://us.pycon.org/2019/about/volunteers/&quot;&gt;Call for On-Site Volunteers&lt;/a&gt;.  There&amp;rsquo;s a little something for everyone.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what you need to know about volunteering at PyCon:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Just Do It.&lt;/li&gt;
&lt;li&gt;Really, Just Do It!&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3 id=&quot;after-hours-activities&quot;&gt;After Hours Activities&lt;/h3&gt;
&lt;p&gt;Even though the conference ends in the early evening, there&amp;rsquo;s still more to do after the conference wraps up for the day. &lt;/p&gt;
&lt;p&gt;The first thing you should check out, even if only for a little while, is the lightning talks.  These are 5 minute &amp;ldquo;soap boxes&amp;rdquo; for anyone to share on a topic.  These talks cover a wide range of topics: anything from a new open source project to social commentary to philanthropic topics.  Did you know that &lt;a href=&quot;https://www.youtube.com/watch?v=wW9CAH9nSLs&quot;&gt;Docker was first publicly announced during a PyCon lightning talk&lt;/a&gt;?  The lightning talks have become a popular staple of regular attendees.&lt;/p&gt;
&lt;p&gt;Also be on the lookout for sponsors doing sponsored dinners with members of their company.  This is a great way to build up your network and get a free dinner as well.  PyCon does host dinner parties in the evenings, but these cost money and typically sell out really fast.  &lt;/p&gt;
&lt;p&gt;Even if you don&amp;rsquo;t get in on the official PyCon dinners or the sponsored ones, there&amp;rsquo;s always plenty to check out near the conference.  Each conference location is selected in part because of the interesting things nearby.  When you&amp;rsquo;re getting ready for the conference, look for fun places to go eat.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what you need to know about after-hours events at PyCon:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check out the lightning talks.&lt;/li&gt;
&lt;li&gt;If there are spots available, sign up for one of the official PyCon dinners.&lt;/li&gt;
&lt;li&gt;Check early and often for any sponsored dinners.&lt;/li&gt;
&lt;li&gt;Have fun exploring the local cuisine and culture.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h3 id=&quot;new-friends&quot;&gt;New Friends&lt;/h3&gt;
&lt;p&gt;One of the greatest pieces of advice that I received when I first started going to PyCon was to make a new friend each day.  &lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/slack-imgs.com.07f581566314.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/slack-imgs.com.07f581566314.jpg&quot; width=&quot;1200&quot; height=&quot;901&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/slack-imgs.com.07f581566314.jpg&amp;amp;w=300&amp;amp;sig=101f7a2b6b8c54e1b2c86e4b35a3f3416ffac883 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/slack-imgs.com.07f581566314.jpg&amp;amp;w=600&amp;amp;sig=7f9721210a1948572248ef7a5ea68387adfd56a9 600w, https://files.realpython.com/media/slack-imgs.com.07f581566314.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Our very own Dan Bader and Anthony Shaw&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Dan Bader and Anthony Shaw&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;Some of the best times to get to know someone at PyCon are the lunch and snack breaks.  Instead of trying to pick an empty table to sit at, find one that already has a person or two and ask if you can join them.  Strike up a conversation about what their favorite talk is thus far, or how they use Python in their day to day activities.  Pretty soon you&amp;rsquo;ll make a new friend.  You can take a few notes, whether mentally or literally, about your conversation so you can remember that person later on.&lt;/p&gt;
&lt;p&gt;You might want to make some business cards with the contact info you want to share with people you meet in order to stay in contact with them.  PyCon will actually give you a few to give out, but you can go through them really quickly! Be sure to update any profiles that you share with people such as LinkedIn or GitHub.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what you need to know about making new friends at PyCon:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Take the challenge to meet at least one new person each day.&lt;/li&gt;
&lt;li&gt;Make a note of who that person is so that you don&amp;rsquo;t forget.&lt;/li&gt;
&lt;li&gt;Bring business cards to share with people you meet.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h2 id=&quot;what-to-do-after-pycon&quot;&gt;What to Do After PyCon&lt;/h2&gt;
&lt;p&gt;Once the conference is over, there&amp;rsquo;s still a lot you can do.  First off, if you have the time, there are the Sprints, which are a great opportunity for you to hone your skills and even gain new ones as a Python developer.  They last for four days after the Conference, but you don&amp;rsquo;t need to stay for the entire time.  Stay for as long as you like, whether that&amp;rsquo;s for a few hours or a few days.&lt;/p&gt;
&lt;p&gt;After you get home, make sure to check out the YouTube videos of talks you missed or made a note to watch again.  There&amp;rsquo;s also all of the tutorials, keynote speaker talks, and even the lightning talks to check out.  There&amp;rsquo;s plenty there for you to get your PyCon fix throughout the year.&lt;/p&gt;
&lt;p&gt;The greatest thing about PyCon is the feeling of belonging to a community.  That&amp;rsquo;s only made possible by the great people who give back to the Python community, and you can become one of them!  &lt;/p&gt;
&lt;p&gt;There are lots of ways that you can give back to this great community:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Contribute to an open source project that uses Python.&lt;/li&gt;
&lt;li&gt;Join a local Python meetup group.  Don&amp;rsquo;t have one?  Create one!&lt;/li&gt;
&lt;li&gt;Share with others what you&amp;rsquo;ve learned.&lt;/li&gt;
&lt;li&gt;Submit a talk or poster for next year&amp;rsquo;s PyCon.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Finally, you can start preparing for the next PyCon.  When you purchase tickets early, you get a discount on the pricing, but those tickets go pretty fast too.  You can also start taking note of any problems or questions that you can&amp;rsquo;t find the answer to in preparation for selecting talks to check out at the next PyCon.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Recap:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s what you need to know about what to do after the conference:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;If you have the time, stay for the Sprints.&lt;/li&gt;
&lt;li&gt;Check out the YouTube videos of the talks you missed or loved.&lt;/li&gt;
&lt;li&gt;Look for a way to contribute back to the Python community with what you learned.&lt;/li&gt;
&lt;li&gt;Start looking at next year&amp;rsquo;s PyCon.&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
&lt;h2 id=&quot;welcome-to-the-greatest-community&quot;&gt;Welcome to the Greatest Community!&lt;/h2&gt;
&lt;p&gt;Congratulation!  You&amp;rsquo;re about to attend one of the greatest technical conferences there is out there.  &lt;/p&gt;
&lt;p&gt;In this article, you learned:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;What PyCon is all about&lt;/li&gt;
&lt;li&gt;What you can do before coming to PyCon&lt;/li&gt;
&lt;li&gt;What you can do at PyCon&lt;/li&gt;
&lt;li&gt;What you can do after PyCon&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;With the tips in this article, you&amp;rsquo;ll be able to have a great PyCon.  We look forward to seeing you there!&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Conditional Statements in Python (if/elif/else)</title>
      <id>https://realpython.com/courses/python-conditional-statements/</id>
      <link href="https://realpython.com/courses/python-conditional-statements/"/>
      <updated>2019-04-25T14:00:00+00:00</updated>
      <summary>In this step-by-step course you&#39;ll learn how to work with conditional (&quot;if&quot;) statements in Python. Master if-statements step-by-step and see how to write complex decision making code in your programs.</summary>
      <content type="html">
        &lt;p&gt;In this step-by-step course you&amp;rsquo;ll learn how to work with conditional (&amp;ldquo;if&amp;rdquo;) statements in Python. Master if-statements step-by-step and see how to write complex decision making code in your programs.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;&lt;i class=&quot;fa fa-graduation-cap&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt; Take the Quiz:&lt;/strong&gt; Test your knowledge with our interactive “Python Conditional Statements” quiz. Upon completion you will receive a score so you can track your learning progress over time:&lt;/p&gt;&lt;p class=&quot;text-center my-2&quot;&gt;&lt;a class=&quot;btn btn-primary&quot; href=&quot;/quizzes/python-conditional-statements/&quot; target=&quot;_blank&quot;&gt;Take the Quiz »&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Sending Emails With Python</title>
      <id>https://realpython.com/courses/sending-emails-python/</id>
      <link href="https://realpython.com/courses/sending-emails-python/"/>
      <updated>2019-04-23T14:00:00+00:00</updated>
      <summary>In this course, you&#39;ll learn how to send emails using Python. Find out how to send plain-text and HTML messages, add files as attachments, and send personalized emails to multiple people. Later on you&#39;ll build a CSV-powered email sending script from scratch.</summary>
      <content type="html">
        &lt;p&gt;In this course, you&amp;rsquo;ll learn how to send emails using Python. Find out how to send plain-text and HTML messages, add files as attachments, and send personalized emails to multiple people. Later on you&amp;rsquo;ll build a CSV-powered email sending script from scratch.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Immutability in Python</title>
      <id>https://realpython.com/courses/immutability-python/</id>
      <link href="https://realpython.com/courses/immutability-python/"/>
      <updated>2019-04-18T14:00:00+00:00</updated>
      <summary>In Python, immutable vs mutable data types and objects types can cause some confusion—and weird bugs. With this course you&#39;ll see what the difference between mutable and immutable data types is in Python, and how you can use it to your advantage in your own programs.</summary>
      <content type="html">
        &lt;p&gt;In Python, immutable vs mutable data types and objects types can cause some confusion—and weird bugs. With this video course you&amp;rsquo;ll see what the difference between mutable and immutable data types is in Python, and how you can use it to your advantage in your own programs.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll also see how to deal with a language quirk in Python that allows objects referenced by immutable types to me modified. Python&amp;rsquo;s definition of &amp;ldquo;immutable&amp;rdquo; can be a bit misleading.&lt;/p&gt;
&lt;p&gt;Basically, the promise of &amp;ldquo;immutability&amp;rdquo; on tuples is only partly true. The tuple itself cannot be modified, but objects referenced by the tuple can be. This is sometimes called &amp;ldquo;non-transitive immutability.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;If the tuple has an immutable field like a string for example, then it cannot be modified. A mutable field like a list however, can be edited, even if it&amp;rsquo;s embedded in the &amp;ldquo;immutable&amp;rdquo; tuple.&lt;/p&gt;
&lt;p&gt;When the Python documentation refers to an object as being &amp;ldquo;immutable&amp;rdquo; they mean the behavior above observed. Other immutable types in Python behave the same way, e.g. namedtuples or frozensets.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;ve ever encountered the following exception and now you want to know why, this is the video course for you:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;TypeError: &amp;#39;tuple&amp;#39; object does not support item assignment
&lt;/pre&gt;&lt;/div&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  
    <entry>
      <title>Hands-on Python 3 Concurrency With the asyncio Module</title>
      <id>https://realpython.com/courses/python-3-concurrency-asyncio-module/</id>
      <link href="https://realpython.com/courses/python-3-concurrency-asyncio-module/"/>
      <updated>2019-04-16T14:00:00+00:00</updated>
      <summary>Learn how to speed up your Python 3 programs using concurrency and the asyncio module in the standard library. See step-by-step how to leverage concurrency and parallelism in your own programs, all the way to building a complete HTTP downloader example app using asyncio and aiohttp.</summary>
      <content type="html">
        &lt;p&gt;Learn how to speed up your Python 3 programs using concurrency and the new &lt;code&gt;asyncio&lt;/code&gt; module in the standard library. &lt;/p&gt;
&lt;p&gt;First, you&amp;rsquo;ll explore the key terms of parallel programming. Next, you&amp;rsquo;ll see step-by-step how to leverage concurrency and parallelism in your own programs, all the way to building a complete HTTP downloader example app using &lt;code&gt;asyncio&lt;/code&gt; and &lt;code&gt;aiohttp&lt;/code&gt;.&lt;/p&gt;
        &lt;hr /&gt;
        &lt;p&gt;&lt;em&gt;[ Improve Your Python With 🐍 Python Tricks 💌 – Get a short &amp;amp; sweet Python Trick delivered to your inbox every couple of days. &lt;a href=&quot;https://realpython.com/python-tricks/?utm_source=realpython&amp;amp;utm_medium=rss&amp;amp;utm_campaign=footer&quot;&gt;&amp;gt;&amp;gt; Click here to learn more and see examples&lt;/a&gt; ]&lt;/em&gt;&lt;/p&gt;
      </content>
    </entry>
  

</feed>
