<?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-06-18T14:00:00+00:00</updated>
  <id>https://realpython.com/</id>
  <author>
    <name>Real Python</name>
  </author>

  
    <entry>
      <title>How to Publish Your Own Python Package to PyPI</title>
      <id>https://realpython.com/courses/how-to-publish-your-own-python-package-pypi/</id>
      <link href="https://realpython.com/courses/how-to-publish-your-own-python-package-pypi/"/>
      <updated>2019-06-18T14:00:00+00:00</updated>
      <summary>Learn how to create a Python package for your project and how to publish it to PyPI, the Python Package Repository with this step-by-step course. Quickly get up to speed on everything from naming your package to configuring it using setup.py.</summary>
      <content type="html">
        &lt;p&gt;Learn how to create a Python package for your project and how to publish it to PyPI, the Python Package Repository with this step-by-step course. Quickly get up to speed on everything from naming your package to configuring it using &lt;code&gt;setup.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>Python Community Interview With Marlene Mhangami</title>
      <id>https://realpython.com/interview-marlene-mhangami/</id>
      <link href="https://realpython.com/interview-marlene-mhangami/"/>
      <updated>2019-06-17T14:00:00+00:00</updated>
      <summary>Join us as we chat with Marlene Mhangami. She&#39;s a PSF Director and the co-founder of ZimboPy, a Zimbabwean non-profit that empowers women to pursue careers in tech. She&#39;s also organizing the very first PyCon Africa.</summary>
      <content type="html">
        &lt;p&gt;We are joined today by Marlene Mhangami. &lt;a href=&quot;https://twitter.com/marlene_zw&quot;&gt;Marlene&lt;/a&gt; is a passionate Pythonista who is not only using tech to facilitate social change and empower Zimbabwean women but is also the chair of the very first &lt;a href=&quot;https://africa.pycon.org/&quot;&gt;PyCon Africa&lt;/a&gt;. Join me as we talk about her non-traditional start in tech, as well as her passion for using technology to create social change for good.&lt;/p&gt;
&lt;p class=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;Welcome, Marlene! I&amp;rsquo;m so glad you could join me for this interview. Let&amp;rsquo;s start with the usual first question. How&amp;rsquo;d you get into programming, and when did you start using Python?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/IMG_9845.a13bccafc9ec.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid w-25 float-right ml-3 rounded-circle&quot; src=&quot;https://files.realpython.com/media/IMG_9845.a13bccafc9ec.jpg&quot; width=&quot;1923&quot; height=&quot;2207&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/IMG_9845.a13bccafc9ec.jpg&amp;amp;w=480&amp;amp;sig=82a21586db37d56365319d2296719011e3d72cef 480w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/IMG_9845.a13bccafc9ec.jpg&amp;amp;w=961&amp;amp;sig=e91c5a935bc742b737577261686abb179de92862 961w, https://files.realpython.com/media/IMG_9845.a13bccafc9ec.jpg 1923w&quot; sizes=&quot;75vw&quot; alt=&quot;Marlene Mhangami&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marlene:&lt;/strong&gt; Well, my background is in molecular biology, so in college, although I had some interaction with code, it wasn&amp;rsquo;t really something I used regularly. I&amp;rsquo;ve always been interested in technology and the impact it has on the world, but growing up I didn&amp;rsquo;t really have anyone to introduce me to the concept of coding. We had one computer that we shared in my house, and my brothers were super into gaming. They were on it all the time.&lt;/p&gt;
&lt;p&gt;In high school, I took a computer class, but my teachers, who I&amp;rsquo;m sure were really nice people, didn&amp;rsquo;t go much further than the basics of using Microsoft Office and having us memorize names of different parts of hardware. So, in general, I focused more on life and physical sciences, and I&amp;rsquo;m still really interested in those fields today.&lt;/p&gt;
&lt;p&gt;I studied for a bit in the United States for college, and I remember coming home one summer and being really aware of how different Zimbabwe was from the U.S. From really small cultural differences like how people address conflict (which is something I&amp;rsquo;m still trying to figure out with my US friends) to much more impactful things like access to knowledge and education. &lt;/p&gt;
&lt;p&gt;I decided I wanted to start being more involved with my local community, and for some reason, I decided that I wanted to leverage technology to help me do that. I also had a really vivid dream that made me re-evaluate what I was doing with my life. &lt;/p&gt;
&lt;p&gt;After googling around and actually organizing a meetup, I got introduced to one of my co-founders, &lt;a href=&quot;https://www.linkedin.com/in/ronald-t-maravanyika-78221131/&quot;&gt;Ronald Maravanykia&lt;/a&gt;, who was at the time running a &lt;a href=&quot;https://djangogirls.org/&quot;&gt;Django girls&lt;/a&gt; workshop in Harare. He introduced me to Python as a great educational tool for teaching programming to people who don&amp;rsquo;t have a computer science background. That was almost three years ago, and I&amp;rsquo;m super grateful Python ended up being the language I chose to focus on. It&amp;rsquo;s really great!&lt;/p&gt;
&lt;p class=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;As a Zimbabwean, you are passionate about empowering Zimbabwean women in tech and helping today&amp;rsquo;s young girls pursue a career in tech. So much so that you are the programs director at the non-profit ZimboPy?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marlene:&lt;/strong&gt; Yes, as I mentioned earlier, using technology to create social change for good is something that&amp;rsquo;s consistently at the forefront of my mind. My co-founders and I decided to create &lt;a href=&quot;https://www.zimbopy.com/&quot;&gt;ZimboPy&lt;/a&gt; as a way to give girls in Zim access to knowledge and experiences they wouldn&amp;rsquo;t necessarily get anywhere else in the country. &lt;/p&gt;
&lt;p&gt;I think for me, the end goal is to create a model where we introduce girls to programming, and if they enjoy it, offering them a pathway to get jobs in the field. The tech world is not perfect, but unlike most fields, there are ways that you can by-pass traditional gatekeepers and be successful regardless of whether or not you have the privilege of receiving formal higher education. &lt;/p&gt;
&lt;p&gt;We are still a small non-profit, and I&amp;rsquo;m learning new things every day, but we&amp;rsquo;ve had some great success stories that give me so much hope! Also, our mentorship weeks, where we introduce girls to women who are doing incredible things in the field and help them build something new, are my favorite thing to do all year! We&amp;rsquo;ve had incredible women like Ashley McNamara and Emily Freeman speak. It&amp;rsquo;s always so much fun!&lt;/p&gt;
&lt;p class=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;You are one of the 13 members of the &lt;a href=&quot;https://www.python.org/psf/&quot;&gt;Python Software Foundation&amp;rsquo;s (PSF)&lt;/a&gt; Board of Directors. How did you come to be involved with the PSF, and what do you think is the biggest challenge as we look towards 2020 and beyond?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marlene:&lt;/strong&gt; I&amp;rsquo;m actually up for re-election this year, so hopefully, I&amp;rsquo;ll still be on the board for 2020. I really had such a positive experience with it so far! &lt;/p&gt;
&lt;p&gt;I was actually introduced to the PSF by &lt;a href=&quot;https://twitter.com/loooorenanicole&quot;&gt;Lorena Mesa&lt;/a&gt;, who was volunteering to speak at one of our ZimboPy mentorship weeks in early 2017. She was on the board at the time, and we spoke about it around the time when elections were coming up. She really felt that I would be a great addition to the board. At that time, no one from Africa had ever held a seat, so she was super encouraging. &lt;/p&gt;
&lt;p&gt;I remember looking through the list of the nominees and thinking that I didn&amp;rsquo;t belong there. I had done some work with the local Python community in Zimbabwe, but I felt really intimidated by everyone&amp;rsquo;s profiles. I ended up agreeing to let Lorena nominate me, mainly because I had nothing to lose, haha! Surprisingly, I was voted in, which I think is purely a testament to the Python community&amp;rsquo;s commitment to diversity and global representation. &lt;/p&gt;
&lt;p&gt;So many changes have taken place in the last few years: the formation of the steering council, the exponential growth of PyCon, and the spread of the language globally. All of these are things we&amp;rsquo;ve been able to discuss as a board. &lt;/p&gt;
&lt;p&gt;I think defining the biggest challenge is tricky because it genuinely depends on each individual&amp;rsquo;s perspective. There are Directors on the board who are infinitely more technical than I am, and they can probably speak to all sorts of challenges on the future of Python from a more technical perspective. &lt;/p&gt;
&lt;p&gt;For me, my focus is to help the growth of Python and its community to be as inclusive and representative as possible. I recently became the board&amp;rsquo;s communications co-chair, along with Lorena, and have been working with the blogging team. I&amp;rsquo;d like to see an increase in the representation of voices from communities around the world, maybe one day having blog posts and content on the official site in various languages. &lt;/p&gt;
&lt;p&gt;All of these are things I feel are important and a challenge that we have to tackle well. &lt;/p&gt;
&lt;p class=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;I had the good fortune to meet you in person at PyCon 2019. It was your first PyCon (mine, too). How was your experience there? What was the standout moment for you?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marlene:&lt;/strong&gt; I genuinely loved Pycon 2019, and of course meeting you, Ricky, and the rest of the &lt;em&gt;Real Python&lt;/em&gt; team! I&amp;rsquo;ve been to several PyCons around Africa and other parts of the world, but PyCon US is definitely a unique experience. &lt;/p&gt;
&lt;p&gt;One of my favorite things about the conference was how friendly and laid back everyone was. I&amp;rsquo;d literally pass by people that I follow on Twitter, who have done amazing things, and they&amp;rsquo;d just be sitting there, eating a sandwich! I&amp;rsquo;m being a little funny here, but honestly, everyone was so welcoming and fun. I still can&amp;rsquo;t fully wrap my head around it.&lt;/p&gt;
&lt;p&gt;I had so many standout moments, but I think I&amp;rsquo;d say Sha Wallace and Jessica Meckeller&amp;rsquo;s joint keynote was out of this world. I was tearing up because it&amp;rsquo;s such a great example of how we as a community can create positive change! I took away so many notes from that talk that I&amp;rsquo;d like to implement here in Zimbabwe. &lt;/p&gt;
&lt;p&gt;This is an additional thing, I know, but I&amp;rsquo;d also like to say that I had so many standout moments outside the convention center, like having dinner with people from around the world and going to the local art gallery and trying bubble tea, also generally just wandering about the city. I had the best time, and I&amp;rsquo;m really looking forward to Pittsburg in 2020!&lt;/p&gt;
&lt;p class=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;If my memory serves right, at the end of PyCon, &lt;a href=&quot;https://twitter.com/nnja/status/1126514450830385157&quot;&gt;Microsoft and Adafruit donated a bunch of Circuit Playground Lunchbox Kits&lt;/a&gt; for you to take back to the girls you mentor in Zimbabwe. I&amp;rsquo;m curious if you managed to put them to use yet? Or what your plans are, outside of using them to teach them how to write some CircuitPython?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marlene:&lt;/strong&gt; Yes! That was another standout moment (to add to the twenty others above, haha). I got to chat with &lt;a href=&quot;https://twitter.com/nnja&quot;&gt;Nina Zakharenko&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/kattni&quot;&gt;Katni from Adafruit&lt;/a&gt;, who are some of the loveliest human beings I&amp;rsquo;ve ever met! We had dinner together at some point and afterwards, they decided to donate the kits for me to bring back home and use for our ZimboPy programs. &lt;/p&gt;
&lt;p&gt;I only recently got back to Zimbabwe, and I&amp;rsquo;ve started to play around with the kits myself. The plan at the moment is to host a workshop specifically centered around CircuitPython to show the girls that they can be playful and have fun while they code. I&amp;rsquo;m super pumped about it! &lt;/p&gt;
&lt;p&gt;I was also talking to Kat about the potential of me hosting a tutorial at PyCon Africa with the Adafruit boards, similar to what she was demoing at the Microsoft booth. If I feel confident enough to do it by July, I think that&amp;rsquo;s something attendees at the conference should look out for! &lt;/p&gt;
&lt;p class=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;As if all the community work you do already isn&amp;rsquo;t enough, you&amp;rsquo;re also the organizer of the very first PyCon Africa! How&amp;rsquo;s the planning coming on? Can you share any details?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marlene:&lt;/strong&gt; I&amp;rsquo;m really excited that we&amp;rsquo;re in the final stages of planning for the conference. PyCon Africa is the first regional / pan-African gathering of the Python community! We have a great organizing committee, with people who have helped organize PyCons in Nigeria, Ghana, Namibia, Uganda, South Africa, and even the UK, so in that respect, I&amp;rsquo;ve been really lucky to land on this team. &lt;/p&gt;
&lt;p&gt;The response from the global Python community has also been really encouraging. &lt;em&gt;Real Python&lt;/em&gt; is actually &lt;a href=&quot;https://africa.pycon.org/our-sponsors/&quot;&gt;one of our sponsors&lt;/a&gt;, which is amazing. Shout out to you! I think we&amp;rsquo;re moving in the right direction.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m this year&amp;rsquo;s chair, and although everything is running smoothly so far, I&amp;rsquo;ve been surprised by how all-consuming the process of planning can feel at times. Each time I look up it&amp;rsquo;s as if 3 months have passed! At PyCon US, I was speaking to a few other regional conference organizers and was glad to find I wasn&amp;rsquo;t the only one that felt like this. It can feel pretty overwhelming sometimes, but for the most part, I&amp;rsquo;m happy with the progress we&amp;rsquo;ve made and optimistic that we will put on a great event! &lt;/p&gt;
&lt;p&gt;The conference is going to be held in &lt;strong&gt;Accra, Ghana, this year from August 6 to 10&lt;/strong&gt;. We&amp;rsquo;re looking for sponsors, and there&amp;rsquo;s an option for individuals to buy a &lt;strong&gt;sharing ticket&lt;/strong&gt; to sponsor a Pythonista who doesn&amp;rsquo;t have the means to buy their own ticket! You can find out more info on all this on our website: &lt;a href=&quot;https://africa.pycon.org/&quot;&gt;africa.pycon.org&lt;/a&gt;&lt;/p&gt;
&lt;p class=&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? Any other hobbies and interests, aside from Python and coding?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Marlene:&lt;/strong&gt; I really enjoy long walks on the beach, haha. I&amp;rsquo;m joking, but I also genuinely do! I&amp;rsquo;ve been getting into running recently, and I&amp;rsquo;m hoping to try to get myself into good enough form to do a marathon at some point. &lt;/p&gt;
&lt;p&gt;I also really like painting, but not in a cultured, cool way. I sometimes just like to paint and draw as a way to relax. Meditation and gratefulness journaling is also something I like to do each morning, as a good way to start the day. &lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;It was an absolute pleasure speaking to Marlene. If you want to attend PyCon Africa, &lt;a href=&quot;https://africa.pycon.org/register/&quot;&gt;tickets are still available&lt;/a&gt;. If you want to find out more about Marlene, or reach out to her and discuss any of the amazing things she is doing, then you can &lt;a href=&quot;https://twitter.com/marlene_zw&quot;&gt;find her on Twitter&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>How to Build Command Line Interfaces in Python With argparse</title>
      <id>https://realpython.com/command-line-interfaces-python-argparse/</id>
      <link href="https://realpython.com/command-line-interfaces-python-argparse/"/>
      <updated>2019-06-12T14:00:00+00:00</updated>
      <summary>In this step-by-step Python tutorial, you&#39;ll learn how to take your command line Python scripts to the next level by adding a convenient command line interface that you can write with argparse.</summary>
      <content type="html">
        &lt;p&gt;One of the strengths of Python is that it comes with batteries included: it has a rich and versatile standard library that makes it one of the best programming languages for writing scripts for the &lt;a href=&quot;https://realpython.com/comparing-python-command-line-parsing-libraries-argparse-docopt-click/&quot;&gt;command line&lt;/a&gt;.
But, if you write &lt;a href=&quot;https://realpython.com/run-python-scripts/&quot;&gt;scripts&lt;/a&gt; for the command line, then you also need to provide a good command line interface, which you can create with the Python &lt;code&gt;argparse&lt;/code&gt; library.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this article, you&amp;rsquo;ll learn:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What the Python &lt;code&gt;argparse&lt;/code&gt; library is, and why it&amp;rsquo;s important to use it if you need to write command line scripts in Python&lt;/li&gt;
&lt;li&gt;How to use the Python &lt;code&gt;argparse&lt;/code&gt; library to quickly create a simple CLI in Python&lt;/li&gt;
&lt;li&gt;What the advanced usage of the Python &lt;code&gt;argparse&lt;/code&gt; library is&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article is written for early &lt;a href=&quot;https://realpython.com/intermediate-python-project-ideas/&quot;&gt;intermediate&lt;/a&gt; Pythonistas who probably write scripts in Python for their everyday work but have never implemented a command line interface for their scripts. &lt;/p&gt;
&lt;p&gt;If that sounds like you, and you&amp;rsquo;re used to setting variable values at the beginning of your scripts or manually parsing the &lt;code&gt;sys.argv&lt;/code&gt; system list instead of using a more robust CLI development tool, then this article is for you.&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;what-is-a-command-line-interface&quot;&gt;What Is a Command Line Interface?&lt;/h2&gt;
&lt;p&gt;The command line interface (also known as &lt;strong&gt;CLI&lt;/strong&gt;) is a means to interact with a command line script. Python comes with several different libraries that allow you to write a command line interface for your scripts, but the standard way for creating a CLI in Python is currently the Python &lt;code&gt;argparse&lt;/code&gt; library.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://docs.python.org/3/library/argparse.html&quot;&gt;Python &lt;code&gt;argparse&lt;/code&gt; library&lt;/a&gt; was released as part of the standard library with Python 3.2 on February the 20th, 2011. It was introduced with &lt;a href=&quot;https://www.python.org/dev/peps/pep-0389/&quot;&gt;Python Enhancement Proposal 389&lt;/a&gt; and is now the standard way to create a CLI in Python, both in 2.7 and 3.2+ versions.&lt;/p&gt;
&lt;p&gt;This new module was released as a replacement for the older &lt;a href=&quot;https://docs.python.org/3/library/getopt.html&quot;&gt;&lt;code&gt;getopt&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://docs.python.org/3/library/optparse.html&quot;&gt;&lt;code&gt;optparse&lt;/code&gt;&lt;/a&gt; modules because they were lacking some important features.&lt;/p&gt;
&lt;p&gt;The Python &lt;code&gt;argparse&lt;/code&gt; library:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Allows the use of positional arguments&lt;/li&gt;
&lt;li&gt;Allows the customization of the prefix chars&lt;/li&gt;
&lt;li&gt;Supports variable numbers of parameters for a single option&lt;/li&gt;
&lt;li&gt;Supports subcommands (A main command line parser can use other command line parsers depending on some arguments.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before getting started, you need to know how a command line interface works, so open a terminal on your computer and execute the command &lt;code&gt;ls&lt;/code&gt; to get the list of the files contained in the current directory 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; ls
&lt;span class=&quot;go&quot;&gt;dcdb_20180201.sg4    mastro35.sg4        openings.sg4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;dcdb_20180201.si4    mastro35.si4        openings.si4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;dcdb_20180201.sn4    mastro35.sn4        openings.sn4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, there are a bunch of files in the current directory, but the command didn&amp;rsquo;t return a lot of information about these files.&lt;/p&gt;
&lt;p&gt;The good news is that you don&amp;rsquo;t need to look around for another program to have a richer list of the files contained in the current directory. You also don&amp;rsquo;t need to modify the &lt;code&gt;ls&lt;/code&gt; command yourself, because it adopts a command line interface, that is just a set of tokens (called &lt;strong&gt;arguments&lt;/strong&gt;) that you can use to configure the behavior of this command.&lt;/p&gt;
&lt;p&gt;Now try to execute the command &lt;code&gt;ls&lt;/code&gt; again, but with adding the &lt;code&gt;-l&lt;/code&gt; option to the command line as in 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;$&lt;/span&gt; ls -l
&lt;span class=&quot;go&quot;&gt;total 641824&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-------  1 dave  staff  204558286  5 Mar  2018 dcdb_20180201.sg4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-------  1 dave  staff  110588409  5 Mar  2018 dcdb_20180201.si4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-------  1 dave  staff    2937516  5 Mar  2018 dcdb_20180201.sn4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-------  1 dave  staff     550127 27 Mar  2018 mastro35.sg4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-------  1 dave  staff      15974 11 Gen 17:01 mastro35.si4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-------  1 dave  staff       3636 27 Mar  2018 mastro35.sn4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-------  1 dave  staff      29128 17 Apr  2018 openings.sg4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-------  1 dave  staff        276 17 Apr  2018 openings.si4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-rw-------  1 dave  staff         86 18 Apr  2018 openings.sn4&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The output is very different now. The command has returned a lot of information about the permissions, owner, group, and size of each file and the total directory occupation on the disk.&lt;/p&gt;
&lt;p&gt;This is because you used the command line interface of the &lt;code&gt;ls&lt;/code&gt; command and specified the &lt;code&gt;-l&lt;/code&gt; option that enables the long format, a special format that returns a lot more information for every single file listed.&lt;/p&gt;
&lt;p&gt;In order to familiarize yourself with this topic, you&amp;rsquo;re going to read a lot about arguments, options, and parameters, so let&amp;rsquo;s clarify the terminology right away:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;argument&lt;/strong&gt; is a single part of a command line, delimited by blanks.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;option&lt;/strong&gt; is a particular type of argument (or a part of an argument) that can modify the behavior of the command line.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;parameter&lt;/strong&gt; is a particular type of argument that provides additional information to a single option or command.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Consider the following command:&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; ls -l -s -k /var/log
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you have five different arguments:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ls&lt;/code&gt;:&lt;/strong&gt; the name of the command you are executing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;-l&lt;/code&gt;:&lt;/strong&gt; an option to enable the long list format&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;-s&lt;/code&gt;:&lt;/strong&gt; an option to print the allocated size of each file&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;-k&lt;/code&gt;:&lt;/strong&gt; an option to have the size in kilobytes&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;/var/log&lt;/code&gt;:&lt;/strong&gt; a parameter that provides additional information (the path to list) to the command&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note that, if you have multiple options in a single command line, then you can combine them into a single argument 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; ls -lsk /var/log
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here you have only three arguments:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ls&lt;/code&gt; :&lt;/strong&gt; the name of the command you are executing&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;-lsk&lt;/code&gt;:&lt;/strong&gt; the three different options you want to enable (a combination of &lt;code&gt;-l&lt;/code&gt;, &lt;code&gt;-s&lt;/code&gt;, and &lt;code&gt;-k&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;/var/log&lt;/code&gt;:&lt;/strong&gt; a parameter that provides additional information (the path to list) to the command&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;when-to-use-a-command-line-interface&quot;&gt;When to Use a Command Line Interface&lt;/h2&gt;
&lt;p&gt;Now that you know what a command line interface is, you may be wondering when it&amp;rsquo;s a good idea to implement one in your programs. The rule of thumb is that, if you want to provide a user-friendly approach to configuring your program, then you should consider a command line interface, and the standard way to do it is by using the Python &lt;code&gt;argparse&lt;/code&gt; library.&lt;/p&gt;
&lt;p&gt;Even if you&amp;rsquo;re creating a complex command line program that needs a configuration file to work, if you want to let your user specify which configuration file to use, it&amp;rsquo;s a good idea to accept this value by creating a command line interface with the Python &lt;code&gt;argparse&lt;/code&gt; library.&lt;/p&gt;
&lt;h2 id=&quot;how-to-use-the-python-argparse-library-to-create-a-command-line-interface&quot;&gt;How to Use the Python &lt;code&gt;argparse&lt;/code&gt; Library to Create a Command Line Interface&lt;/h2&gt;
&lt;p&gt;Using the Python &lt;code&gt;argparse&lt;/code&gt; library has four steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Import the Python &lt;code&gt;argparse&lt;/code&gt; library&lt;/li&gt;
&lt;li&gt;Create the parser&lt;/li&gt;
&lt;li&gt;Add optional and positional arguments to the parser&lt;/li&gt;
&lt;li&gt;Execute &lt;code&gt;.parse_args()&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After you execute &lt;code&gt;.parse_args()&lt;/code&gt;, what you get is a &lt;a href=&quot;https://docs.python.org/dev/library/argparse.html#argparse.Namespace&quot;&gt;&lt;code&gt;Namespace&lt;/code&gt; object&lt;/a&gt; that contains a simple property for each input argument received from the command line.&lt;/p&gt;
&lt;p&gt;In order to see these four steps in detail with an example, let&amp;rsquo;s pretend you&amp;rsquo;re creating a program named &lt;code&gt;myls.py&lt;/code&gt; that lists the files contained in the current directory.
Here&amp;rsquo;s a possible implementation of your command line interface without using the Python &lt;code&gt;argparse&lt;/code&gt; library:&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;# myls.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&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;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;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&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;2&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;You have specified too many arguments&amp;#39;&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;exit&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;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argv&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;mi&quot;&gt;2&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;You need to specify the path to be listed&amp;#39;&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;exit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;input_path&lt;/span&gt; &lt;span class=&quot;o&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;argv&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;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;os&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_path&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;The path specified does not exist&amp;#39;&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;exit&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;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&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;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is a possible implementation of the command line interface for your program that doesn&amp;rsquo;t use the Python &lt;code&gt;argparse&lt;/code&gt; library, but if you try to execute it, then you&amp;rsquo;ll see that it works:&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; python myls.py
&lt;span class=&quot;go&quot;&gt;You need to specify the path to be listed&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python myls.py /mnt /proc /dev
&lt;span class=&quot;go&quot;&gt;You have specified too many arguments&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python myls.py /mnt
&lt;span class=&quot;go&quot;&gt;dir1&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;dir2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the script does work, but the output is quite different from the output you&amp;rsquo;d expect from a standard built-in command.&lt;/p&gt;
&lt;p&gt;Now, let&amp;rsquo;s see how the Python &lt;code&gt;argparse&lt;/code&gt; library can improve this 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;c1&quot;&gt;# myls.py&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Import the argparse library&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&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;c1&quot;&gt;# Create the parser&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;List the content of a folder&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Add the arguments&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Path&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;metavar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;path&amp;#39;&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;o&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;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;the path to list&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Execute the parse_args() method&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;input_path&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Path&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;os&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_path&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;The path specified does not exist&amp;#39;&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;exit&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;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&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;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code has changed a lot with the introduction of the Python &lt;code&gt;argparse&lt;/code&gt; library.&lt;/p&gt;
&lt;p&gt;The first big difference compared to the previous version is that the &lt;code&gt;if&lt;/code&gt; statements to check the arguments provided by the user are gone because the library will check the presence of the arguments for us.&lt;/p&gt;
&lt;p&gt;We&amp;rsquo;ve imported the Python &lt;code&gt;argparse&lt;/code&gt; library, created a simple parser with a brief description of the program&amp;rsquo;s goal, and defined the positional argument we want to get from the user.
Lastly, we have executed &lt;code&gt;.parse_args()&lt;/code&gt; to parse the input arguments and get a &lt;code&gt;Namespace&lt;/code&gt; object that contains the user input.&lt;/p&gt;
&lt;p&gt;Now, if you run this code, you&amp;rsquo;ll see that with just four lines of code. You have a very different output:&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; python myls.py
&lt;span class=&quot;go&quot;&gt;usage: myls.py [-h] path&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;myls.py: error: the following arguments are required: path&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the program has detected that you needed at least a positional argument (&lt;code&gt;path&lt;/code&gt;), and so the execution of the program has been interrupted with a specific error message.&lt;/p&gt;
&lt;p&gt;You may also have noticed that now your program accepts an optional &lt;code&gt;-h&lt;/code&gt; flag, like in 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;$&lt;/span&gt; python myls.py -h
&lt;span class=&quot;go&quot;&gt;usage: myls.py [-h] path&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;List the content of a folder&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;positional arguments:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;path        the path to list&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;optional arguments:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-h, --help  show this help message and exit&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Good, now the program responds to the &lt;code&gt;-h&lt;/code&gt; flag, displaying a help message that tells the user how to use the program. Isn&amp;rsquo;t that neat, considering that you didn&amp;rsquo;t even need to ask for that feature?&lt;/p&gt;
&lt;p&gt;Lastly, with just four lines of code, now the &lt;code&gt;args&lt;/code&gt; variable is a &lt;code&gt;Namespace&lt;/code&gt; object, which has a property for each argument that has been gathered from the command line. That&amp;rsquo;s super convenient.&lt;/p&gt;
&lt;h2 id=&quot;the-advanced-use-of-the-python-argparse-library&quot;&gt;The Advanced Use of the Python &lt;code&gt;argparse&lt;/code&gt; Library&lt;/h2&gt;
&lt;p&gt;In the previous section, you learned the basic usage of the Python &lt;code&gt;argparse&lt;/code&gt; library, and now you can implement a simple command line interfaces for all your programs. However, there&amp;rsquo;s a lot more that you can achieve with this library. In this section, you&amp;rsquo;ll see almost everything this library can offer you.&lt;/p&gt;
&lt;h3 id=&quot;setting-the-name-of-the-program&quot;&gt;Setting the Name of the Program&lt;/h3&gt;
&lt;p&gt;By default, the library uses the value of the &lt;code&gt;sys.argv[0]&lt;/code&gt; element to set the name of the program, which as you probably already know is the name of the Python script you have executed. However, you can specify the name of your program just by using the &lt;code&gt;prog&lt;/code&gt; keyword:&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;# Create the parser&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myls&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;List the content of a folder&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the &lt;code&gt;prog&lt;/code&gt; keyword, you specify the name of the program that will be used in the help text:  &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; python myls.py
&lt;span class=&quot;go&quot;&gt;usage: myls [-h] path&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;myls.py: error: the following arguments are required: path&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, now the program name is just &lt;code&gt;myls&lt;/code&gt; instead of &lt;code&gt;myls.py&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;displaying-a-custom-program-usage-help&quot;&gt;Displaying a Custom Program Usage Help&lt;/h3&gt;
&lt;p&gt;By default, the program usage help has a standard format defined by the Python &lt;code&gt;argparse&lt;/code&gt; library.
However, you can customize it with the &lt;code&gt;usage&lt;/code&gt; keyword 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;c1&quot;&gt;# Create the parser&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;myls&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;n&quot;&gt;usage&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;si&quot;&gt;%(prog)s&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; [options] path&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;List the content of a folder&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that, at runtime, the &lt;code&gt;%(prog)s&lt;/code&gt; token is automatically replaced with the name of your program:&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; python myls.py
&lt;span class=&quot;go&quot;&gt;usage: myls [options] path&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;myls: error: too few arguments&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the help of the program now shows a different usage string, where the &lt;code&gt;[-h]&lt;/code&gt; option has been replaced by a generic &lt;code&gt;[options]&lt;/code&gt; token.&lt;/p&gt;
&lt;h3 id=&quot;displaying-text-before-and-after-the-arguments-help&quot;&gt;Displaying Text Before and After the Arguments Help&lt;/h3&gt;
&lt;p&gt;To customize the text displayed before and after the arguments help text, you can use two different keywords:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;description&lt;/code&gt;:&lt;/strong&gt; for the text that is shown before the help text&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;epilog&lt;/code&gt;:&lt;/strong&gt; for the text shown after the help text&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You&amp;rsquo;ve already seen the &lt;code&gt;description&lt;/code&gt; keyword in the previous chapter, so let&amp;rsquo;s see an example of how the &lt;code&gt;epilog&lt;/code&gt; keyword works:&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;# Create the parser&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;List the content of a folder&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;n&quot;&gt;epilog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Enjoy the program! :)&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;code&gt;epilog&lt;/code&gt; keyword here has customized the text that will be shown after the standard help text:&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; python myls.py -h
&lt;span class=&quot;go&quot;&gt;usage: myls.py [-h] path&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;List the content of a folder&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;positional arguments:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;path        the path to list&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;optional arguments:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-h, --help  show this help message and exit&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;Enjoy the program! :)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the output shows the extra text that has been customized by the &lt;code&gt;epilog&lt;/code&gt; keyword.&lt;/p&gt;
&lt;h3 id=&quot;customizing-the-allowed-prefix-chars&quot;&gt;Customizing the Allowed Prefix Chars&lt;/h3&gt;
&lt;p&gt;Another feature that the Python &lt;code&gt;argparse&lt;/code&gt; library offers you is the ability to customize the &lt;strong&gt;prefix chars&lt;/strong&gt;, which are the chars that you can use to pass optional arguments to the command line interface.&lt;/p&gt;
&lt;p&gt;By default, the standard prefix char is the dash (&lt;code&gt;-&lt;/code&gt;) character, but if you want to use a different character, then you can customize it by using the &lt;code&gt;prefix_chars&lt;/code&gt; keyword while defining the parser 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;c1&quot;&gt;# Create the parser&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;List the content of a folder&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;n&quot;&gt;epilog&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Enjoy the program! :)&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;n&quot;&gt;prefix_chars&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;After the redefinition, the program now supports a completely different prefix char, and the help text has changed accordingly:&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; python myls.py
&lt;span class=&quot;go&quot;&gt;usage: myls.py [/h] path&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;myls.py: error: too few arguments&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, now your program does not support the &lt;code&gt;-h&lt;/code&gt; flag but the &lt;code&gt;/h&lt;/code&gt; flag. That&amp;rsquo;s especially useful when you&amp;rsquo;re coding for Microsoft Windows because Windows users are used to these prefix chars when working with the command line.&lt;/p&gt;
&lt;h3 id=&quot;setting-prefix-chars-for-files-that-contain-arguments-to-be-included&quot;&gt;Setting Prefix Chars for Files That Contain Arguments to Be Included&lt;/h3&gt;
&lt;p&gt;When you are dealing with a very long or complicated command line, it can be a good idea to save the arguments to an external file and ask your program to load arguments from it. The Python &lt;code&gt;argparse&lt;/code&gt; library can do this work for you out of the box.&lt;/p&gt;
&lt;p&gt;To test this feature, create the following Python program:&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;# fromfile_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromfile_prefix_chars&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;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&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;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a first argument&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a second argument&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;c&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a third argument&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;d&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a fourth argument&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;e&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a fifth argument&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-v&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;s1&quot;&gt;&amp;#39;--verbose&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store_true&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;an optional argument&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Execute parse_args()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;If you read this line it means that you have provided &amp;#39;&lt;/span&gt;
      &lt;span class=&quot;s1&quot;&gt;&amp;#39;all the parameters&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that we have used the &lt;code&gt;fromfile_prefix_chars&lt;/code&gt; keyword while creating the parser.&lt;/p&gt;
&lt;p&gt;Now, if you try to execute your program without passing any arguments, then you&amp;rsquo;ll get an error message:&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; python fromfile_example.py
&lt;span class=&quot;go&quot;&gt;usage: fromfile_example.py [-h] [-v] a b c d e&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;fromfile_example.py: error: the following arguments are required: a, b, c, d, e&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here you can see that the Python &lt;code&gt;argparse&lt;/code&gt; library is complaining because you have not provided enough arguments.&lt;/p&gt;
&lt;p&gt;So let&amp;rsquo;s create a file named &lt;code&gt;args.txt&lt;/code&gt; that contains all the necessary parameters, with an argument on each line like this:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;first
second
third
fourth
fifth
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that you have specified a prefix char to get arguments from an external file, open a terminal and try to execute the previous program:&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; python fromfile_example.py @args.txt
&lt;span class=&quot;go&quot;&gt;If you read this line it means that you have provided all the parameters&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you can see that &lt;code&gt;argparse&lt;/code&gt; has read the arguments from the &lt;code&gt;args.txt&lt;/code&gt; file.&lt;/p&gt;
&lt;h3 id=&quot;allowing-or-disallowing-abbreviations&quot;&gt;Allowing or Disallowing Abbreviations&lt;/h3&gt;
&lt;p&gt;One of the features that the Python &lt;code&gt;argparse&lt;/code&gt; library provides out of the box is the ability to handle abbreviations. Consider the following program, which prints out the value you specify on the command line interface for the &lt;code&gt;--input&lt;/code&gt; argument:&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;# abbrev_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;--input&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&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;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;required&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;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;--id&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&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;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;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This program prints out the value you specify for the &lt;code&gt;--input&lt;/code&gt; argument. We haven&amp;rsquo;t looked at the optional arguments yet, but don&amp;rsquo;t worry, we will discuss them in depth in just a moment. For now, just consider this argument like any other positional argument we already saw, with the difference that the name starts with a couple of dashes.&lt;/p&gt;
&lt;p&gt;Now let&amp;rsquo;s see how the Python &lt;code&gt;argparse&lt;/code&gt; library can handle abbreviations, by calling our program  multiple times, specifying a different abbreviation of the &lt;code&gt;input&lt;/code&gt; argument at each run:&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; python abbrev_example.py --input &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;42&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python abbrev_example.py --inpu &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;42&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python abbrev_example.py --inp &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;42&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python abbrev_example.py --in &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;42&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the optional parameters can always be shortened unless the abbreviation can lead to an incorrect interpretation.
But what happens if you try to execute the program specifying just &lt;code&gt;--i 42&lt;/code&gt;?
In this case, &lt;code&gt;argparse&lt;/code&gt; doesn&amp;rsquo;t know if you want to pass the value &lt;code&gt;42&lt;/code&gt; to the &lt;code&gt;--input&lt;/code&gt; argument or to the &lt;code&gt;--id&lt;/code&gt; argument, so it exits the program with a specific error message:&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; python abbrev_example.py --i &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;usage: abbrev_example.py [-h] --input INPUT [--id ID]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;abbrev_example.py: error: ambiguous option: --i could match --input, --id&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, if you don&amp;rsquo;t like this behavior, and you want to force your users to specify the full name of the options they use, then you can just disable this feature with the keyword &lt;code&gt;allow_abbrev&lt;/code&gt; set to &lt;code&gt;False&lt;/code&gt; during the creation of the parser:&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;# abbrev_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;allow_abbrev&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;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;--input&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&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;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;required&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;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, if you try the code above, you&amp;rsquo;ll see that the abbreviations are no longer permitted:&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; python abbrev_example.py --inp &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;usage: abbrev_example.py [-h] --input INPUT&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;abbrev_example.py: error: the following arguments are required: --input&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The error message tells the user that the &lt;code&gt;--input&lt;/code&gt; parameter has not been specified because the &lt;code&gt;--inp&lt;/code&gt; abbreviation has not been recognized.&lt;/p&gt;
&lt;h3 id=&quot;using-auto-help&quot;&gt;Using Auto Help&lt;/h3&gt;
&lt;p&gt;In some of the previous examples, you used the &lt;code&gt;-h&lt;/code&gt; flag to get a help text.
This is a very convenient feature that the Python &lt;code&gt;argparse&lt;/code&gt; library allows you to use without having to code anything. However, sometimes you may want to disable this feature.
To do that, just use the &lt;code&gt;add_help&lt;/code&gt; keyword when creating the parser:&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;# Create the parser&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;List the content of a folder&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                                    &lt;span class=&quot;n&quot;&gt;add_help&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code in the example above specifies the &lt;code&gt;add_help&lt;/code&gt; keyword set to &lt;code&gt;False&lt;/code&gt;, so now if you run the code, you&amp;rsquo;ll see that the &lt;code&gt;-h&lt;/code&gt; flag isn&amp;rsquo;t accepted anymore:&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; myls.py
&lt;span class=&quot;go&quot;&gt;usage: myls.py path&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;myls.py: error: the following arguments are required: path&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the &lt;code&gt;-h&lt;/code&gt; flag is no longer shown or accepted.&lt;/p&gt;
&lt;h3 id=&quot;setting-the-name-or-flags-of-the-arguments&quot;&gt;Setting the Name or Flags of the Arguments&lt;/h3&gt;
&lt;p&gt;There are basically two different types of arguments that you can add to your command line interface:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Positional arguments&lt;/li&gt;
&lt;li&gt;Optional arguments&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Positional arguments are the ones your command needs to operate.&lt;/p&gt;
&lt;p&gt;In the previous example, the argument &lt;code&gt;path&lt;/code&gt; was a positional argument, and our program couldn&amp;rsquo;t work without it. They are called &lt;strong&gt;positional&lt;/strong&gt; because their position defines their function.&lt;/p&gt;
&lt;p&gt;For example, consider the &lt;code&gt;cp&lt;/code&gt; command on Linux (or the &lt;code&gt;copy&lt;/code&gt; command in Windows). Here&amp;rsquo;s the standard usage:&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; cp &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;OPTION&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;... &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;-T&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; SOURCE DEST
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first positional argument after the &lt;code&gt;cp&lt;/code&gt; command is the source of the file you&amp;rsquo;re going to copy. The second one is the destination where you want to copy it.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Optional&lt;/strong&gt; arguments are not mandatory, and when they are used they can modify the behavior of the command at runtime. In the &lt;code&gt;cp&lt;/code&gt; example, an optional argument is, for example, the &lt;code&gt;-r&lt;/code&gt; flag, which makes the command copy directories recursively.&lt;/p&gt;
&lt;p&gt;Syntactically, the difference between positional and optional arguments is that optional arguments start with &lt;code&gt;-&lt;/code&gt; or &lt;code&gt;--&lt;/code&gt;, while positional arguments don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;To add an optional argument, you just need to call &lt;code&gt;.add_argument()&lt;/code&gt; again and name the new argument with a starting &lt;code&gt;-&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, try to modify the &lt;code&gt;myls.py&lt;/code&gt; 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;c1&quot;&gt;# myls.py&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Import the argparse library&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;os&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;c1&quot;&gt;# Create the parser&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;List the content of a folder&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Add the arguments&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Path&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;metavar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;path&amp;#39;&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;o&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;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;the path to list&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-l&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;s1&quot;&gt;&amp;#39;--long&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store_true&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;enable the long listing format&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Execute parse_args()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;input_path&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Path&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;os&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_path&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;The path specified does not exist&amp;#39;&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;exit&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;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&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;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;listdir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, try to execute this program to see if the new &lt;code&gt;-l&lt;/code&gt; option is accepted:&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; python myls.py -h
&lt;span class=&quot;go&quot;&gt;usage: myls.py [-h] [-l] path&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;List the content of a folder&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;positional arguments:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;path        the path to list&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;optional arguments:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-h, --help  show this help message and exit&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-l, --long  enable the long listing format&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, now the program also accepts (but doesn&amp;rsquo;t require) the &lt;code&gt;-l&lt;/code&gt; option, which allows the user to get a long listing format for the directory content.&lt;/p&gt;
&lt;h3 id=&quot;setting-the-action-to-be-taken-for-an-argument&quot;&gt;Setting the Action to Be Taken for an Argument&lt;/h3&gt;
&lt;p&gt;When you add an optional argument to your command line interface, you can also define what kind of action to take when the argument is specified. This means that you usually need to specify how to store the value to the &lt;code&gt;Namespace&lt;/code&gt; object you will get when &lt;code&gt;.parse_args()&lt;/code&gt; is executed.&lt;/p&gt;
&lt;p&gt;There are several actions that are already defined and ready to be used. Let&amp;rsquo;s analyze them in detail:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;store&lt;/code&gt;&lt;/strong&gt; stores the input value to the &lt;code&gt;Namespace&lt;/code&gt; object. (This is the default action.)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;store_const&lt;/code&gt;&lt;/strong&gt; stores a constant value when the corresponding optional arguments are specified.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;store_true&lt;/code&gt;&lt;/strong&gt; stores the Boolean value &lt;code&gt;True&lt;/code&gt; when the corresponding optional argument is specified and stores a &lt;code&gt;False&lt;/code&gt; elsewhere.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;store_false&lt;/code&gt;&lt;/strong&gt; stores the Boolean value &lt;code&gt;False&lt;/code&gt; when the corresponding optional argument is specified and stores &lt;code&gt;True&lt;/code&gt; elsewhere.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;append&lt;/code&gt;&lt;/strong&gt; stores a list, appending a value to the list each time the option is provided.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;append_const&lt;/code&gt;&lt;/strong&gt; stores a list appending a constant value to the list each time the option is provided.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;count&lt;/code&gt;&lt;/strong&gt; stores an &lt;code&gt;int&lt;/code&gt; that is equal to the times the option has been provided.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;help&lt;/code&gt;&lt;/strong&gt; shows a help text and exits.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;version&lt;/code&gt;&lt;/strong&gt; shows the version of the program and exits.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s create an example to test all the actions we have seen so far:&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;# actions_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;1.0&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store_const&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-c&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store_true&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-d&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store_false&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-e&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;append&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-f&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;append_const&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;const&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-g&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;count&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-i&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;help&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-j&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;version&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;nb&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;This script accepts an optional argument for each type of action discussed and then prints the value of the arguments read from the command line. Test it by executing this example:&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; python actions_example.py
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: None, &amp;#39;b&amp;#39;: None, &amp;#39;c&amp;#39;: False, &amp;#39;d&amp;#39;: True, &amp;#39;e&amp;#39;: None, &amp;#39;f&amp;#39;: None, &amp;#39;g&amp;#39;: None}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, if we do not specify any arguments, then the default values are generally &lt;code&gt;None&lt;/code&gt;, at least for the actions that do not store a Boolean value.&lt;/p&gt;
&lt;p&gt;The use of the &lt;code&gt;store&lt;/code&gt; action, instead, stores the value we pass without any further consideration:&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; python actions_example.py -a &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: &amp;#39;42&amp;#39;, &amp;#39;b&amp;#39;: None, &amp;#39;c&amp;#39;: False, &amp;#39;d&amp;#39;: True, &amp;#39;e&amp;#39;: None, &amp;#39;f&amp;#39;: None, &amp;#39;g&amp;#39;: None}&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python actions_example.py -a &lt;span class=&quot;s2&quot;&gt;&amp;quot;test&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: &amp;#39;test&amp;#39;, &amp;#39;b&amp;#39;: None, &amp;#39;c&amp;#39;: False, &amp;#39;d&amp;#39;: True, &amp;#39;e&amp;#39;: None, &amp;#39;f&amp;#39;: None, &amp;#39;g&amp;#39;: None}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;store_const&lt;/code&gt; action, stores the defined const when the arguments are provided. In our test, we provided just the &lt;code&gt;b&lt;/code&gt; argument and the value of &lt;code&gt;args.b&lt;/code&gt; is now &lt;code&gt;42&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; python actions_example.py -b
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: None, &amp;#39;b&amp;#39;: 42, &amp;#39;c&amp;#39;: False, &amp;#39;d&amp;#39;: True, &amp;#39;e&amp;#39;: None, &amp;#39;f&amp;#39;: None, &amp;#39;g&amp;#39;: None}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;store_true&lt;/code&gt; action stores a &lt;code&gt;True&lt;/code&gt; Boolean when the argument is passed and store a &lt;code&gt;False&lt;/code&gt; Boolean elsewhere. If you need the opposite behavior, just use the &lt;code&gt;store_false&lt;/code&gt; action:&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; python actions_example.py
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: None, &amp;#39;b&amp;#39;: None, &amp;#39;c&amp;#39;: False, &amp;#39;d&amp;#39;: True, &amp;#39;e&amp;#39;: None, &amp;#39;f&amp;#39;: None, &amp;#39;g&amp;#39;: None}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python actions_example.py -c
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: None, &amp;#39;b&amp;#39;: None, &amp;#39;c&amp;#39;: True, &amp;#39;d&amp;#39;: True, &amp;#39;e&amp;#39;: None, &amp;#39;f&amp;#39;: None, &amp;#39;g&amp;#39;: None}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python actions_example.py -d
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: None, &amp;#39;b&amp;#39;: None, &amp;#39;c&amp;#39;: False, &amp;#39;d&amp;#39;: False, &amp;#39;e&amp;#39;: None, &amp;#39;f&amp;#39;: None, &amp;#39;g&amp;#39;: None}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;append&lt;/code&gt; action lets you create a list of all the values passed to the CLI with the same argument:&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; python actions_example.py -e me -e you -e us
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: None, &amp;#39;b&amp;#39;: None, &amp;#39;c&amp;#39;: False, &amp;#39;d&amp;#39;: True, &amp;#39;e&amp;#39;: [&amp;#39;me&amp;#39;, &amp;#39;you&amp;#39;, &amp;#39;us&amp;#39;], &amp;#39;f&amp;#39;: None, &amp;#39;g&amp;#39;: None}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;append_const&lt;/code&gt; action is similar to the &lt;code&gt;append&lt;/code&gt; one, but it always appends the same constant value:&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; python actions_example.py -f -f
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: None, &amp;#39;b&amp;#39;: None, &amp;#39;c&amp;#39;: False, &amp;#39;d&amp;#39;: True, &amp;#39;e&amp;#39;: None, &amp;#39;f&amp;#39;: [42, 42], &amp;#39;g&amp;#39;: None}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;count&lt;/code&gt; action counts how many time an argument is passed. It&amp;rsquo;s quite useful when you want to implement a verbosity level for your program, since you can define a level where &lt;code&gt;-v&lt;/code&gt; is less verbose than &lt;code&gt;-vvv&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; python actions_example.py -ggg
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: None, &amp;#39;b&amp;#39;: None, &amp;#39;c&amp;#39;: False, &amp;#39;d&amp;#39;: True, &amp;#39;e&amp;#39;: None, &amp;#39;f&amp;#39;: None, &amp;#39;g&amp;#39;: 3}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python actions_example.py -ggggg
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: None, &amp;#39;b&amp;#39;: None, &amp;#39;c&amp;#39;: False, &amp;#39;d&amp;#39;: True, &amp;#39;e&amp;#39;: None, &amp;#39;f&amp;#39;: None, &amp;#39;g&amp;#39;: 5}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;help&lt;/code&gt; action is the one you already saw at the beginning of the article. It&amp;rsquo;s enabled for the &lt;code&gt;-h&lt;/code&gt; flag by default, but you can use it for another flag if you want:&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; python actions_example.py -i
&lt;span class=&quot;go&quot;&gt;usage: actions_example.py [-h] [-a A] [-b] [-c] [-d] [-e E] [-f] [-g] [-i]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[-j]&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;optional arguments:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-h, --help  show this help message and exit&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-a A&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-b&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-c&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-d&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-e E&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-f&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-g&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-i&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-j          show program&amp;#39;s version number and exit&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;version&lt;/code&gt; action is the last one you can use. It just shows the version of the program (defined by assigning a value to the &lt;code&gt;.version&lt;/code&gt; property of the parser) and then ends the execution of the 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; python actions_example.py -j
&lt;span class=&quot;go&quot;&gt;1.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Another possibility you have is to create a custom action. That&amp;rsquo;s done by subclassing the &lt;code&gt;argparse.Action&lt;/code&gt; class and implementing a couple of methods.&lt;/p&gt;
&lt;p&gt;Look at the following example, which is a custom &lt;code&gt;store&lt;/code&gt; action that is just a little bit more verbose than the standard one:&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;# custom_action.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;VerboseStore&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Action&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;option_strings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargs&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;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;n&quot;&gt;nargs&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&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;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;s1&quot;&gt;&amp;#39;nargs not allowed&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VerboseStore&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;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;n&quot;&gt;option_strings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dest&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__call__&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;parser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;option_string&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;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;Here I am, setting the &amp;#39;&lt;/span&gt; \
              &lt;span class=&quot;s1&quot;&gt;&amp;#39;values &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%r&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; for the &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%r&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; option...&amp;#39;&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;values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;option_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;setattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namespace&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;dest&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-i&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;--input&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;VerboseStore&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;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;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;nb&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;This example defines a custom action that is just like the &lt;code&gt;store&lt;/code&gt; action but a little bit more verbose. Try to execute it to test how it works:&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; python custom_action.py -i &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Here I am, setting the values 42 for the &amp;#39;-i&amp;#39; option...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;input&amp;#39;: 42}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the program has printed out a line before setting the value &lt;code&gt;42&lt;/code&gt; for the &lt;code&gt;-i&lt;/code&gt; parameter.&lt;/p&gt;
&lt;h3 id=&quot;setting-the-number-of-values-that-should-be-consumed-by-the-option&quot;&gt;Setting the Number of Values That Should Be Consumed by the Option&lt;/h3&gt;
&lt;p&gt;The parser, by default, assumes that you&amp;rsquo;ll consume a single parameter for each argument, but you can modify this default behavior by specifying a different number of values with the &lt;code&gt;nargs&lt;/code&gt; keyword.&lt;/p&gt;
&lt;p&gt;For example, if you want to create an optional argument that consumes exactly three values, then you can specify the number &lt;code&gt;3&lt;/code&gt; as the value for the &lt;code&gt;nargs&lt;/code&gt; keyword while adding the parameter to the parser:&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;# nargs_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;--input&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&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;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;nargs&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;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, the program accepts three values for the &lt;code&gt;--input&lt;/code&gt; parameter:&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; python nargs_example.py --input &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;usage: nargs_example.py [-h] [--input INPUT INPUT INPUT]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;nargs_example.py: error: argument --input: expected 3 arguments&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python nargs_example.py --input &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[42, 42, 42]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the value of the &lt;code&gt;args.input&lt;/code&gt; variable is now a list that contains three values.&lt;/p&gt;
&lt;p&gt;However, the &lt;code&gt;nargs&lt;/code&gt; keyword can also accept the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;?&lt;/code&gt;:&lt;/strong&gt; a single value, which can be optional&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;*&lt;/code&gt;:&lt;/strong&gt; a flexible number of values, which will be gathered into a list&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;+&lt;/code&gt;:&lt;/strong&gt; like &lt;code&gt;*&lt;/code&gt;, but requiring &lt;em&gt;at least&lt;/em&gt; one value&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;argparse.REMAINDER&lt;/code&gt;:&lt;/strong&gt; all the values that are remaining in the command line&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So, for example, in the following program, the positional argument &lt;code&gt;input&lt;/code&gt; takes a single value when provided, but if the value is not provided, then the one specified by the &lt;code&gt;default&lt;/code&gt; keyword is used:&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;# nargs_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;input&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;nargs&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;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;my default value&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&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 choose to set a specific value for the &lt;code&gt;input&lt;/code&gt; argument or not. In this case, the default value will be used:&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; python nargs_example.py &lt;span class=&quot;s1&quot;&gt;&amp;#39;my custom value&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;my custom value&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python nargs_example.py
&lt;span class=&quot;go&quot;&gt;my default value&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To take a flexible number of values and gather them all into a single list, you need to specify the &lt;code&gt;*&lt;/code&gt; value for the &lt;code&gt;nargs&lt;/code&gt; keyword 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;c1&quot;&gt;# nargs_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;input&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;nargs&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;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;my default value&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;See how this code allows the user to set a flexible number of values for the expected argument:&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; python nargs_example.py me you us
&lt;span class=&quot;go&quot;&gt;[&amp;#39;me&amp;#39;, &amp;#39;you&amp;#39;, &amp;#39;us&amp;#39;]&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python nargs_example.py
&lt;span class=&quot;go&quot;&gt;my default value&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you need to take a variable number of values, but you have to be sure that at least one value is specified, then you can use the &lt;code&gt;+&lt;/code&gt; value for the &lt;code&gt;nargs&lt;/code&gt; keyword 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;c1&quot;&gt;# nargs_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;input&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargs&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;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case, if you execute the program with no positional arguments, then you will receive an explicit error message:&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; python nargs_example.py me you us
&lt;span class=&quot;go&quot;&gt;[&amp;#39;me&amp;#39;, &amp;#39;you&amp;#39;, &amp;#39;us&amp;#39;]&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python nargs_example.py
&lt;span class=&quot;go&quot;&gt;usage: nargs_example.py [-h] input [input ...]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;nargs_example.py: error: the following arguments are required: input&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Lastly, if you need to grab all the remaining arguments that have been specified on the command line and put them all in a list, then the &lt;code&gt;nargs&lt;/code&gt; keyword has to be set to &lt;code&gt;argparse.REMAINDER&lt;/code&gt; 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;c1&quot;&gt;# nargs_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;first&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;others&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nargs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;REMAINDER&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;first = &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%r&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&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;others = &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%r&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;others&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now if you execute this program, you will see that the first value will be associated with the first parameters, while all the other values provided will be associated with the second one:&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; python nargs_example.py me you us
&lt;span class=&quot;go&quot;&gt;first = &amp;#39;me&amp;#39;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;others = [&amp;#39;you&amp;#39;, &amp;#39;us&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note how all the remaining values are put in a single list.&lt;/p&gt;
&lt;h3 id=&quot;setting-a-default-value-produced-if-the-argument-is-missing&quot;&gt;Setting a Default Value Produced if the Argument Is Missing&lt;/h3&gt;
&lt;p&gt;You already know that the user can decide whether or not to specify optional arguments in the command line. When arguments are not specified, the corresponding value is generally set to &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, it is possible to define a default value for an argument when it&amp;rsquo;s not provided:&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;# default_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;42&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;nb&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you execute this example without passing the &lt;code&gt;-a&lt;/code&gt; option, then this is the output you get:&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; python default_example.py
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: &amp;#39;42&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can see that now the option &lt;code&gt;-a&lt;/code&gt; is set to &lt;code&gt;42&lt;/code&gt;, even if you didn&amp;rsquo;t explicitly set the value on the command line.&lt;/p&gt;
&lt;h3 id=&quot;setting-the-type-of-the-argument&quot;&gt;Setting the Type of the Argument&lt;/h3&gt;
&lt;p&gt;By default, all the input argument values are treated as if they were strings. However, it&amp;rsquo;s possible to define the type for the corresponding property of the &lt;code&gt;Namespace&lt;/code&gt; &lt;a href=&quot;https://realpython.com/learning-paths/object-oriented-programming-oop-python/&quot;&gt;object&lt;/a&gt; you get after &lt;code&gt;.parse_args()&lt;/code&gt; is invoked just by defining it with the &lt;code&gt;type&lt;/code&gt; keyword 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;c1&quot;&gt;# type_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&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;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;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;nb&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Specifying the int value for the argument, you are telling &lt;code&gt;argparse&lt;/code&gt; that the &lt;code&gt;.a&lt;/code&gt; property of your &lt;code&gt;Namespace&lt;/code&gt; object has to be an &lt;code&gt;int&lt;/code&gt; (instead of a string):&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; python type_example.py -a &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: 42}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Besides, now the value of the argument is checked at runtime, and if there&amp;rsquo;s a problem with the type of the value provided at the command line, then the execution is interrupted with a clear error message:&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; python type_example.py -a &lt;span class=&quot;s2&quot;&gt;&amp;quot;that&amp;#39;s a string&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;usage: type_example.py [-h] [-a A]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;type_example.py: error: argument -a: invalid int value: &amp;quot;that&amp;#39;s a string&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case, the error message is very clear because it states that you were expected to pass an &lt;code&gt;int&lt;/code&gt; instead of a &lt;a href=&quot;https://realpython.com/python-strings/&quot;&gt;string&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;setting-a-domain-of-allowed-values-for-a-specific-argument&quot;&gt;Setting a Domain of Allowed Values for a Specific Argument&lt;/h3&gt;
&lt;p&gt;Another interesting possibility with the Python &lt;code&gt;argparse&lt;/code&gt; library creating a domain of allowed values for specific arguments. You can do this by providing a list of accepted values while adding the new option:&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;# choices_ex.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;choices&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;head&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;tail&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Please note that if you are accepting numeric values, then you can even use &lt;a href=&quot;https://realpython.com/python-range/&quot;&gt;&lt;code&gt;range()&lt;/code&gt;&lt;/a&gt; to specify a range of accepted 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;c1&quot;&gt;# choices_ex.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&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;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;choices&lt;/span&gt;&lt;span class=&quot;o&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;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;nb&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case, the value provided on the command line will be automatically checked against the range defined:&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; python choices_ex.py -a &lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: 4}&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python choices_ex.py -a &lt;span class=&quot;m&quot;&gt;40&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;usage: choices_ex.py [-h] [-a {1,2,3,4}]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;choices_ex.py: error: argument -a: invalid choice: 40 (choose from 1, 2, 3, 4)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If the input number is outside the defined range, then you&amp;rsquo;ll get an error message.&lt;/p&gt;
&lt;h3 id=&quot;setting-whether-the-argument-is-required&quot;&gt;Setting Whether the Argument Is Required&lt;/h3&gt;
&lt;p&gt;If you want to force your user to specify the value for an optional argument, then you can use the &lt;code&gt;required&lt;/code&gt; keyword:&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;# required_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&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;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;choices&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;head&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;tail&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;required&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;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;nb&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you use the &lt;code&gt;required&lt;/code&gt; keyword set to &lt;code&gt;True&lt;/code&gt; for an optional argument, then the user will be forced to set a value for that argument:&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; python required_example.py
&lt;span class=&quot;go&quot;&gt;usage: required_example.py [-h] -a {head,tail}&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;required_example.py: error: the following arguments are required: -a&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python required_example.py -a head
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;: &amp;#39;head&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;That said, please bear in mind that requiring an optional argument is usually considered bad practice since the user wouldn&amp;rsquo;t expect to have to set a value for an argument that should be optional.&lt;/p&gt;
&lt;h3 id=&quot;showing-a-brief-description-of-what-an-argument-does&quot;&gt;Showing a Brief Description of What an Argument Does&lt;/h3&gt;
&lt;p&gt;A great feature of the Python &lt;code&gt;argparse&lt;/code&gt; library is that, by default, you have the ability to ask for help just by adding the &lt;code&gt;-h&lt;/code&gt; flag to your command line.&lt;/p&gt;
&lt;p&gt;To make it even better, you can add help text to your arguments, so as to give the users even more help when they execute your program with the &lt;code&gt;-h&lt;/code&gt; flag:&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;# help_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&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;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;choices&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;head&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;tail&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;set the user choice to head or tail&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;nb&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;This example shows you how to define a custom help text for the &lt;code&gt;-a&lt;/code&gt; argument, and now the help text will be more clear for the user:&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; python help_example.py -h
&lt;span class=&quot;go&quot;&gt;usage: help_example.py [-h] [-a {head,tail}]&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;optional arguments:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-h, --help      show this help message and exit&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;-a {head, tail}  set the user choice to head or tail&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Defining a help text for all the arguments is a really good idea because it makes the usage of your program more clear to the user.&lt;/p&gt;
&lt;h3 id=&quot;defining-mutually-exclusive-groups&quot;&gt;Defining Mutually Exclusive Groups&lt;/h3&gt;
&lt;p&gt;Another interesting option you have when working with the Python &lt;code&gt;argparse&lt;/code&gt; library is the ability to create a mutually exclusive group for options that cannot coexist in the same command 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;c1&quot;&gt;# groups.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_group&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_mutually_exclusive_group&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;required&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;my_group&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-v&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;--verbose&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store_true&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_group&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-s&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;--silent&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store_true&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;nb&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can specify the &lt;code&gt;-v&lt;/code&gt; or the &lt;code&gt;-s&lt;/code&gt; flags, unless they aren&amp;rsquo;t on the same command line, and also the help text that &lt;code&gt;argparse&lt;/code&gt; provides reflects this constraint:&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; python groups.py -h
&lt;span class=&quot;go&quot;&gt;usage: groups.py [-h] (-v | -s)&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;optional arguments:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  -h, --help     show this help message and exit&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  -v, --verbose&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  -s, --silent&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python groups.py -v -s
&lt;span class=&quot;go&quot;&gt;usage: groups.py [-h] (-v | -s)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;groups.py: error: argument -s/--silent: not allowed with argument -v/--verbose&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you specify all the options of a mutually exclusive group on the same command line you will get an error.&lt;/p&gt;
&lt;h3 id=&quot;setting-the-argument-name-in-usage-messages&quot;&gt;Setting the Argument Name in Usage Messages&lt;/h3&gt;
&lt;p&gt;If an argument accepts an input value, it can be useful to give this value a name that the parser can use to generate the help message, and this can be done by using the &lt;code&gt;metavar&lt;/code&gt; keyword. 
In the following example, you can see how you can use the &lt;code&gt;metavar&lt;/code&gt; keyword to specify a name for the value of the &lt;code&gt;-v&lt;/code&gt; flag:&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;# metavar_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-v&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;s1&quot;&gt;&amp;#39;--verbosity&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&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;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;metavar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;LEVEL&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;nb&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, if you run your program with the &lt;code&gt;-h&lt;/code&gt; flag, the help text assigns the name &lt;code&gt;LEVEL&lt;/code&gt; to the value of the &lt;code&gt;-v&lt;/code&gt; flag:&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; python metavar_example.py -h
&lt;span class=&quot;go&quot;&gt;usage: metavar_example.py [-h] [-v LEVEL]&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;optional arguments:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  -h, --help            show this help message and exit&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  -v LEVEL, --verbosity LEVEL&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Please note that, in the help message, the value accepted for the &lt;code&gt;-v&lt;/code&gt; flag is now named &lt;code&gt;LEVEL&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;setting-the-name-of-the-attribute-to-be-added-to-the-object-once-parsed&quot;&gt;Setting the Name of the Attribute to Be Added to the Object Once Parsed&lt;/h3&gt;
&lt;p&gt;As you have already seen, when you add an argument to the parser, the value of this argument is stored in a property of the &lt;code&gt;Namespace&lt;/code&gt; object. This property is named by default as the first argument passed to &lt;code&gt;.add_argument()&lt;/code&gt; for the positional argument and as the long option string for optional arguments. &lt;/p&gt;
&lt;p&gt;If an option uses dashes (as is fairly common), they will be converted to underscores in the property name:&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;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-v&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;s1&quot;&gt;&amp;#39;--verbosity-level&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&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;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;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verbosity_level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, it&amp;rsquo;s possible to specify the name of this property just by using the keyword &lt;code&gt;dest&lt;/code&gt; when you&amp;rsquo;re adding an argument to the parser:&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;# dest_example.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;argparse&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;argparse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ArgumentParser&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_argument&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;-v&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;s1&quot;&gt;&amp;#39;--verbosity&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                       &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;store&amp;#39;&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;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;dest&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;my_verbosity_level&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_parser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parse_args&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;nb&quot;&gt;vars&lt;/span&gt;&lt;span class=&quot;p&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;By running this program, you&amp;rsquo;ll see that now the &lt;code&gt;args&lt;/code&gt; variable contains a &lt;code&gt;.my_verbosity_level&lt;/code&gt; property, even if by default the name of the property should have been &lt;code&gt;.verbosity&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; python dest_example.py -v &lt;span class=&quot;m&quot;&gt;42&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;my_verbosity_level&amp;#39;: 42}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The default name of this property would have been &lt;code&gt;.verbosity&lt;/code&gt;, but since a different name has been specified by the &lt;code&gt;dest&lt;/code&gt; keyword, &lt;code&gt;.my_verbosity_level&lt;/code&gt; has been used.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Now you know what a command line interface is and how you can create one in Python by using the Python &lt;code&gt;argparse&lt;/code&gt; library. &lt;/p&gt;
&lt;p&gt;In this article, you&amp;rsquo;ve learned:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What the Python &lt;code&gt;argparse&lt;/code&gt; library is, and why it&amp;rsquo;s important to use it if you need to write command line scripts in Python&lt;/li&gt;
&lt;li&gt;How to use the Python &lt;code&gt;argparse&lt;/code&gt; library to quickly create a simple CLI in Python&lt;/li&gt;
&lt;li&gt;What the advanced usage of the Python &lt;code&gt;argparse&lt;/code&gt; library is&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Writing a good command line interface is a good way to create self-explanatory programs and give users a means of interacting with your application.&lt;/p&gt;
&lt;p&gt;If you still have questions, don&amp;rsquo;t hesitate to reach out in the comment section below and take a look at the &lt;a href=&quot;https://docs.python.org/3/library/argparse.html&quot;&gt;official documentation&lt;/a&gt; and the &lt;a href=&quot;https://docs.python.org/3/howto/argparse.html&quot;&gt;Tshepang Lekhonkhobe tutorial&lt;/a&gt; that is part of the official Python 3 HOWTO documentation.&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>OOP Method Types in Python: @classmethod vs @staticmethod vs Instance Methods</title>
      <id>https://realpython.com/courses/python-method-types/</id>
      <link href="https://realpython.com/courses/python-method-types/"/>
      <updated>2019-06-11T14:00:00+00:00</updated>
      <summary>What&#39;s the difference between @classmethod, @staticmethod, and &quot;plain/regular&quot; instance methods in Python? You&#39;ll know the answer after watching this video course.</summary>
      <content type="html">
        &lt;p&gt;What&amp;rsquo;s the difference between &lt;code&gt;@classmethod&lt;/code&gt;, &lt;code&gt;@staticmethod&lt;/code&gt;, and &amp;ldquo;plain/regular&amp;rdquo; instance methods in Python? You&amp;rsquo;ll know the answer after watching this video course:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Regular (instance) methods need a class instance and can access the instance through &lt;code&gt;self&lt;/code&gt;. They can read and modify an objects state freely.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Class methods, marked with the &lt;code&gt;@classmethod&lt;/code&gt; decorator, don&amp;rsquo;t need a class instance. They can&amp;rsquo;t access the instance (self) but they have access to the class itself via &lt;code&gt;cls&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Static methods, marked with the &lt;code&gt;@staticmethod&lt;/code&gt; decorator, don&amp;rsquo;t have access to &lt;code&gt;cls&lt;/code&gt; or &lt;code&gt;self&lt;/code&gt;. They work like regular functions but belong to the class&amp;rsquo;s namespace.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In this course you&amp;rsquo;ll go over the differences between these three kinds of methods in Python. You&amp;rsquo;ll also see when to use each with a simple example, so you can improve your object-oriented programming (OOP) skills in Python.&lt;/p&gt;
&lt;h2 id=&quot;recommended-resources&quot;&gt;Recommended Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/learning-paths/object-oriented-programming-oop-python/&quot;&gt;Learning Path: Object-Oriented Programming (OOP) With Python&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>How to Make a Twitter Bot in Python With Tweepy</title>
      <id>https://realpython.com/twitter-bot-python-tweepy/</id>
      <link href="https://realpython.com/twitter-bot-python-tweepy/"/>
      <updated>2019-06-10T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn how to make a Twitter bot in Python with Tweepy, which is a package that provides a very convenient way to use the Twitter API. You can use your Twitter bot to automate all or part of your Twitter activity.</summary>
      <content type="html">
        &lt;p&gt;In this article, you&amp;rsquo;ll learn how to make your own Twitter Bot in Python with Tweepy, a package that provides a very convenient way to use the Twitter API.&lt;/p&gt;
&lt;p&gt;Twitter is one of the most widely used social networks. For many organizations and people, having a great Twitter presence is a key factor to keeping their audience engaged.&lt;/p&gt;
&lt;p&gt;Part of having a great Twitter presence involves keeping your account active with new tweets and retweets, following interesting accounts, and quickly replying to your followers&amp;rsquo; messages. You can do all this work manually, but that can take a lot of time. Instead, you can rely on a &lt;strong&gt;Twitter Bot&lt;/strong&gt;, a program that automates all or part of your Twitter activity.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this article, you&amp;rsquo;ll learn how to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Improve and automate your interactions with your Twitter audience&lt;/li&gt;
&lt;li&gt;Install Tweepy&lt;/li&gt;
&lt;li&gt;Sign up as a Twitter developer to use its API&lt;/li&gt;
&lt;li&gt;Use Tweepy to invoke the Twitter API&lt;/li&gt;
&lt;li&gt;Build Twitter Bots&lt;/li&gt;
&lt;li&gt;Deploy the bots to a server using Docker and AWS&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-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;hello-tweepy&quot;&gt;Hello Tweepy&lt;/h2&gt;
&lt;p&gt;To start, here&amp;rsquo;s how you can use Tweepy to create a tweet saying &lt;code&gt;Hello Tweepy&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;tweepy&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Authenticate to Twitter&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OAuthHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;CONSUMER_KEY&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CONSUMER_SECRET&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_access_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ACCESS_TOKEN&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;ACCESS_TOKEN_SECRET&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create API object&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create a tweet&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update_status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello Tweepy&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 is a short example, but it shows the four steps common to all Tweepy programs:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Import the &lt;code&gt;tweepy&lt;/code&gt; package&lt;/li&gt;
&lt;li&gt;Set the authentication credentials&lt;/li&gt;
&lt;li&gt;Create a new &lt;code&gt;tweepy.API&lt;/code&gt; object&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;api&lt;/code&gt; object to call the Twitter API&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Objects belonging to the &lt;code&gt;tweepy.API&lt;/code&gt; class offer a vast set of methods that you can use to access almost all Twitter functionality. In the code snippet, we used &lt;code&gt;update_status()&lt;/code&gt; to create a new Tweet.&lt;/p&gt;
&lt;p&gt;We will see later in this article how the authentication works and how you can create the required authentication key, token, and secrets.&lt;/p&gt;
&lt;p&gt;This is just a little example of what you can do with Tweepy. Through this article, you&amp;rsquo;ll learn how to build programs that interact with Twitter in much more interesting and complex ways. &lt;/p&gt;
&lt;h2 id=&quot;twitter-api&quot;&gt;Twitter API&lt;/h2&gt;
&lt;p&gt;The Twitter API gives developers access to most of Twitter&amp;rsquo;s functionality. You can use the API to read and write information related to Twitter entities such as tweets, users, and trends.&lt;/p&gt;
&lt;p&gt;Technically, the API exposes dozens of HTTP endpoints related to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tweets&lt;/li&gt;
&lt;li&gt;Retweets&lt;/li&gt;
&lt;li&gt;Likes&lt;/li&gt;
&lt;li&gt;Direct messages&lt;/li&gt;
&lt;li&gt;Favorites&lt;/li&gt;
&lt;li&gt;Trends&lt;/li&gt;
&lt;li&gt;Media&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Tweepy, as we&amp;rsquo;ll see later, provides a way to invoke those HTTP endpoints without dealing with low-level details.&lt;/p&gt;
&lt;p&gt;The Twitter API uses &lt;a href=&quot;https://oauth.net&quot;&gt;OAuth&lt;/a&gt;, a widely used open authorization protocol, to authenticate all the requests. Before making any call to the Twitter API, you need to create and configure your authentication credentials. Later in this article, you&amp;rsquo;ll find detailed instructions for this.&lt;/p&gt;
&lt;p&gt;You can leverage the Twitter API to build different kinds of automations, such as bots, analytics, and other tools. Keep in mind that Twitter imposes certain restrictions and policies about what you can and cannot build using its API. This is done to guarantee users a good experience. The development of tools to spam, mislead users, and so on is forbidden. &lt;/p&gt;
&lt;p&gt;The Twitter API also imposes &lt;strong&gt;rate limits&lt;/strong&gt; about how frequently you&amp;rsquo;re allowed to invoke API methods. If you exceed these limits, you&amp;rsquo;ll have to wait between 5 and 15 minutes to be able to use the API again. You must consider this while designing and implementing bots to avoid unnecessary waits.&lt;/p&gt;
&lt;p&gt;You can find more information about the Twitter API&amp;rsquo;s policies and limits in its official documentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://help.twitter.com/en/rules-and-policies/twitter-automation&quot;&gt;Twitter Automation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.twitter.com/en/docs/basics/rate-limits&quot;&gt;Rate limits&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;what-is-tweepy&quot;&gt;What Is Tweepy?&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/tweepy/tweepy&quot;&gt;Tweepy&lt;/a&gt;&lt;/strong&gt; is an open source Python package that gives you a very convenient way to access the Twitter API with Python. Tweepy includes a set of classes and methods that represent Twitter&amp;rsquo;s models and API endpoints, and it transparently handles various implementation details, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Data encoding and decoding&lt;/li&gt;
&lt;li&gt;HTTP requests&lt;/li&gt;
&lt;li&gt;Results pagination&lt;/li&gt;
&lt;li&gt;OAuth authentication&lt;/li&gt;
&lt;li&gt;Rate limits&lt;/li&gt;
&lt;li&gt;Streams&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you weren&amp;rsquo;t using Tweepy, then you would have to deal with low-level details having to do with HTTP requests, data serialization, authentication, and rate limits. This could be time consuming and prone to error. Instead, thanks to Tweepy, you can focus on the functionality you want to build.&lt;/p&gt;
&lt;p&gt;Almost all the functionality provided by Twitter API can be used through Tweepy. The only current limitation, as of version 3.7.0, is that Direct Messages don&amp;rsquo;t work properly due to some recent changes in the Twitter API.&lt;/p&gt;
&lt;h2 id=&quot;using-tweepy&quot;&gt;Using Tweepy&lt;/h2&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll learn how to install Tweepy for development, configure authentication credentials, and interact with the Twitter API.&lt;/p&gt;
&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;
&lt;p&gt;Tweepy can be installed using &lt;strong&gt;pip&lt;/strong&gt;, a Python package manager. In this article, we&amp;rsquo;re going to use a virtual environment (&lt;strong&gt;virtualenv&lt;/strong&gt;) for the projects to avoid depending on system-wide packages. For more information on virtual environments and pip, check out &lt;a href=&quot;https://realpython.com/python-virtual-environments-a-primer/&quot;&gt;Python Virtual Environments: A Primer&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/what-is-pip/&quot;&gt;What Is Pip? A Guide for New Pythonistas&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can get started by creating a project called &lt;code&gt;tweepy-bots&lt;/code&gt;. The first step is to create a directory and a virtual environment:&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; mkdir tweepy-bots
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; tweepy-bots
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python3 -m venv venv
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The commands above create the virtual environment inside the project directory.&lt;/p&gt;
&lt;p&gt;Then you can install the Tweepy package. First, you need to &lt;strong&gt;activate&lt;/strong&gt; the newly created virtual environment and then use &lt;strong&gt;pip&lt;/strong&gt; to do the installation:&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; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ./venv/bin/activate
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; pip install tweepy
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that Tweepy is installed, let&amp;rsquo;s create a &lt;code&gt;requirements.txt&lt;/code&gt; file containing the names of your dependencies. You can use the pip command &lt;strong&gt;freeze&lt;/strong&gt; for this task:&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 freeze &amp;gt; requirements.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll use this &lt;code&gt;requirements.txt&lt;/code&gt; file when you&amp;rsquo;re deploying the project.&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 method used to activate the virtual environment may be different, depending on your operating system and shell. You can learn more about this in the &lt;a href=&quot;https://docs.python.org/3/library/venv.html&quot;&gt;venv documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;creating-twitter-api-authentication-credentials&quot;&gt;Creating Twitter API Authentication Credentials&lt;/h3&gt;
&lt;p&gt;As we have previously seen, the Twitter API requires that all requests use OAuth to authenticate. So you need to create the required authentication credentials to be able to use the API. These credentials are four text strings:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Consumer key&lt;/li&gt;
&lt;li&gt;Consumer secret&lt;/li&gt;
&lt;li&gt;Access token&lt;/li&gt;
&lt;li&gt;Access secret&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you already have a Twitter user account, then follow these steps to create the key, token, and secrets. Otherwise, you have to sign up as a Twitter user before proceeding.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Apply for a Twitter Developer Account&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Go to the &lt;a href=&quot;https://developer.twitter.com&quot;&gt;Twitter developer site&lt;/a&gt; to apply for a developer account. Here, you have to select the Twitter user responsible for this account. It should probably be you or your organization. Here&amp;rsquo;s what this page looks like:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/dev_account_01.2a5eab8edcb8.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/dev_account_01.2a5eab8edcb8.png&quot; width=&quot;1260&quot; height=&quot;853&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/dev_account_01.2a5eab8edcb8.png&amp;amp;w=315&amp;amp;sig=332104c5c315255a4e86177258f09b79537b42a5 315w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/dev_account_01.2a5eab8edcb8.png&amp;amp;w=630&amp;amp;sig=cc072960084a6e5089704edb0430bfa91e1ed788 630w, https://files.realpython.com/media/dev_account_01.2a5eab8edcb8.png 1260w&quot; sizes=&quot;75vw&quot; alt=&quot;Apply for a developer account&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this case, I chose to use my own account, &lt;em&gt;@MikezGarcia&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Twitter then requests some information about how you plan to use the developer account, as showed below:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/dev_account_02.f6f23b384b33.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/dev_account_02.f6f23b384b33.png&quot; width=&quot;1254&quot; height=&quot;796&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/dev_account_02.f6f23b384b33.png&amp;amp;w=313&amp;amp;sig=7910d2425dc6447203f9d56e2a747f877f131827 313w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/dev_account_02.f6f23b384b33.png&amp;amp;w=627&amp;amp;sig=2bf51207cb8da57523b7941729d0de814d6f1611 627w, https://files.realpython.com/media/dev_account_02.f6f23b384b33.png 1254w&quot; sizes=&quot;75vw&quot; alt=&quot;Complete account information&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You have to specify the developer account name and whether you are planning to use it for personal purpose or for your organization.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2: Create an Application&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Twitter grants authentication credentials to apps, not accounts. An app can be any tool or bot that uses the Twitter API. So you need to register your an app to be able to make API calls.&lt;/p&gt;
&lt;p&gt;To register your app, go to &lt;a href=&quot;https://developer.twitter.com/en/apps&quot;&gt;your Twitter apps page&lt;/a&gt; and select the &lt;em&gt;Create an app&lt;/em&gt; option.&lt;/p&gt;
&lt;p&gt;You need to provide the following information about your app and its purpose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;App name:&lt;/strong&gt; a name to identify your application (such as &lt;em&gt;examplebot&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Application description:&lt;/strong&gt; the purpose of your application (such as &lt;em&gt;An example bot for a Real Python article&lt;/em&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your or your application&amp;rsquo;s website URL:&lt;/strong&gt; required, but can be your personal site&amp;rsquo;s URL since bots don&amp;rsquo;t need a URL to work&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use of the app:&lt;/strong&gt; how users will use your app (such as &lt;em&gt;This app is a bot that will automatically respond to users&lt;/em&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Create the Authentication Credentials&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To create the authentication credentials, go to &lt;a href=&quot;https://developer.twitter.com/en/apps&quot;&gt;your Twitter apps page&lt;/a&gt;. Here&amp;rsquo;s what the &lt;em&gt;Apps page&lt;/em&gt; looks like:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/dev_account_06.fcb9c3b19939.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/dev_account_06.fcb9c3b19939.png&quot; width=&quot;1263&quot; height=&quot;179&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/dev_account_06.fcb9c3b19939.png&amp;amp;w=315&amp;amp;sig=26b35934a634c55c76315fe4e7df4f6990839baa 315w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/dev_account_06.fcb9c3b19939.png&amp;amp;w=631&amp;amp;sig=bc07e78e1376535e228780ba3212a5061edf1cfe 631w, https://files.realpython.com/media/dev_account_06.fcb9c3b19939.png 1263w&quot; sizes=&quot;75vw&quot; alt=&quot;Edit app details&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here you&amp;rsquo;ll find the &lt;em&gt;Details&lt;/em&gt; button of your app. Clicking this button takes you to the next page, where you can generate the credentials.&lt;/p&gt;
&lt;p&gt;By selecting the &lt;em&gt;Keys and tokens&lt;/em&gt; tab, you can generate and copy the key, token, and secrets to use them in your code:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/dev_account_07.f37afa5ab26a.efd2422a33c8.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-75&quot; src=&quot;https://files.realpython.com/media/dev_account_07.f37afa5ab26a.efd2422a33c8.png&quot; width=&quot;537&quot; height=&quot;507&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/dev_account_07.f37afa5ab26a.efd2422a33c8.png&amp;amp;w=134&amp;amp;sig=e75ed1f9b1a12e1a3216d112698900f0224b24d3 134w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/dev_account_07.f37afa5ab26a.efd2422a33c8.png&amp;amp;w=268&amp;amp;sig=44647bf1a58f86e46c16963f27b985d9081e5488 268w, https://files.realpython.com/media/dev_account_07.f37afa5ab26a.efd2422a33c8.png 537w&quot; sizes=&quot;75vw&quot; alt=&quot;Generate keys and tokens&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After generating the credentials, save them to later use them in your code.&lt;/p&gt;
&lt;p&gt;You can test the credentials using the following snippet:&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;tweepy&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Authenticate to Twitter&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OAuthHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pGBDoAaEpkliVKBOLwjtcmHGc&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;xF3g1wrP50b6BlZEd20u4oVfjgH1FGQcuWUzlQO5aUWOufvlhw&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_access_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;622518493-6VcLIPprbQbv9wkcBBPvCle8vsjU9fE85Dq9oStl&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
    &lt;span class=&quot;s2&quot;&gt;&amp;quot;tH9aKQbQQ1iRdYTcLSsPwitl44BkAc6jilrsU0ifnXvZhq&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auth&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;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verify_credentials&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;Authentication OK&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;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;Error during authentication&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 snippet, credentials are tested using &lt;code&gt;verify_credentials()&lt;/code&gt;. If all goes well, you should see a message saying &lt;em&gt;Authentication OK&lt;/em&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; All of the credentials used in this article are only examples and will not work. You have to generate and use your own credentials.&lt;/p&gt;
&lt;/div&gt;
&lt;h3 id=&quot;review-of-tweepy-functionality&quot;&gt;Review of Tweepy Functionality&lt;/h3&gt;
&lt;p&gt;Tweepy gives you an interface to access the Twitter API from Python. It does so by encapsulating much of the Twitter API&amp;rsquo;s complexity and adding a model layer and other useful functionalities on top of it.&lt;/p&gt;
&lt;p&gt;Since, over time, the names of various Twitter concepts have evolved, some old names are still used in Tweepy. So keep in mind that, in the context of this article, these equivalences hold:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;status&lt;/strong&gt; is a &lt;strong&gt;tweet&lt;/strong&gt; .&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;friendship&lt;/strong&gt; is a &lt;strong&gt;follow-follower relationship&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;favorite&lt;/strong&gt; is a &lt;strong&gt;like&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that you know how Tweepy names things, let&amp;rsquo;s see how it works. &lt;/p&gt;
&lt;p&gt;Tweepy&amp;rsquo;s functionality can be divided into the following groups:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OAuth&lt;/li&gt;
&lt;li&gt;The API class&lt;/li&gt;
&lt;li&gt;Models&lt;/li&gt;
&lt;li&gt;Cursors&lt;/li&gt;
&lt;li&gt;Streams&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you&amp;rsquo;re going to look into these groups to learn about the functionality each one provides.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;OAuth&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Tweepy takes care of all the details for using OAuth required by the Twitter API to authenticate each request. It provides an &lt;code&gt;OAuthHandler&lt;/code&gt; class that you can use to set the credentials to be used in all API calls. &lt;/p&gt;
&lt;p&gt;This code snippet shows how you can create an &lt;code&gt;OAuthHandler&lt;/code&gt; object that can later be used for API calls:&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;tweepy&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Authenticate to Twitter&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OAuthHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;CONSUMER_KEY&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CONSUMER_SECRET&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_access_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ACCESS_TOKEN&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;ACCESS_TOKEN_SECRET&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 you&amp;rsquo;re telling Tweepy to use the credentials that you created in &lt;strong&gt;Step 3: Create the Authentication Credentials&lt;/strong&gt;. You must replace &lt;code&gt;CONSUMER_KEY&lt;/code&gt;, &lt;code&gt;CONSUMER_SECRET&lt;/code&gt;, &lt;code&gt;ACCESS_TOKEN&lt;/code&gt;, and &lt;code&gt;ACCESS_TOKEN_SECRET&lt;/code&gt; with the values you previously generated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The API Class&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;API&lt;/code&gt; class has many methods that provide access to Twitter API endpoints. Using these methods, you can access the Twitter API&amp;rsquo;s functionality.&lt;/p&gt;
&lt;p&gt;The following code snippet creates an &lt;code&gt;API&lt;/code&gt; object that you can use to invoke Twitter API methods.  Setting &lt;code&gt;wait_on_rate_limit&lt;/code&gt; and &lt;code&gt;wait_on_rate_limit_notify&lt;/code&gt; to &lt;code&gt;True&lt;/code&gt; makes the API object print a message and wait if the rate limit is exceeded:&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;tweepy&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Authenticate to Twitter&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OAuthHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;CONSUMER_KEY&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CONSUMER_SECRET&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_access_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ACCESS_TOKEN&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;ACCESS_TOKEN_SECRET&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create API object&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wait_on_rate_limit&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;wait_on_rate_limit_notify&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;In the code above, we&amp;rsquo;ve set the authentication credentials and created an &lt;code&gt;api&lt;/code&gt; object. You can invoke this object&amp;rsquo;s methods to do any API call.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;API&lt;/code&gt; methods can be grouped into the following categories:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Methods for user timelines&lt;/li&gt;
&lt;li&gt;Methods for tweets&lt;/li&gt;
&lt;li&gt;Methods for users&lt;/li&gt;
&lt;li&gt;Methods for followers&lt;/li&gt;
&lt;li&gt;Methods for your account&lt;/li&gt;
&lt;li&gt;Methods for likes&lt;/li&gt;
&lt;li&gt;Methods for blocking users&lt;/li&gt;
&lt;li&gt;Methods for searches&lt;/li&gt;
&lt;li&gt;Methods for trends&lt;/li&gt;
&lt;li&gt;Methods for streaming&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In the following subsections, you&amp;rsquo;re going to review different groups of API methods. You can visit the &lt;a href=&quot;https://tweepy.readthedocs.io/en/latest/api.html&quot;&gt;API Class Documentation&lt;/a&gt; for a detailed list of all API methods.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods for User Timelines&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;These methods deal with reading tweets, mentions, and retweets from your timeline or any other user&amp;rsquo;s timeline, as long as it&amp;rsquo;s public.&lt;/p&gt;
&lt;p&gt;This code snippet prints the author and text of the last tweets in your home timeline:&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;timeline&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;home_timeline&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;tweet&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;timeline&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;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.user.name}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; said &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.text}&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;&lt;code&gt;home_timeline()&lt;/code&gt;, a Tweepy API method, is used to get the last 20 entries in your timeline. 20 is the default value in Tweepy. You&amp;rsquo;ll see later how to get more than 20 results and work with paginated results.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods for Tweets&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;These methods have to do with creating, fetching, and retweeting tweets.&lt;/p&gt;
&lt;p&gt;The following code uses Tweepy to create a tweet with some text:&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;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update_status&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Test tweet from Tweepy Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We&amp;rsquo;ve used &lt;code&gt;update_status()&lt;/code&gt; to create a new tweet from a Python string.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods for Users&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Methods in this group enable you to search users with a filter criteria, fetch user details, and list the followers of any user, as long as that user account is public.&lt;/p&gt;
&lt;p&gt;The snippet below fetches my user, &lt;em&gt;@MikezGarcia&lt;/em&gt;, and then prints its details as well as its 20 most recent followers:&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;user&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_user&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;MikezGarcia&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;User details:&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;user&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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&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;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;location&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;Last 20 Followers:&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;follower&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;followers&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;follower&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;get_user()&lt;/code&gt; returns an object containing the user details. This returned object also has methods to access information related to the user. You used the &lt;code&gt;followers&lt;/code&gt; attribute to get the list of followers.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods for Followers&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This group of methods deals with following and unfollowing users, querying a user&amp;rsquo;s followers, and listing the accounts any user is following.&lt;/p&gt;
&lt;p&gt;This code shows how you can use Tweepy to start following &lt;em&gt;@realpython&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;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_friendship&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;realpython&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;create_friendship()&lt;/code&gt; adds &lt;em&gt;@realpython&lt;/em&gt; to the list of accounts that you follow.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods for Your Account&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;These methods allow you to read and write your own profile details.&lt;/p&gt;
&lt;p&gt;For example, you can use this code snippet to update your profile description:&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;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update_profile&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;I like Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The keyword argument &lt;code&gt;description&lt;/code&gt; is passed to &lt;code&gt;update_profile()&lt;/code&gt; to change your profile description to &lt;code&gt;&quot;I like Python&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods for Likes&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Using these API methods, you can mark any tweet as &lt;em&gt;Liked&lt;/em&gt; or remove the &lt;em&gt;Like&lt;/em&gt; mark if it was already added.&lt;/p&gt;
&lt;p&gt;You can mark the most recent tweet in your home timeline as &lt;em&gt;Liked&lt;/em&gt; as follows:&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;tweets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;home_timeline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&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;tweet&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweets&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;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;Liking tweet &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.id}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; of &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.author.name}&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;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_favorite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code uses &lt;code&gt;home_timeline()&lt;/code&gt; to get the most recent tweet. Then, the &lt;code&gt;tweet.id&lt;/code&gt; is passed to &lt;code&gt;create_favorite()&lt;/code&gt; to mark the tweet as &lt;em&gt;Liked&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods for Blocking Users&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This group of methods deals with blocking and unblocking users, as well as listing blocked users.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how you can see the users that you have blocked:&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;block&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blocks&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;block&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code iterates through the list of accounts that you have blocked. You can get this list using &lt;code&gt;blocks()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods for Searches&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Using these methods, you can search tweets using text, language, and other filters.&lt;/p&gt;
&lt;p&gt;For example, you can try this code to get the 10 most recent public tweets that are in English and contain the word &lt;code&gt;&quot;Python&quot;&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;q&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rpp&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;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;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.user.name}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.text}&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;You used &lt;code&gt;search()&lt;/code&gt; to filter tweets that match the desired criteria. This will search in any public tweet, not just in tweets from people you are following.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods for Trends&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This group of methods allows you to list the current trends for any geographical location.&lt;/p&gt;
&lt;p&gt;For example, here&amp;rsquo;s how to list the world-wide trending topics:&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;trends_result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trends_place&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trend&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;trends_result&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;trends&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;trend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;name&amp;quot;&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;trends_place()&lt;/code&gt;, you get the list of trends for any place, passing as the only argument the place id. Here, &lt;code&gt;1&lt;/code&gt; means world-wide. You can see the full list of available locations using &lt;code&gt;api.trends_available()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Methods for Streaming&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Streaming&lt;/strong&gt; allows you to actively watch for tweets that match certain criteria in &lt;strong&gt;real time&lt;/strong&gt;. This means that when there aren&amp;rsquo;t any new tweet matching the criteria, then the program will wait until a new tweet is created and then process it.&lt;/p&gt;
&lt;p&gt;To use streaming you have to create two objects:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;strong&gt;stream object&lt;/strong&gt;  uses the Twitter API to get tweets that match some criteria. This object is the source of tweets that are then processed by a &lt;strong&gt;stream listener&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;stream listener&lt;/strong&gt; receives tweets from the stream.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;rsquo;s how you do that:&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;json&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tweepy&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyStreamListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamListener&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;api&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;api&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&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;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&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;on_status&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;tweet&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;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.user.name}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.text}&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_error&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;status&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;Error detected&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;tweets_listener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyStreamListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&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;tweepy&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweets_listener&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;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;track&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;Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Django&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Tweepy&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;languages&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;en&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You declared a new class, &lt;code&gt;MyStreamListener&lt;/code&gt;. This class is used for the stream listener &lt;code&gt;tweets_listener&lt;/code&gt;. By extending Tweepy&amp;rsquo;s &lt;code&gt;StreamLister&lt;/code&gt;, we reused code that is common to all stream listeners. Tweets from the stream are processed by &lt;code&gt;on_status()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We created the stream using &lt;code&gt;tweepy.Stream&lt;/code&gt;, passing the authentication credentials and our stream listener. To start getting tweets from the stream, you have to call the stream&amp;rsquo;s &lt;code&gt;filter()&lt;/code&gt;, passing the criteria to use to filter tweets. Then, for each new tweet that matches the criteria, the stream object invokes the stream listener&amp;rsquo;s &lt;code&gt;on_status()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Models&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Tweepy uses its own model classes to encapsulate the responses from various Twitter API methods. This gives you a convenient way to use the results from API operations.&lt;/p&gt;
&lt;p&gt;The model classes are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;User&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Status&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Friendship&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SearchResults&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Suppose you want to fetch every tweet in which you are mentioned, and then mark each tweet as &lt;em&gt;Liked&lt;/em&gt; and follow its author. You can do that 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;n&quot;&gt;tweets&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mentions_timeline&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;tweet&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweets&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;favorite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;follow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since each &lt;code&gt;tweet&lt;/code&gt; object returned by &lt;code&gt;mentions_timeline()&lt;/code&gt; belongs to the &lt;code&gt;Status&lt;/code&gt; class, you can use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;favorite()&lt;/code&gt;&lt;/strong&gt; to mark it as &lt;em&gt;Liked&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;user&lt;/code&gt;&lt;/strong&gt; to get its author &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This user attribute, &lt;code&gt;tweet.user&lt;/code&gt;, is also an object that belongs to &lt;code&gt;User&lt;/code&gt;, so you can use &lt;code&gt;follow()&lt;/code&gt; to add the tweet&amp;rsquo;s author to the list of people you follow.&lt;/p&gt;
&lt;p&gt;Leveraging Tweepy models enables you to create concise and understandable code. &lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cursors&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A lot of Twitter API endpoints use pagination to return their results. By default, each method returns the first page, which usually contains a few dozen items.&lt;/p&gt;
&lt;p&gt;Tweepy cursors take away part of the complexity of working with paginated results. Cursors are implemented as a Tweepy class named &lt;code&gt;Cursor&lt;/code&gt;. To use a cursor, you select the API method to use to fetch items and the number of items you want. The &lt;code&gt;Cursor&lt;/code&gt; object takes care of fetching the various result pages transparently.&lt;/p&gt;
&lt;p&gt;This code shows how, by using a cursor, you can get not only the first page from your timeline, but also the last 100 tweets:&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;tweet&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;home_timeline&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;mi&quot;&gt;100&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;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.user.name}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; said: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.text}&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;A cursor object is created using &lt;code&gt;tweepy.Cursor&lt;/code&gt;. The class constructor receives an API method to use as the source for results. In the example, we used &lt;code&gt;home_timeline()&lt;/code&gt; as the source since we wanted tweets from the timeline. The &lt;code&gt;Cursor&lt;/code&gt; object has an &lt;code&gt;items()&lt;/code&gt; method that returns an iterable you can use to iterate over the results. You can pass &lt;code&gt;items()&lt;/code&gt; the number of result items that you want to get.&lt;/p&gt;
&lt;h2 id=&quot;how-to-make-a-twitter-bot-in-python-with-tweepy&quot;&gt;How to Make a Twitter Bot in Python With Tweepy&lt;/h2&gt;
&lt;p&gt;Now that you know how Tweepy works, let&amp;rsquo;s see how you can make a Twitter bot in Python with Tweepy. Bots work by &lt;strong&gt;continuously watching&lt;/strong&gt; for some Twitter activity and &lt;strong&gt;automatically reacting&lt;/strong&gt; to it.&lt;/p&gt;
&lt;h3 id=&quot;watching-for-twitter-activity&quot;&gt;Watching for Twitter Activity&lt;/h3&gt;
&lt;p&gt;There are two ways to continuously watch for Twitter activity:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Using streams:&lt;/strong&gt; to be notified when new content, such as tweets, that matches certain criteria is created&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Using polling:&lt;/strong&gt; to periodically make Tweepy API calls and then check their results to see if they contain something new&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Which option to choose depends on your use case. Using streams is the most efficient option, but then you can only watch activity related to tweets, so it&amp;rsquo;s less flexible. In this section, both options are used to build different bots.&lt;/p&gt;
&lt;h3 id=&quot;presenting-the-example-bots&quot;&gt;Presenting the Example Bots&lt;/h3&gt;
&lt;p&gt;In this article, you&amp;rsquo;ll learn how to build three different bots that perform automatic actions to react to some Twitter events:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The Follow Followers Bot&lt;/strong&gt; automatically follows anyone who follows you.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Fav &amp;amp; Retweet Bot&lt;/strong&gt; automatically likes and retweets tweets that match certain criteria.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Reply to Mentions Bot&lt;/strong&gt; automatically replies to tweets mentioning you that contain the words &lt;code&gt;help&lt;/code&gt; or &lt;code&gt;support&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We are going to use a directory named &lt;code&gt;bots&lt;/code&gt; to store all the Python files of the project as shown below:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;tweepy-bots/
│
├── bots/
│   ├── config.py
│   └── followfollowers.py
│   └── favretweet.py
│   └── autoreply.py
│
└── requirements.txt
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The next section explains the &lt;code&gt;config&lt;/code&gt; module.&lt;/p&gt;
&lt;h3 id=&quot;the-config-module&quot;&gt;The Config Module&lt;/h3&gt;
&lt;p&gt;All the bots we are building have some functionality in common. For example, they need to authenticate to the Twitter API.&lt;/p&gt;
&lt;p&gt;You can create a reusable Python module containing the logic common to all bots. We named this module &lt;code&gt;config&lt;/code&gt;. &lt;/p&gt;
&lt;p&gt;This module reads the authentication credentials from environment variables and creates the Tweepy API object. By reading the credentials from environment variables, you avoid hard coding them into the source code, making it much more secure.&lt;/p&gt;
&lt;p&gt;The bots will read the credentials from these environment variables:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CONSUMER_KEY&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CONSUMER_SECRET&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ACCESS_TOKEN&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ACCESS_TOKEN_SECRET&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Later, you&amp;rsquo;ll see how to set these variables to match the credentials you have previously generated for your Twitter app.&lt;/p&gt;
&lt;p&gt;Below is the complete source code for the &lt;code&gt;config&lt;/code&gt; module. It contains &lt;code&gt;create_api()&lt;/code&gt;, a function that reads authentication credentials from environment variables and creates the Tweepy API object:&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;# tweepy-bots/bots/config.py&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tweepy&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;os&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;create_api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;consumer_key&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;CONSUMER_KEY&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;consumer_secret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;CONSUMER_SECRET&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;access_token&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ACCESS_TOKEN&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;access_token_secret&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getenv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;ACCESS_TOKEN_SECRET&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;OAuthHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;consumer_key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;consumer_secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_access_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;access_token&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;access_token_secret&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wait_on_rate_limit&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;wait_on_rate_limit_notify&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;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;verify_credentials&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;n&quot;&gt;logger&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;Error creating API&amp;quot;&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;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&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;API created&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;api&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code uses &lt;code&gt;os.getenv()&lt;/code&gt; to read environment variables and then creates the Tweepy &lt;code&gt;auth&lt;/code&gt; object. Then the API object is created.&lt;/p&gt;
&lt;p&gt;Passing &lt;code&gt;wait_on_rate_limit&lt;/code&gt; and &lt;code&gt;wait_on_rate_limit_notify&lt;/code&gt; in the creation of the &lt;code&gt;tweepy.API&lt;/code&gt; object makes Tweepy wait and print a message when the rate limit is exceeded.&lt;/p&gt;
&lt;p&gt;Before returning the API object, &lt;code&gt;create_api()&lt;/code&gt; calls &lt;code&gt;verify_credentials()&lt;/code&gt; to check that the credentials are valid.&lt;/p&gt;
&lt;p&gt;This module and, as you will see later, the bot&amp;rsquo;s source code, use the &lt;code&gt;logging&lt;/code&gt; Python module to inform errors and info messages that help you debug them if any issue arise. You can read more about it in &lt;a href=&quot;https://realpython.com/python-logging/&quot;&gt;Logging in Python&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-follow-followers-bot&quot;&gt;The Follow Followers Bot&lt;/h3&gt;
&lt;p&gt;This bot gets your list of followers from Twitter every minute and then iterates through it to follow each user that you&amp;rsquo;re not already following.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bot Source Code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the full source code of this bot. It uses the previously created &lt;code&gt;config&lt;/code&gt; module, the Tweepy API, and cursors:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# tweepy-bots/bots/followfollowers.py&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tweepy&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;config&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_api&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&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 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;INFO&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;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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;follow_followers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&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;Retrieving and following followers&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;follower&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;followers&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;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;follower&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;following&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;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Following &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{follower.name}&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;follower&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;follow&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;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&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;n&quot;&gt;follow_followers&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&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;Waiting...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&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;60&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;&lt;code&gt;main()&lt;/code&gt; creates a Tweepy API object using &lt;code&gt;create_api()&lt;/code&gt; from the &lt;code&gt;config&lt;/code&gt; module you previously created. Then, inside a loop, &lt;code&gt;follow_followers()&lt;/code&gt; is called once every minute.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;follow_followers()&lt;/code&gt; uses a Tweepy cursor and the Tweepy API method &lt;code&gt;followers()&lt;/code&gt; to get your list of followers. This list contains a Tweepy user model for each user that is following you.&lt;/p&gt;
&lt;p&gt;Then the bot iterates through the list and uses &lt;code&gt;following&lt;/code&gt; to check if you are already following each user. Users that are not already being followed are followed using &lt;code&gt;follow()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Running the Bot&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To run the bot, you must first create the environment variables for the authentication credentials. You can do this by running this commands from a terminal and replacing the values with your actual credentials:&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; &lt;span class=&quot;nb&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CONSUMER_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pGBDoAaEpkliVKBOLwjtcmHGc&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;CONSUMER_SECRET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;xF3g1wrP50b6BlZEd20u4oVfjgH1FGQcuWUzlQO5aUWOufvlhw&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;622518493-6VcLIPprbQbv9wkcBBPvCle8vsjU9fE85Dq9oStl&amp;quot;&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ACCESS_TOKEN_SECRET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;tH9aKQbQQ1iRdYTcLSsPwitl44BkAc6jilrsU0ifnXvZhq&amp;quot;&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; This assumes that you&amp;rsquo;re using &lt;strong&gt;Linux&lt;/strong&gt; or &lt;strong&gt;macOS&lt;/strong&gt;. If you&amp;rsquo;re using Windows, then the steps might be a little different.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;After you run the commands, your environment variables will contain the credentials needed to use the Twitter API.&lt;/p&gt;
&lt;p&gt;Next, you have to activate your virtual environment and run the bot&amp;rsquo;s main file, &lt;code&gt;bots/followfollowers.py&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; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; ./venv/bin/activate
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; python bots/followfollowers.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While it&amp;rsquo;s running, the bot will follow anybody who follows you. You can test that it works by unfollowing someone that is following you. After a minute, they will be followed again. You can stop the bot using &lt;code&gt;Ctrl-C&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-fav-retweet-bot&quot;&gt;The Fav &amp;amp; Retweet Bot&lt;/h3&gt;
&lt;p&gt;This bot uses the previously introduced Tweepy stream to actively watch for tweets that contain certain keywords. For each tweet, if you&amp;rsquo;re not the tweet author, it will mark the tweet as &lt;em&gt;Liked&lt;/em&gt; and then retweet it.&lt;/p&gt;
&lt;p&gt;You can use this bot to feed your account with content that is relevant to your interests.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bot Source Code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Below, you can see the full source code of this bot. It uses a stream to filter tweets that contain the words &lt;code&gt;&quot;Python&quot;&lt;/code&gt; or &lt;code&gt;&quot;Tweepy&quot;&lt;/code&gt;. Each tweet from the stream is marked as &lt;em&gt;Liked&lt;/em&gt; and retweeted:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# tweepy-bots/bots/favretweet.py&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tweepy&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;config&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_api&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;json&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 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;INFO&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;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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;FavRetweetListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StreamListener&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;api&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;me&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;me&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;on_status&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;tweet&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;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Processing tweet id &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.id}&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in_reply_to_status_id&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;None&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; \
            &lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&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;me&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&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;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;favorite&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;retweet&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;n&quot;&gt;logger&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;Error on fav and retweet&amp;quot;&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_error&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;status&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;error&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;p&quot;&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;n&quot;&gt;keywords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;tweets_listener&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FavRetweetListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&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;tweepy&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;auth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweets_listener&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;filter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;track&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keywords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;languages&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;en&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;span class=&quot;s2&quot;&gt;&amp;quot;Python&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Tweepy&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 with the previous bot, the main function uses &lt;code&gt;create_api()&lt;/code&gt; from the &lt;code&gt;config&lt;/code&gt; module to create a Tweepy API object.&lt;/p&gt;
&lt;p&gt;A Tweepy stream is created to filter tweets that are in the English language and include some of the keywords specified in the main function argument, &lt;code&gt;&quot;Python&quot;&lt;/code&gt; or &lt;code&gt;&quot;Tweepy&quot;&lt;/code&gt; in this case.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;on_status()&lt;/code&gt; of &lt;code&gt;FavRetweetListener&lt;/code&gt; processes tweets from the stream. This method receives a status object and uses  &lt;code&gt;favorite()&lt;/code&gt; and &lt;code&gt;retweet()&lt;/code&gt; to mark the tweet as &lt;em&gt;Liked&lt;/em&gt; and retweet.&lt;/p&gt;
&lt;p&gt;To avoid retweeting and liking tweets that are replies to other tweets, &lt;code&gt;on_status()&lt;/code&gt; uses an &lt;code&gt;if&lt;/code&gt; to see if &lt;code&gt;in_reply_to_status_id&lt;/code&gt; is not &lt;code&gt;None&lt;/code&gt;. Also, the code checks if you&amp;rsquo;re the tweet author to avoid retweeting and liking your own content.&lt;/p&gt;
&lt;p&gt;You can run this bot using the same instructions used for the previous bot, changing the Python program to &lt;code&gt;favretweet.py&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;the-reply-to-mentions-bot&quot;&gt;The Reply to Mentions Bot&lt;/h3&gt;
&lt;p&gt;This bot periodically fetches tweets in which you are mentioned. If the tweet is not a reply to another tweet, and it contains the words &lt;code&gt;&quot;help&quot;&lt;/code&gt; or &lt;code&gt;&quot;support&quot;&lt;/code&gt;, then the tweet author will be followed, and the tweet will be replied to with another tweet saying &lt;code&gt;&quot;Please reach us via DM&quot;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can use this bot to automate the initial process of answering your followers&amp;rsquo; questions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bot Source Code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the full source code for this bot. It uses a cursor to fetch your mentions:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;#!/usr/bin/env python&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# tweepy-bots/bots/autoreply.py&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tweepy&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;config&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_api&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&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 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;INFO&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;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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;check_mentions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keywords&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;since_id&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;Retrieving mentions&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;new_since_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;since_id&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweepy&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cursor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mentions_timeline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;since_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;since_id&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;n&quot;&gt;new_since_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;max&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_since_id&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;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;in_reply_to_status_id&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&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;continue&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;keyword&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&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;lower&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;keyword&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;keywords&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;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Answering to &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{tweet.user.name}&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;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;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;following&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;user&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;follow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

            &lt;span class=&quot;n&quot;&gt;api&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update_status&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;s2&quot;&gt;&amp;quot;Please reach us via DM&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;in_reply_to_status_id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tweet&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&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;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_since_id&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;n&quot;&gt;api&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;create_api&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;since_id&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;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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;since_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;since_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;check_mentions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;api&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;help&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;support&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;since_id&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;Waiting...&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&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;60&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;As with the others bots, the main function creates a Tweepy API object. After that, it initializes the variable &lt;code&gt;since_id&lt;/code&gt; with the value &lt;code&gt;1&lt;/code&gt;. This variable is used to only fetch mentions created after those already processed.&lt;/p&gt;
&lt;p&gt;Inside a loop, &lt;code&gt;check_mentions()&lt;/code&gt; is called once every minute.&lt;/p&gt;
&lt;p&gt;This function uses a Tweepy cursor and &lt;code&gt;mentions_timeline()&lt;/code&gt; to get all the tweets mentioning you that have an &lt;code&gt;id&lt;/code&gt; greater than the &lt;code&gt;since_id&lt;/code&gt; variable.&lt;/p&gt;
&lt;p&gt;For each tweet mentioning you, its author is followed using &lt;code&gt;tweet.user.follow()&lt;/code&gt; if you are not already following them.&lt;/p&gt;
&lt;p&gt;Then a &lt;strong&gt;reply&lt;/strong&gt; to the tweet is created using &lt;code&gt;update_status()&lt;/code&gt;, passing the &lt;code&gt;id&lt;/code&gt; of the original tweet as &lt;code&gt;in_reply_to_status_id&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;check_mentions()&lt;/code&gt; returns the greatest processed tweet &lt;code&gt;id&lt;/code&gt;. This information will be used as the &lt;code&gt;since_id&lt;/code&gt; in the next call to look only for tweets more recent than the ones already fetched.&lt;/p&gt;
&lt;p&gt;You can run the bot using the same instructions used previously. Just change the Python program to &lt;code&gt;autoreply.py&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;deploying-bots-to-a-server-using-docker&quot;&gt;Deploying Bots to a Server Using Docker&lt;/h2&gt;
&lt;p&gt;Being able to run your Twitter bots in your local machine is fine for development, but for production you&amp;rsquo;ll probably need to run your bots in a server. This section details how you can package your bot and its dependencies using &lt;strong&gt;Docker&lt;/strong&gt; and then deploy it to a server.&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 is just one of the ways you can deploy a Twitter bot to a server.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Docker provides a way to package any app in a Docker image containing not only the app itself, but all its dependencies too. You can learn more about Docker and its setup in &lt;a href=&quot;https://realpython.com/docker-in-action-fitter-happier-more-productive/#why-docker&quot;&gt;Docker in Action – Fitter, Happier, More Productive&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;building-the-docker-image&quot;&gt;Building the Docker Image&lt;/h3&gt;
&lt;p&gt;To package your bot or application, you have to create a &lt;strong&gt;Dockerfile&lt;/strong&gt; in the project&amp;rsquo;s root directory. This file contains a set of instructions used to create the Docker image containing your app.&lt;/p&gt;
&lt;p&gt;This is how your project structure should look:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;tweepy-bots/
│
├── bots/
│   ├── config.py
│   └── followfollowers.py
│   └── favretweet.py
│   └── autoreply.py
│
├── requirements.txt
└── Dockerfile
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the &lt;code&gt;Dockerfile&lt;/code&gt; and &lt;code&gt;requirements.txt&lt;/code&gt; live inside your project top directory.&lt;/p&gt;
&lt;p&gt;You can use the following Dockerfile to create the image for the Fav &amp;amp; Retweet bot. It uses &lt;code&gt;Python:3.7-alpine&lt;/code&gt; as the base image. We chose this image as the base since it&amp;rsquo;s very small and contains Python3.7 and pip. This Dockerfile then copies the bot code and the &lt;code&gt;requirements.txt&lt;/code&gt; file to the image. Finally, the dependencies are installed inside the image using &lt;strong&gt;pip3&lt;/strong&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight dockerfile&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;FROM&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; python:3.7-alpine&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt; bots/config.py /bots/
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt; bots/favretweet.py /bots/
&lt;span class=&quot;k&quot;&gt;COPY&lt;/span&gt; requirements.txt /tmp
&lt;span class=&quot;k&quot;&gt;RUN&lt;/span&gt; pip3 install -r /tmp/requirements.txt

&lt;span class=&quot;k&quot;&gt;WORKDIR&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; /bots&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;CMD&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;python3&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;favretweet.py&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The final line says what command must be run when this image is used.&lt;/p&gt;
&lt;p&gt;Now you can build the image using this command:&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; docker build . -t fav-retweet-bot
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, using the &lt;code&gt;docker images&lt;/code&gt; command, you can see the details of the newly generated image.&lt;/p&gt;
&lt;p&gt;Finally, you can use the &lt;code&gt;docker run&lt;/code&gt; command to test the image, passing it the environment variables holding the authentication credentials:&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; docker run -it -e &lt;span class=&quot;nv&quot;&gt;CONSUMER_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;uDRNy31oWfoiKV9AvPoNavy0I&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
 -e &lt;span class=&quot;nv&quot;&gt;CONSUMER_SECRET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;lnAL5VAgZLWNspQVpd3X6tEo47PRCmsPEwuxpvLCLSR08DMa4O&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
 -e &lt;span class=&quot;nv&quot;&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;622518593-j7gWSqzQO31ju7Bf7idB47NlZeSENsuADGU9B69I&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
 -e &lt;span class=&quot;nv&quot;&gt;ACCESS_TOKEN_SECRET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;iutFsxvP5IglRckJ1I1why6017xMNkzxqBID48Azw0GvT&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
 fav-retweet-bot
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While it&amp;rsquo;s running, you&amp;rsquo;ll see the bot&amp;rsquo;s logs output on the screen.&lt;/p&gt;
&lt;p&gt;This same procedure can be used to create the Docker image for other bots.&lt;/p&gt;
&lt;h3 id=&quot;example-deploying-a-twitter-bot-to-amazon-aws&quot;&gt;Example: Deploying a Twitter Bot to Amazon AWS&lt;/h3&gt;
&lt;p&gt;Now that the Docker image is ready, there are a lot of ways to deploy it to run in any server. In this section, you&amp;rsquo;ll see one method you can use to deploy a bot to a server in &lt;strong&gt;&lt;a href=&quot;https://aws.amazon.com&quot;&gt;Amazon AWS&lt;/a&gt;&lt;/strong&gt;. This setup uses an Amazon AWS &lt;strong&gt;EC2 instance&lt;/strong&gt;, like a virtual server, to run the Docker image. &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 need an Amazon AWS account to follow these steps. All the resources used in this article are eligible for the AWS free tier, so if you are new to AWS, then you won&amp;rsquo;t be charged.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Step 1: Export The Docker Image&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From the computer where you have created the Docker image, run these commands to export it to a file and compress it. You&amp;rsquo;re going to use this file later to upload the image to your EC2 instance:&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; docker image save fav-retweet-bot:latest -o fav-retweet-bot.tar
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; gzip fav-retweet-bot.tar
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the image has been compressed into &lt;code&gt;fav-retweet-bot.tar.gz&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2: Create an Amazon EC2 Instance&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The first step in AWS is to create a new EC2 instance. The bot will run inside this instance. Log in to your &lt;a href=&quot;https://aws.amazon.com/&quot;&gt;AWS console&lt;/a&gt;, choose the EC2 service, and select &lt;em&gt;Instances&lt;/em&gt;. You&amp;rsquo;ll see something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/aws_1.bc3ce5234c7e.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/aws_1.bc3ce5234c7e.png&quot; width=&quot;1918&quot; height=&quot;487&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_1.bc3ce5234c7e.png&amp;amp;w=479&amp;amp;sig=801f0ceb1985713f5e95390ddeb975d8be404dde 479w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_1.bc3ce5234c7e.png&amp;amp;w=959&amp;amp;sig=c42216b8d1f410cb79d90470feba4d69c083991e 959w, https://files.realpython.com/media/aws_1.bc3ce5234c7e.png 1918w&quot; sizes=&quot;75vw&quot; alt=&quot;Create an EC2 instance&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Click the &lt;em&gt;Launch instance&lt;/em&gt; button and select Ubuntu Server 18.04 as the base image:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/aws_2.63baf00be335.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/aws_2.63baf00be335.png&quot; width=&quot;1865&quot; height=&quot;719&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_2.63baf00be335.png&amp;amp;w=466&amp;amp;sig=d25af1e4306870544c663391ddcea30ca24e67bc 466w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_2.63baf00be335.png&amp;amp;w=932&amp;amp;sig=5df29ab6af0175c33484e4e7a612333f421503d9 932w, https://files.realpython.com/media/aws_2.63baf00be335.png 1865w&quot; sizes=&quot;75vw&quot; alt=&quot;Select EC2 instance base image&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now you can choose the instance type. This depends on the computing resources needed by your bot. For the bots described in this article, the &lt;em&gt;t2.micro&lt;/em&gt; instance type is a good starting point. Select it and click &lt;em&gt;Review and Launch&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/aws_3.9844080cc9c4.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/aws_3.9844080cc9c4.png&quot; width=&quot;1894&quot; height=&quot;889&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_3.9844080cc9c4.png&amp;amp;w=473&amp;amp;sig=f6f59ea45c0ce6126ab8f679b17e07f40628b9ec 473w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_3.9844080cc9c4.png&amp;amp;w=947&amp;amp;sig=f7921314f45e5b0760a6b6f8d5401fa67adb398b 947w, https://files.realpython.com/media/aws_3.9844080cc9c4.png 1894w&quot; sizes=&quot;75vw&quot; alt=&quot;Select EC2 instance type&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;On the next page, you can review and check your configuration. Then click the &lt;em&gt;Launch&lt;/em&gt; button to begin the creation of your EC2 instance:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/aws_4.e1b0bc829b9c.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/aws_4.e1b0bc829b9c.png&quot; width=&quot;1901&quot; height=&quot;892&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_4.e1b0bc829b9c.png&amp;amp;w=475&amp;amp;sig=45168fc8916d5c076ebac2f2e73fad5b86466eb2 475w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_4.e1b0bc829b9c.png&amp;amp;w=950&amp;amp;sig=e304781ee63d3fe1a2c2f85eefc74c337d276679 950w, https://files.realpython.com/media/aws_4.e1b0bc829b9c.png 1901w&quot; sizes=&quot;75vw&quot; alt=&quot;Review and launch EC2 instance&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After you&amp;rsquo;ve clicked &lt;em&gt;Launch&lt;/em&gt;, you&amp;rsquo;ll be asked to create a key pair. It&amp;rsquo;s used to allow you to connect to your instance and deploy the bot Docker image. Select &lt;em&gt;Create a new key pair&lt;/em&gt;, enter a key pair name, and download the key pair. &lt;/p&gt;
&lt;p&gt;Remember where you&amp;rsquo;re downloading the key pair. You&amp;rsquo;ll need it later.&lt;/p&gt;
&lt;p&gt;Then click the &lt;em&gt;Launch instances&lt;/em&gt; button to proceed:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/aws_5.8535e23d58c9.4d395260998a.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/aws_5.8535e23d58c9.4d395260998a.png&quot; width=&quot;692&quot; height=&quot;491&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_5.8535e23d58c9.4d395260998a.png&amp;amp;w=173&amp;amp;sig=239589f6562bcedf3f0eb3aa14a8d5afe67c2b19 173w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_5.8535e23d58c9.4d395260998a.png&amp;amp;w=346&amp;amp;sig=cad5eb947b33068785ffbdf3721c94b56436d470 346w, https://files.realpython.com/media/aws_5.8535e23d58c9.4d395260998a.png 692w&quot; sizes=&quot;75vw&quot; alt=&quot;Create key pair&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You will see a page saying that your instance is being created. Click the &lt;em&gt;View instances&lt;/em&gt; button to see the status of your instance:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/aws_6.cb10be3e43d0.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/aws_6.cb10be3e43d0.png&quot; width=&quot;1905&quot; height=&quot;675&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_6.cb10be3e43d0.png&amp;amp;w=476&amp;amp;sig=570ac07be22aaa303937e489ff6644ebd06d2199 476w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_6.cb10be3e43d0.png&amp;amp;w=952&amp;amp;sig=54b4021c4337177d7705bbe9f90db11f25683b59 952w, https://files.realpython.com/media/aws_6.cb10be3e43d0.png 1905w&quot; sizes=&quot;75vw&quot; alt=&quot;Instance is getting created&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At first, your instance state will be &lt;em&gt;pending&lt;/em&gt;. You have to wait until it transitions to &lt;em&gt;running&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/aws_7.0d23fb8e4c7f.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/aws_7.0d23fb8e4c7f.png&quot; width=&quot;1694&quot; height=&quot;289&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_7.0d23fb8e4c7f.png&amp;amp;w=423&amp;amp;sig=ae149ccdc9a07baa69778f0400298534172ec2f7 423w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_7.0d23fb8e4c7f.png&amp;amp;w=847&amp;amp;sig=df72276dddc513b2e2f56fec513dfdd65be293ee 847w, https://files.realpython.com/media/aws_7.0d23fb8e4c7f.png 1694w&quot; sizes=&quot;75vw&quot; alt=&quot;EC2 instance is in peding status&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/aws_8.daf1274ceeab.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/aws_8.daf1274ceeab.png&quot; width=&quot;1703&quot; height=&quot;191&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_8.daf1274ceeab.png&amp;amp;w=425&amp;amp;sig=52dc1d3c53f2e6c8829cc71b8ce9f3607c316094 425w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_8.daf1274ceeab.png&amp;amp;w=851&amp;amp;sig=06edc3a115d4e2a68a56f9bc09e569593c108f5c 851w, https://files.realpython.com/media/aws_8.daf1274ceeab.png 1703w&quot; sizes=&quot;75vw&quot; alt=&quot;EC2 instance is ready&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3: Install Docker in Your EC2 Instance&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Now you have to connect to your instance using SSH to install Docker on it.&lt;/p&gt;
&lt;p&gt;If, in the previous screen, you right click on your instance, you&amp;rsquo;ll find a context menu. Select the &lt;em&gt;Connect&lt;/em&gt; option to see how to connect using SSH:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/aws_9.6f76c4146b38.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/aws_9.6f76c4146b38.png&quot; width=&quot;302&quot; height=&quot;262&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_9.6f76c4146b38.png&amp;amp;w=75&amp;amp;sig=99e56a01307030be9e749e79b9c6aeac6ffdb807 75w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_9.6f76c4146b38.png&amp;amp;w=151&amp;amp;sig=62939dfc0830f9e75c93dfe1f849a1a8e2e0a62a 151w, https://files.realpython.com/media/aws_9.6f76c4146b38.png 302w&quot; sizes=&quot;75vw&quot; alt=&quot;Context menu for EC2 instance&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This dialog shows how to connect to your instance:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Captura_de_pantalla_de_2019-05-12_21-01-46.765f497770af.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/Captura_de_pantalla_de_2019-05-12_21-01-46.765f497770af.png&quot; width=&quot;675&quot; height=&quot;621&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Captura_de_pantalla_de_2019-05-12_21-01-46.765f497770af.png&amp;amp;w=168&amp;amp;sig=f3256af0fe66ff3e7eac563b6ee6e52f861f42e9 168w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Captura_de_pantalla_de_2019-05-12_21-01-46.765f497770af.png&amp;amp;w=337&amp;amp;sig=822204b1ad571cd9b12f47cd39ce29c0946dfcf7 337w, https://files.realpython.com/media/Captura_de_pantalla_de_2019-05-12_21-01-46.765f497770af.png 675w&quot; sizes=&quot;75vw&quot; alt=&quot;EC2 connection dialog&quot;/&gt;&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; &lt;code&gt;ec2-3-86-66-73.compute-1.amazonaws.com&lt;/code&gt; is the address that AWS assigned to the instance used in this article, but it will probably be different for you.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;First, change the permissions of your key pair file using the following command. Otherwise, you won&amp;rsquo;t be able to connect to your EC2 instance using this key pair:&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; chmod &lt;span class=&quot;m&quot;&gt;400&lt;/span&gt; mykeypair.pem
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then connect to your instance using SSH. You can copy the command you need to execute from the &lt;em&gt;Connect To Your Instance&lt;/em&gt; dialog: &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; ssh -i &lt;span class=&quot;s2&quot;&gt;&amp;quot;mykeypair.pem&amp;quot;&lt;/span&gt; ubuntu@ec2-3-86-66-73.compute-1.amazonaws.com
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once you&amp;rsquo;re connected, run the following commands to install Docker in the instance:&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;ubuntu@ip-172-31-44-227:~$&lt;/span&gt; sudo apt-get update
&lt;span class=&quot;gp&quot;&gt;ubuntu@ip-172-31-44-227:~$&lt;/span&gt; sudo apt install docker.io
&lt;span class=&quot;gp&quot;&gt;ubuntu@ip-172-31-44-227:~$&lt;/span&gt; sudo adduser ubuntu docker
&lt;span class=&quot;gp&quot;&gt;ubuntu@ip-172-31-44-227:~$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;exit&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;s important that you exit the SSH session after the installation, so that in the next login your user permissions will be reloaded.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 4: Upload Your Bot&amp;rsquo;s Docker Image&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From your local computer, upload the bot Docker image to your instance using &lt;code&gt;scp&lt;/code&gt;. This can take some time depending on your internet connection:&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; scp -i &lt;span class=&quot;s2&quot;&gt;&amp;quot;mykeypair.pem&amp;quot;&lt;/span&gt; fav-retweet-bot.tar.gz &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
    ubuntu@ec2-3-86-66-73.compute-1.amazonaws.com:/tmp
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When the image upload finishes, log in again to your instance using SSH:&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; ssh -i &lt;span class=&quot;s2&quot;&gt;&amp;quot;mykeypair.pem&amp;quot;&lt;/span&gt; ubuntu@ec2-3-86-66-73.compute-1.amazonaws.com
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Run these commands in your instance to decompress and import the Docker image:&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;ubuntu@ip-172-31-44-227:~$&lt;/span&gt; gunzip /tmp/fav-retweet-bot.tar.gz 
&lt;span class=&quot;gp&quot;&gt;ubuntu@ip-172-31-44-227:~$&lt;/span&gt; docker image load -i /tmp/fav-retweet-bot.tar
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Run Your Bot&amp;rsquo;s Docker Image&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The final step to deploy the bot is to run the Docker image in your EC2 instance, passing it the authentication credentials.&lt;/p&gt;
&lt;p&gt;You can do this using the &lt;code&gt;docker&lt;/code&gt; command. Passing the flags &lt;code&gt;-d&lt;/code&gt; and &lt;code&gt;--restart-always&lt;/code&gt; assures that the bot will keep running if you disconnect from the SSH session or if the instance is restarted:&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;ubuntu@ip-172-31-44-227:~$&lt;/span&gt; docker run -d --restart always &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
-e &lt;span class=&quot;nv&quot;&gt;CONSUMER_KEY&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;uDRNy31oWfoiKV9AvPoNavy0I&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
-e &lt;span class=&quot;nv&quot;&gt;CONSUMER_SECRET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;lnAL5VAgZLWNspQVpd3X6tEo47PRCmsPEwuxpvLCLSR08DMa4O&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
-e &lt;span class=&quot;nv&quot;&gt;ACCESS_TOKEN&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;622518593-j7gWSqzQO31ju7Bf7idB47NlZeSENsuADGU9B69I&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
-e &lt;span class=&quot;nv&quot;&gt;ACCESS_TOKEN_SECRET&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;iutFsxvP5IglRckJ1I1why6017xMNkzxqBID48Azw0GvT&amp;quot;&lt;/span&gt; &lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
fav-retweet-bot
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using &lt;code&gt;docker ps&lt;/code&gt;, you can check that the bot is running and find its container &lt;code&gt;id&lt;/code&gt;. Finally, using the &lt;code&gt;docker logs&lt;/code&gt; command and the container &lt;code&gt;id&lt;/code&gt;, you can check the output from the bot to see if it works properly:&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; ubuntu@ip-172-31-44-227:~$ docker logs e6aefe73a885
&lt;span class=&quot;go&quot;&gt;INFO:root:API created&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;INFO:root:Processing tweet id 1118276911262785538&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;INFO:root:Processing tweet id 1118276942162214918&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;INFO:root:Processing tweet id 1118276990853951488&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;INFO:root:Processing tweet id 1118277032360722433&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;INFO:root:Processing tweet id 1118277034466324480&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, even if you disconnect from the SSH session or turn off your computer, the bot will continue to run on your AWS EC2 instance.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Free AWS Resources&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;To save resources and money (if your AWS free tier period has ended), you can stop or terminate your EC2 instance:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/aws_11.e75996b3fab5.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border &quot; src=&quot;https://files.realpython.com/media/aws_11.e75996b3fab5.png&quot; width=&quot;1134&quot; height=&quot;382&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_11.e75996b3fab5.png&amp;amp;w=283&amp;amp;sig=12390bf50d65549451558fb3acd7c41e8f0574dd 283w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/aws_11.e75996b3fab5.png&amp;amp;w=567&amp;amp;sig=6910e663a36c485c9c4f817aeac6d4a600e66ea9 567w, https://files.realpython.com/media/aws_11.e75996b3fab5.png 1134w&quot; sizes=&quot;75vw&quot; alt=&quot;EC2 terminate or stop and instance&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Stopping it will allow you to restart it in the future, but it will still consume some resources related to your instance storage. By contrast, if you Terminate an EC2 instance, then all its resources will be released, but you won&amp;rsquo;t be able to restart it. &lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a lot more to using AWS, like creating an AWS image of your instance, but that goes beyond the scope of this article.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;Building your own Twitter bots allows you to take your Twitter presence to the next level. By using bots, you can automate content creation and other Twitter activities. This can save you a lot of time and give your audience a better experience.&lt;/p&gt;
&lt;p&gt;The Tweepy package hides many low level details of the Twitter API, allowing you to focus on the logic of your Twitter bots.&lt;/p&gt;
&lt;p&gt;In this article, you learned how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Improve and automate your interactions with your Twitter audience&lt;/li&gt;
&lt;li&gt;Install Tweepy&lt;/li&gt;
&lt;li&gt;Sign up as a Twitter developer to use its API&lt;/li&gt;
&lt;li&gt;Use Tweepy to invoke the Twitter API&lt;/li&gt;
&lt;li&gt;Build Twitter bots&lt;/li&gt;
&lt;li&gt;Deploy the bots to a server using Docker and AWS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can use the bots in this article as a starting point to automate part of your Twitter activity. Don&amp;rsquo;t forget to take a look at the whole &lt;a href=&quot;https://tweepy.readthedocs.io/en/latest/api.html&quot;&gt;Tweepy API documentation&lt;/a&gt; and use your imagination to make more complex bots that are meaningful to your use case.&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 Implement a Python Stack</title>
      <id>https://realpython.com/how-to-implement-python-stack/</id>
      <link href="https://realpython.com/how-to-implement-python-stack/"/>
      <updated>2019-06-05T14:00:00+00:00</updated>
      <summary>In this tutorial, you&#39;ll learn how to implement a Python stack. You&#39;ll see how to recognize when a stack is a good choice for data structures, how to decide which implementation is best for a program, and what extra considerations to make about stacks in a threading or multiprocessing environment.</summary>
      <content type="html">
        &lt;p&gt;Have you heard of stacks and wondered what they are? Do you have the general idea but are wondering how to implement a Python stack? You&amp;rsquo;ve come to the right place!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this tutorial, you&amp;rsquo;ll learn:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to recognize when a stack is a good choice for data structures&lt;/li&gt;
&lt;li&gt;How to decide which implementation is best for your program&lt;/li&gt;
&lt;li&gt;What extra considerations to make about stacks in a threading or multiprocessing environment&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This tutorial is for Pythonistas who are comfortable running scripts, know what a &lt;a href=&quot;https://realpython.com/python-lists-tuples/&quot;&gt;&lt;code&gt;list&lt;/code&gt;&lt;/a&gt; is and how to use it, and are wondering how to implement Python stacks.&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-cheat-sheet-shortened&quot; data-focus=&quot;false&quot;&gt;Click here to get a Python Cheat Sheet&lt;/a&gt; and learn the basics of Python 3, like working with data types, dictionaries, lists, and Python functions.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;what-is-a-stack&quot;&gt;What Is a Stack?&lt;/h2&gt;
&lt;p&gt;A &lt;a href=&quot;https://en.wikipedia.org/wiki/Stack_(abstract_data_type)&quot;&gt;stack&lt;/a&gt; is a data structure that stores items in an Last-In/First-Out manner. This is frequently referred to as LIFO. This is in contrast to a &lt;a href=&quot;https://en.wikipedia.org/wiki/Queue_(abstract_data_type)&quot;&gt;queue&lt;/a&gt;, which stores items in a First-In/First-Out (FIFO) manner.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s probably easiest to understand a stack if you think of a use case you&amp;rsquo;re likely familiar with: the &lt;em&gt;Undo&lt;/em&gt; feature in your editor.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s imagine you&amp;rsquo;re editing a Python file so we can look at some of the operations you perform. First, you add a new function. This adds a new item to the undo stack:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stack_push_add_function.b406cffbe2dd.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-50&quot; src=&quot;https://files.realpython.com/media/stack_push_add_function.b406cffbe2dd.png&quot; width=&quot;1338&quot; height=&quot;873&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_push_add_function.b406cffbe2dd.png&amp;amp;w=334&amp;amp;sig=80332ad3884db374f0a530b66b9966a79867996b 334w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_push_add_function.b406cffbe2dd.png&amp;amp;w=669&amp;amp;sig=83ba4a8744b2a83a7529428e15efe1871de1e386 669w, https://files.realpython.com/media/stack_push_add_function.b406cffbe2dd.png 1338w&quot; sizes=&quot;75vw&quot; alt=&quot;Pushing the &amp;quot;add function&amp;quot; operation to the undo stack.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see that the stack now has an &lt;em&gt;Add Function&lt;/em&gt; operation on it. After adding the function, you delete a word from a comment. This also gets added to the undo stack:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stack_push_delete_word.6a64fed15fde.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-50&quot; src=&quot;https://files.realpython.com/media/stack_push_delete_word.6a64fed15fde.png&quot; width=&quot;1338&quot; height=&quot;873&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_push_delete_word.6a64fed15fde.png&amp;amp;w=334&amp;amp;sig=652eff9b09a6f976bc6c18d838c06b61c3a08aa1 334w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_push_delete_word.6a64fed15fde.png&amp;amp;w=669&amp;amp;sig=5af3dac661dbc7942f73b9d9eee13f8efc66a8b7 669w, https://files.realpython.com/media/stack_push_delete_word.6a64fed15fde.png 1338w&quot; sizes=&quot;75vw&quot; alt=&quot;Pushing the &amp;quot;delete word&amp;quot; operation on the undo stack.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notice how the &lt;em&gt;Delete Word&lt;/em&gt; item is placed on top of the stack. Finally you indent a comment so that it&amp;rsquo;s lined up properly:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stack_push_indent.01223b7d94a7.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-50&quot; src=&quot;https://files.realpython.com/media/stack_push_indent.01223b7d94a7.png&quot; width=&quot;1338&quot; height=&quot;873&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_push_indent.01223b7d94a7.png&amp;amp;w=334&amp;amp;sig=a9b5273aff865637b9d3fb834e487f7105d6cae9 334w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_push_indent.01223b7d94a7.png&amp;amp;w=669&amp;amp;sig=d9d64460b1f17caabf89dcea155bc844c83c8c31 669w, https://files.realpython.com/media/stack_push_indent.01223b7d94a7.png 1338w&quot; sizes=&quot;75vw&quot; alt=&quot;Pushing the &amp;quot;indent comment&amp;quot; operation on the undo stack.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see that each of these commands are stored in an undo stack, with each new command being put at the top. When you&amp;rsquo;re working with stacks, adding new items like this is called &lt;code&gt;push&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now you&amp;rsquo;ve decided to undo all three of those changes, so you hit the undo command. It takes the item at the top of the stack, which was indenting the comment, and removes that from the stack:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stack_pop_indent.e28029c81831.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-50&quot; src=&quot;https://files.realpython.com/media/stack_pop_indent.e28029c81831.png&quot; width=&quot;1338&quot; height=&quot;873&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_pop_indent.e28029c81831.png&amp;amp;w=334&amp;amp;sig=d9bb6ea3297399063ae1e2893e7734bf8c87edfa 334w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_pop_indent.e28029c81831.png&amp;amp;w=669&amp;amp;sig=89f1a41716e1692aadb5da4f3008dbb521a09459 669w, https://files.realpython.com/media/stack_pop_indent.e28029c81831.png 1338w&quot; sizes=&quot;75vw&quot; alt=&quot;Popping the &amp;quot;indent comment&amp;quot; function from the undo stack.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Your editor undoes the indent, and the undo stack now contains two items. This operation is the opposite of &lt;code&gt;push&lt;/code&gt; and is commonly called &lt;code&gt;pop&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When you hit undo again, the next item is popped off the stack:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stack_pop_delete_word.89f14f6ed390.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-50&quot; src=&quot;https://files.realpython.com/media/stack_pop_delete_word.89f14f6ed390.png&quot; width=&quot;1338&quot; height=&quot;873&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_pop_delete_word.89f14f6ed390.png&amp;amp;w=334&amp;amp;sig=2e824fd4a6f906e970c3687fae4d795126192f55 334w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_pop_delete_word.89f14f6ed390.png&amp;amp;w=669&amp;amp;sig=70a8bc9d19c0d3f9fc47e81048110123ced12477 669w, https://files.realpython.com/media/stack_pop_delete_word.89f14f6ed390.png 1338w&quot; sizes=&quot;75vw&quot; alt=&quot;Popping the &amp;quot;delete word&amp;quot; operation from the undo stack.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This removes the &lt;em&gt;Delete Word&lt;/em&gt; item, leaving only one operation on the stack.&lt;/p&gt;
&lt;p&gt;Finally, if you hit &lt;em&gt;Undo&lt;/em&gt; a third time, then the last item will be popped off the stack:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stack_pop_add_function.a4f66332971a.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block w-50&quot; src=&quot;https://files.realpython.com/media/stack_pop_add_function.a4f66332971a.png&quot; width=&quot;1338&quot; height=&quot;873&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_pop_add_function.a4f66332971a.png&amp;amp;w=334&amp;amp;sig=2837d04717001c3b3f6ce04792da09532a9cda3c 334w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_pop_add_function.a4f66332971a.png&amp;amp;w=669&amp;amp;sig=491c7d02bc1b3e98732a179395938094af273b92 669w, https://files.realpython.com/media/stack_pop_add_function.a4f66332971a.png 1338w&quot; sizes=&quot;75vw&quot; alt=&quot;Popping the &amp;quot;add function&amp;quot; operation from the undo stack.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The undo stack is now empty. Hitting &lt;em&gt;Undo&lt;/em&gt; again after this will have no effect because your undo stack is empty, at least in most editors. You&amp;rsquo;ll see what happens when you call &lt;code&gt;.pop()&lt;/code&gt; on an empty stack in the implementation descriptions below.&lt;/p&gt;
&lt;h2 id=&quot;implementing-a-python-stack&quot;&gt;Implementing a Python Stack&lt;/h2&gt;
&lt;p&gt;There are a couple of options when you&amp;rsquo;re implementing a Python stack. This article won&amp;rsquo;t cover all of them, just the basic ones that will meet almost all of your needs. You&amp;rsquo;ll focus on using data structures that are part of the Python library, rather than writing your own or using third-party packages.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll look at the following Python stack implementations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;list&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;collections.deque&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;queue.LifoQueue&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;using-list-to-create-a-python-stack&quot;&gt;Using &lt;code&gt;list&lt;/code&gt; to Create a Python Stack&lt;/h3&gt;
&lt;p&gt;The built-in &lt;code&gt;list&lt;/code&gt; structure that you likely use frequently in your programs can be used as a stack. Instead of &lt;code&gt;.push()&lt;/code&gt;, you can use &lt;code&gt;.append()&lt;/code&gt; to add new elements to the top of your stack, while &lt;code&gt;.pop()&lt;/code&gt; removes the elements in the LIFO order:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;myStack&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;myStack&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;s1&quot;&gt;&amp;#39;a&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;myStack&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;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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myStack&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;s1&quot;&gt;&amp;#39;c&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;myStack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&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;myStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;c&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;myStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;b&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;myStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&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;n&quot;&gt;myStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&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;console&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;IndexError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;pop from empty list&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can see in the final command that a &lt;code&gt;list&lt;/code&gt; will raise an &lt;code&gt;IndexError&lt;/code&gt; if you call &lt;code&gt;.pop()&lt;/code&gt; on an empty stack.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;list&lt;/code&gt; has the advantage of being familiar. You know how it works and likely have used it in your programs already.&lt;/p&gt;
&lt;p&gt;Unfortunately, &lt;code&gt;list&lt;/code&gt; has a few shortcomings compared to other data structures you&amp;rsquo;ll look at. The biggest issue is that it can run into speed issues as it grows. The items in a &lt;code&gt;list&lt;/code&gt; are stored with the goal of providing fast access to random elements in the &lt;code&gt;list&lt;/code&gt;. At a high level, this means that the items are stored next to each other in memory.&lt;/p&gt;
&lt;p&gt;If your stack grows bigger than the block of memory that currently holds it, then Python needs to do some memory allocations. This can lead to some &lt;code&gt;.append()&lt;/code&gt; calls taking much longer than other ones.&lt;/p&gt;
&lt;p&gt;There is a less serious problem as well. If you use &lt;code&gt;.insert()&lt;/code&gt; to add an element to your stack at a position other than the end, it can take much longer. This is not normally something you would do to a stack, however.&lt;/p&gt;
&lt;p&gt;The next data structure will help you get around the reallocation problem you saw with &lt;code&gt;list&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;using-collectionsdeque-to-create-a-python-stack&quot;&gt;Using &lt;code&gt;collections.deque&lt;/code&gt; to Create a Python Stack&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;collections&lt;/code&gt; module contains &lt;a href=&quot;https://docs.python.org/3/library/collections.html#collections.deque&quot;&gt;&lt;code&gt;deque&lt;/code&gt;&lt;/a&gt;, which is useful for creating Python stacks. &lt;code&gt;deque&lt;/code&gt; is pronounced &amp;ldquo;deck&amp;rdquo; and stands for &amp;ldquo;double-ended queue.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;You can use the same methods on &lt;code&gt;deque&lt;/code&gt; as you saw above for &lt;code&gt;list&lt;/code&gt;, &lt;code&gt;.append()&lt;/code&gt;, and &lt;code&gt;.pop()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;deque&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myStack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deque&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;myStack&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;s1&quot;&gt;&amp;#39;a&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;myStack&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;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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myStack&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;s1&quot;&gt;&amp;#39;c&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;myStack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;deque([&amp;#39;a&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&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;myStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;c&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;myStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;b&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;myStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&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;n&quot;&gt;myStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&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;console&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;IndexError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;pop from an empty deque&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This looks almost identical to the &lt;code&gt;list&lt;/code&gt; example above. At this point, you might be wondering why the Python core developers would create two data structures that look the same.&lt;/p&gt;
&lt;h4 id=&quot;why-have-deque-and-list&quot;&gt;Why Have &lt;code&gt;deque&lt;/code&gt; and &lt;code&gt;list&lt;/code&gt;?&lt;/h4&gt;
&lt;p&gt;As you saw in the discussion about &lt;code&gt;list&lt;/code&gt; above, it was built upon blocks of contiguous memory, meaning that the items in the list are stored right next to each other:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stack_list_memory_usage.bf57ab8fa608.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/stack_list_memory_usage.bf57ab8fa608.png&quot; width=&quot;738&quot; height=&quot;378&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_list_memory_usage.bf57ab8fa608.png&amp;amp;w=184&amp;amp;sig=d43b0ebb44ce8d90a4797d6e0f3d88cfbefb52cb 184w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_list_memory_usage.bf57ab8fa608.png&amp;amp;w=369&amp;amp;sig=ebbf4699e3f5e6fb73296ae53ca5d9167fb7bb81 369w, https://files.realpython.com/media/stack_list_memory_usage.bf57ab8fa608.png 738w&quot; sizes=&quot;75vw&quot; alt=&quot;Memory structure of a list implementing a stack&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This works great for several operations, like indexing into the &lt;code&gt;list&lt;/code&gt;. Getting &lt;code&gt;myList[3]&lt;/code&gt; is fast, as Python knows exactly where to look in memory to find it. This memory layout also allows slices to work well on lists.&lt;/p&gt;
&lt;p&gt;The contiguous memory layout is the reason that &lt;code&gt;list&lt;/code&gt; might need to take more time to &lt;code&gt;.append()&lt;/code&gt; some objects than others. If the block of contiguous memory is full, then it will need to get another block, which can take much longer than a normal &lt;code&gt;.append()&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stack_list_memory_push.8ad17a48f40a.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/stack_list_memory_push.8ad17a48f40a.png&quot; width=&quot;1698&quot; height=&quot;528&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_list_memory_push.8ad17a48f40a.png&amp;amp;w=424&amp;amp;sig=78676d6dc9598bbc9e9634f3b9936ce63b795315 424w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_list_memory_push.8ad17a48f40a.png&amp;amp;w=849&amp;amp;sig=40bd3cfee9d0120bd4f7efd716b65a247feb2d7e 849w, https://files.realpython.com/media/stack_list_memory_push.8ad17a48f40a.png 1698w&quot; sizes=&quot;75vw&quot; alt=&quot;Memory structure of a list pushing a new element&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;deque&lt;/code&gt;, on the other hand, is built upon a doubly linked list. In a linked list structure, each entry is stored in its own memory block and has a reference to the next entry in the list.&lt;/p&gt;
&lt;p&gt;A doubly linked list is just the same, except that each entry has references to both the previous and the next entry in the list. This allows you to easily add nodes to either end of the list.&lt;/p&gt;
&lt;p&gt;Adding a new entry into a linked list structure only requires setting the new entry&amp;rsquo;s reference to point to the current top of the stack and then pointing the top of the stack to the new entry:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/stack_deque_memory.e414da68dce1.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/stack_deque_memory.e414da68dce1.png&quot; width=&quot;1857&quot; height=&quot;522&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_deque_memory.e414da68dce1.png&amp;amp;w=464&amp;amp;sig=8f163886ee9484fd2eda09f15dbd1cadf4a9be62 464w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/stack_deque_memory.e414da68dce1.png&amp;amp;w=928&amp;amp;sig=2a09d739db5d8ff99f33e6ec6939c712fba15281 928w, https://files.realpython.com/media/stack_deque_memory.e414da68dce1.png 1857w&quot; sizes=&quot;75vw&quot; alt=&quot;Memory structure of a deque pushing a new element&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This constant-time addition and removal of entries onto a stack comes with a trade-off, however. Getting &lt;code&gt;myDeque[3]&lt;/code&gt; is slower than it was for a list, because Python needs to walk through each node of the list to get to the third element.&lt;/p&gt;
&lt;p&gt;Fortunately, you rarely want to do random indexing or slicing on a stack. Most operations on a stack are either &lt;code&gt;push&lt;/code&gt; or &lt;code&gt;pop&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The constant time &lt;code&gt;.append()&lt;/code&gt; and &lt;code&gt;.pop()&lt;/code&gt; operations make &lt;code&gt;deque&lt;/code&gt; an excellent choice for implementing a Python stack if your code doesn&amp;rsquo;t use threading.&lt;/p&gt;
&lt;h2 id=&quot;python-stacks-and-threading&quot;&gt;Python Stacks and Threading&lt;/h2&gt;
&lt;p&gt;Python stacks can be useful in multi-threaded programs as well, but if you&amp;rsquo;re not interested in threading, then you can safely skip this section and jump to the summary.&lt;/p&gt;
&lt;p&gt;The two options you&amp;rsquo;ve seen so far, &lt;code&gt;list&lt;/code&gt; and &lt;code&gt;deque&lt;/code&gt;, behave differently if your program has threads.&lt;/p&gt;
&lt;p&gt;To start with the simpler one, you should never use &lt;code&gt;list&lt;/code&gt; for any data structure that can be accessed by multiple threads. &lt;code&gt;list&lt;/code&gt; is not thread-safe.&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 need a refresher on thread safety and race conditions, check out &lt;a href=&quot;https://realpython.com/intro-to-python-threading/&quot;&gt;An Intro to Threading in Python&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;deque&lt;/code&gt; is a little more complex, however. If you read the documentation for &lt;code&gt;deque&lt;/code&gt;, it clearly states that both the &lt;code&gt;.append()&lt;/code&gt; and &lt;code&gt;.pop()&lt;/code&gt; operations are atomic, meaning that they won&amp;rsquo;t be interrupted by a different thread.&lt;/p&gt;
&lt;p&gt;So if you restrict yourself to using only &lt;code&gt;.append()&lt;/code&gt; and &lt;code&gt;.pop()&lt;/code&gt;, then you will be thread safe.&lt;/p&gt;
&lt;p&gt;The concern with using &lt;code&gt;deque&lt;/code&gt; in a threaded environment is that there are other methods in that class, and those are not specifically designed to be atomic, nor are they thread safe.&lt;/p&gt;
&lt;p&gt;So, while it&amp;rsquo;s possible to build a thread-safe Python stack using a &lt;code&gt;deque&lt;/code&gt;, doing so exposes yourself to someone misusing it in the future and causing race conditions.&lt;/p&gt;
&lt;p&gt;Okay, if you&amp;rsquo;re threading, you can&amp;rsquo;t use &lt;code&gt;list&lt;/code&gt; for a stack and you probably don&amp;rsquo;t want to use &lt;code&gt;deque&lt;/code&gt; for a stack, so how &lt;em&gt;can&lt;/em&gt; you build a Python stack for a threaded program?&lt;/p&gt;
&lt;p&gt;The answer is in the &lt;code&gt;queue&lt;/code&gt; module, &lt;a href=&quot;https://docs.python.org/3/library/queue.html&quot;&gt;&lt;code&gt;queue.LifoQueue&lt;/code&gt;&lt;/a&gt;. Remember how you learned that stacks operate on the Last-In/First-Out principle? Well, that&amp;rsquo;s what the &amp;ldquo;Lifo&amp;rdquo; portion of &lt;code&gt;LifoQueue&lt;/code&gt; stands for.&lt;/p&gt;
&lt;p&gt;While the interface for &lt;code&gt;list&lt;/code&gt; and &lt;code&gt;deque&lt;/code&gt; were similar, &lt;code&gt;LifoQueue&lt;/code&gt; uses &lt;code&gt;.put()&lt;/code&gt; and &lt;code&gt;.get()&lt;/code&gt; to add and remove data from the stack:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;queue&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LifoQueue&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myStack&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LifoQueue&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;myStack&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;s1&quot;&gt;&amp;#39;a&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;myStack&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;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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myStack&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;s1&quot;&gt;&amp;#39;c&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;myStack&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;queue.LifoQueue object at 0x7f408885e2b0&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;myStack&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;go&quot;&gt;&amp;#39;c&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;myStack&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;go&quot;&gt;&amp;#39;b&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;myStack&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;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;c1&quot;&gt;# myStack.get() &amp;lt;--- waits forever&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;myStack&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_nowait&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;console&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;/usr/lib/python3.7/queue.py&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;198&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;get_nowait&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;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;block&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;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;/usr/lib/python3.7/queue.py&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;167&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;get&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Empty&lt;/span&gt;
&lt;span class=&quot;err&quot;&gt;_queue.Empty&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unlike &lt;code&gt;deque&lt;/code&gt;, &lt;code&gt;LifoQueue&lt;/code&gt; is designed to be fully thread-safe. All of its methods are safe to use in a threaded environment. It also adds optional time-outs to its operations which can frequently be a must-have feature in threaded programs.&lt;/p&gt;
&lt;p&gt;This full thread safety comes at a cost, however. To achieve this thread-safety, &lt;code&gt;LifoQueue&lt;/code&gt; has to do a little extra work on each operation, meaning that it will take a little longer.&lt;/p&gt;
&lt;p&gt;Frequently, this slight slow down will not matter to your overall program speed, but if you&amp;rsquo;ve measured your performance and discovered that your stack operations are the bottleneck, then carefully switching to a &lt;code&gt;deque&lt;/code&gt; might be worth doing.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;d like to stress again that switching from &lt;code&gt;LifoQueue&lt;/code&gt; to &lt;code&gt;deque&lt;/code&gt; because it&amp;rsquo;s faster without having measurements showing that your stack operations are a bottleneck is an example of &lt;a href=&quot;https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize&quot;&gt;premature optimization&lt;/a&gt;. Don&amp;rsquo;t do that.&lt;/p&gt;
&lt;h2 id=&quot;python-stacks-which-implementation-should-you-use&quot;&gt;Python Stacks: Which Implementation Should You Use?&lt;/h2&gt;
&lt;p&gt;In general, you should use a &lt;code&gt;deque&lt;/code&gt; if you&amp;rsquo;re not using threading. If you are using threading, then you should use a &lt;code&gt;LifoQueue&lt;/code&gt; unless you&amp;rsquo;ve measured your performance and found that a small boost in speed for pushing and popping will make enough difference to warrant the maintenance risks.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;list&lt;/code&gt; may be familiar, but it should be avoided because it can potentially have memory reallocation issues. The interfaces for &lt;code&gt;deque&lt;/code&gt; and &lt;code&gt;list&lt;/code&gt; are identical, and &lt;code&gt;deque&lt;/code&gt; doesn&amp;rsquo;t have these issues, which makes &lt;code&gt;deque&lt;/code&gt; the best choice for your non-threaded Python stack.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You now know what a stack is and have seen situations where they can be used in real-life programs. You&amp;rsquo;ve evaluated three different options for implementing stacks and seen that &lt;code&gt;deque&lt;/code&gt; is a great choice for non-threaded programs. If you&amp;rsquo;re implementing a stack in a threading environment, then it&amp;rsquo;s likely a good idea to use a &lt;code&gt;LifoQueue&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You are now able to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Recognize when a stack would be a good data structure&lt;/li&gt;
&lt;li&gt;Select which implementation is right for your problem&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you still have questions, feel free to reach out in the comments sections below. Now, go write some code since you gained another tool to help you solve your programming problems!&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>Introduction to Git and GitHub for Python Developers</title>
      <id>https://realpython.com/courses/python-git-github-intro/</id>
      <link href="https://realpython.com/courses/python-git-github-intro/"/>
      <updated>2019-06-04T14:00:00+00:00</updated>
      <summary>What is Git,  what is GitHub, and what&#39;s the difference? Learn the basics of Git and GitHub from the perspective of a Pythonista in this step-by-step video course.</summary>
      <content type="html">
        &lt;p&gt;What is Git,  what is GitHub, and what&amp;rsquo;s the difference? Learn the basics of Git and GitHub from the perspective of a Pythonista in this step-by-step video course.&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>Object-Oriented Programming in Python vs Java</title>
      <id>https://realpython.com/oop-in-python-vs-java/</id>
      <link href="https://realpython.com/oop-in-python-vs-java/"/>
      <updated>2019-06-03T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn about the practical differences in Python vs Java for object-oriented programming. By the end, you&#39;ll be able to apply your knowledge to Python, understand how to reinterpret your understanding of Java objects to Python, and use objects in a Pythonic way.</summary>
      <content type="html">
        &lt;p&gt;Java programmers making a move to Python often struggle with Python&amp;rsquo;s approach to object-oriented programming (OOP). The approach to working with objects, variable types, and other language capabilities taken by Python vs Java are quite different. It can make switching between both languages very confusing.&lt;/p&gt;
&lt;p&gt;This article compares and contrasts object-oriented programming support in Python vs Java. By the end, you&amp;rsquo;ll be able to apply your knowledge of object-oriented programming to Python, understand how to reinterpret your understanding of Java objects to Python, and use objects in a Pythonic way.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Over the course of this article, you&amp;rsquo;ll:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Build a basic class in both Java and Python&lt;/li&gt;
&lt;li&gt;Explore how object attributes work in Python vs Java&lt;/li&gt;
&lt;li&gt;Compare and contrast Java methods and Python functions&lt;/li&gt;
&lt;li&gt;Discover inheritance and polymorphism mechanisms in both languages&lt;/li&gt;
&lt;li&gt;Investigate reflection across Python vs Java&lt;/li&gt;
&lt;li&gt;Apply everything in a complete class implementation in both languages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article isn&amp;rsquo;t a primer on object-oriented programming. Rather, it compares object-oriented features and principles of Python vs Java. Readers should have good knowledge of Java, and also be familiar with coding Python. If you are unfamiliar with object-oriented programming, then check out &lt;a href=&quot;https://realpython.com/courses/intro-object-oriented-programming-oop-python/&quot;&gt;Intro to Object-Oriented Programming (OOP) in Python&lt;/a&gt;. All Python examples will work with Python 3.6 or later.&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Sample Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/optins/view/oop-python-vs-java/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-oop-python-vs-java&quot; data-focus=&quot;false&quot;&gt;Click here to download the commented sample object definitions and source code&lt;/a&gt; for the Java and Python objects in this article.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;sample-classes-in-python-vs-java&quot;&gt;Sample Classes in Python vs Java&lt;/h2&gt;
&lt;p&gt;To begin, you&amp;rsquo;ll implement the same small class in both Python and Java to illustrate the differences between them. You&amp;rsquo;ll make modifications to them as the article progresses.&lt;/p&gt;
&lt;p&gt;First, assume you have the following &lt;code&gt;Car&lt;/code&gt; class definition in Java:&lt;/p&gt;
&lt;div class=&quot;highlight java&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;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;}&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;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getYear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Java classes are defined in files with the same name as the class. So, you have to save this class in a file named &lt;code&gt;Car.java&lt;/code&gt;. Only one class can be defined in each file. &lt;/p&gt;
&lt;p&gt;A similar small &lt;code&gt;Car&lt;/code&gt; class is written in Python as follows:&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&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;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;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &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;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &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;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &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;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Python you can declare a class anywhere, in any file, at any time. Save this class in the file &lt;code&gt;car.py&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Using these classes as your base, you can explore the basic components of classes and objects.&lt;/p&gt;
&lt;h2 id=&quot;object-attributes&quot;&gt;Object Attributes&lt;/h2&gt;
&lt;p&gt;All object-oriented languages have some way to store data about the object. In Java and Python, data is stored in &lt;strong&gt;attributes&lt;/strong&gt;, which are variables associated with specific objects.&lt;/p&gt;
&lt;p&gt;One of the most significant differences between Python vs Java is how they define and manage class and object attributes. Some of these differences come from constraints imposed by the languages, while others come from best practices.&lt;/p&gt;
&lt;h3 id=&quot;declaration-and-initialization&quot;&gt;Declaration and Initialization&lt;/h3&gt;
&lt;p&gt;In Java, you declare attributes in the class body, outside of any methods, with a definite type. You must define class attributes before they are used:&lt;/p&gt;
&lt;div class=&quot;highlight java&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;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Python, you both declare and define attributes inside the class &lt;code&gt;__init__()&lt;/code&gt;, which is the equivalent of Java&amp;rsquo;s constructor:&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;__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;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &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;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &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;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By prefixing the variable names with &lt;code&gt;self&lt;/code&gt;, you tell Python these are attributes. Each instance of the class will have a copy. All variables in Python are &lt;a href=&quot;https://realpython.com/python-type-checking/#duck-typing&quot;&gt;loosely typed&lt;/a&gt;, and these attributes are no exception.&lt;/p&gt;
&lt;p&gt;You can also create instance variables outside of &lt;code&gt;.__init__()&lt;/code&gt;, but it&amp;rsquo;s not a best practice as their scope is often confusing. If not used properly, instance variables created outside of &lt;code&gt;.__init__()&lt;/code&gt; can lead to subtle bugs that are hard to find. For example, you can add a new attribute &lt;code&gt;.wheels&lt;/code&gt; to a &lt;code&gt;Car&lt;/code&gt; object like this:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;lineno&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;car&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1967&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&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;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;My car is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.color}&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;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;My car is yellow&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &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;my_car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wheels&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&gt;&lt;span class=&quot;lineno&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;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;Wheels: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.wheels}&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;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;Wheels: 5&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, if you forget the &lt;code&gt;my_car.wheels = 5&lt;/code&gt; on line 6, then Python displays an error:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;lineno&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;car&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1967&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&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;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;My car is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.color}&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;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;My car is yellow&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;
&lt;span class=&quot;lineno&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;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;Wheels: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.wheels}&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;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;hll&quot;&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&gt;&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;gr&quot;&gt;AttributeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;Car&amp;#39; object has no attribute &amp;#39;wheels&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Python, when you declare a variable outside of a method, it&amp;rsquo;s treated as a class variable. Update the &lt;code&gt;Car&lt;/code&gt; class as follows:&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&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;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;wheels&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&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;__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;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &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;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &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;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This changes how you use the variable &lt;code&gt;wheels&lt;/code&gt;. Instead of referring to it using an object, you refer to it using the class name:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;lineno&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;car&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1967&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&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;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;My car is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.color}&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;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;My car is yellow&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;
&lt;span class=&quot;lineno&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;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;It has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{car.Car.wheels}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; wheels&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;go&quot;&gt;It has 0 wheels&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;
&lt;span class=&quot;lineno&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;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;It has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.wheels}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; wheels&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;go&quot;&gt;It has 0 wheels&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; In Python, you refer to a class variable using the following syntax:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The name of the file containing the class, without the &lt;code&gt;.py&lt;/code&gt; extension&lt;/li&gt;
&lt;li&gt;A dot&lt;/li&gt;
&lt;li&gt;The name of the class&lt;/li&gt;
&lt;li&gt;A dot&lt;/li&gt;
&lt;li&gt;The name of the variable&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Since you saved the &lt;code&gt;Car&lt;/code&gt; class in the file &lt;code&gt;car.py&lt;/code&gt;, you refer to the class variable &lt;code&gt;wheels&lt;/code&gt; on line 6 as &lt;code&gt;car.Car.wheels&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can refer to &lt;code&gt;my_car.wheels&lt;/code&gt; or &lt;code&gt;car.Car.wheels&lt;/code&gt;, but be careful. Changing the value of the instance variable &lt;code&gt;my_car.wheels&lt;/code&gt; will not change the value of the class variable &lt;code&gt;car.Car.wheels&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;lineno&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1966&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&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;n&quot;&gt;my_other_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;red&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;corvette&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1999&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;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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My car is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.color}&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;lineno&quot;&gt; 6 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;My car is yellow&lt;/span&gt;
&lt;span class=&quot;lineno&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;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;It has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.wheels}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; wheels&amp;quot;&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;go&quot;&gt;It has 0 wheels&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;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;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;My other car is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_other_car.color}&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;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;My other car is red&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;It has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_other_car.wheels}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; wheels&amp;quot;&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;go&quot;&gt;It has 0 wheels&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Change the class variable value&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wheels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&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;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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My car has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.wheels}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; wheels&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;go&quot;&gt;My car has 4 wheels&lt;/span&gt;
&lt;span class=&quot;lineno&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;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;My other car has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_other_car.wheels}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; wheels&amp;quot;&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;go&quot;&gt;My other car has 4 wheels&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23 &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;# Change the instance variable value for my_car&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wheels&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&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;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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My car has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.wheels}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; wheels&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;go&quot;&gt;My car has 5 wheels&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My other car has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_other_car.wheels}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; wheels&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;My other car has 4 wheels&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You define two &lt;code&gt;Car&lt;/code&gt; objects on lines 2 and 3:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;my_car&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;my_other_car&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At first, both of them have zero wheels. When you set the class variable using &lt;code&gt;car.Car.wheels = 4&lt;/code&gt; on line 16, both objects now have four wheels. However, when you set the instance variable using &lt;code&gt;my_car.wheels = 5&lt;/code&gt; on line 24, only that object is affected.&lt;/p&gt;
&lt;p&gt;This means that there are now two different copies of the &lt;code&gt;wheels&lt;/code&gt; attribute:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A class variable that applies to all &lt;code&gt;Car&lt;/code&gt; objects&lt;/li&gt;
&lt;li&gt;A specific instance variable applicable to the &lt;code&gt;my_car&lt;/code&gt; object only&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;It isn&amp;rsquo;t difficult to accidentally refer to the wrong one and introduce subtle bugs.&lt;/p&gt;
&lt;p&gt;Java&amp;rsquo;s equivalent to a class attribute is a &lt;code&gt;static&lt;/code&gt; attribute:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wheels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getWheels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&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;wheels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setWheels&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;wheels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Normally, you refer to static variables using the Java class name. You can refer to a static variable through a class instance like Python, but it&amp;rsquo;s not a best practice.&lt;/p&gt;
&lt;p&gt;Your Java class is getting long. One of the reasons why Java is more verbose than Python is the notion of public and private methods and attributes.&lt;/p&gt;
&lt;h3 id=&quot;public-and-private&quot;&gt;Public and Private&lt;/h3&gt;
&lt;p&gt;Java controls access to methods and attributes by differentiating between &lt;strong&gt;public&lt;/strong&gt; data and &lt;strong&gt;private&lt;/strong&gt; data.&lt;/p&gt;
&lt;p&gt;In Java, it is expected that attributes are declared as &lt;code&gt;private&lt;/code&gt;, or &lt;code&gt;protected&lt;/code&gt; if subclasses need direct access to them. This limits access to these attributes from code outside the class. To provide access to &lt;code&gt;private&lt;/code&gt; attributes, you declare &lt;code&gt;public&lt;/code&gt; methods which set and retrieve data in a controlled manner (more on that later).&lt;/p&gt;
&lt;p&gt;Recall from your Java class above that the &lt;code&gt;color&lt;/code&gt; variable was declared as &lt;code&gt;private&lt;/code&gt;. Therefore, this Java code will show a compilation error at the highlighted line:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;myCar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;blue&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Ford&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1972&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Paint the car&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;myCar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;red&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you don&amp;rsquo;t specify an access level, then the attribute defaults to &lt;strong&gt;package protected&lt;/strong&gt;, which limits access to classes in the same package. You have to mark the attribute as &lt;code&gt;public&lt;/code&gt; if you want this code to work. &lt;/p&gt;
&lt;p&gt;However, declaring public attributes is not considered a best practice in Java. You&amp;rsquo;re expected to declare attributes as &lt;code&gt;private&lt;/code&gt;, and use &lt;code&gt;public&lt;/code&gt; access methods, such as the &lt;code&gt;.getColor()&lt;/code&gt; and &lt;code&gt;.getModel()&lt;/code&gt; shown in the code.&lt;/p&gt;
&lt;p&gt;Python doesn&amp;rsquo;t have the same notion of &lt;code&gt;private&lt;/code&gt; or &lt;code&gt;protected&lt;/code&gt; data that Java does. Everything in Python is &lt;code&gt;public&lt;/code&gt;. This code works with your existing Python class just fine:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;blue&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Ford&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1972&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;# Paint the car&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;red&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Instead of &lt;code&gt;private&lt;/code&gt;, Python has a notion of a &lt;strong&gt;non-public&lt;/strong&gt; instance variable. Any variable which starts with an underscore character is defined to be non-public. This naming convention makes it harder to access a variable, but it&amp;rsquo;s only a naming convention, and you can still access the variable directly. &lt;/p&gt;
&lt;p&gt;Add the following line to your Python &lt;code&gt;Car&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;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;wheels&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;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;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&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;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&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;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&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;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&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;_cupholders&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can access the &lt;code&gt;._cupholders&lt;/code&gt; variable directly:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;car&lt;/span&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1969&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;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;It was built in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.year}&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;go&quot;&gt;It was built in 1969&lt;/span&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_car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1966&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;It was built in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.year}&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;go&quot;&gt;It was built in 1966&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;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;It has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car._cupholders}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; cupholders.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;go&quot;&gt;It has 6 cupholders.&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python lets you access &lt;code&gt;._cupholders&lt;/code&gt;, but IDEs such as &lt;a href=&quot;https://realpython.com/courses/python-development-visual-studio-code-setup-guide/&quot;&gt;VS Code&lt;/a&gt; may issue a warning through linters that support PEP 8. For more on PEP 8, read &lt;a href=&quot;https://realpython.com/python-pep8/&quot;&gt;How to Write Beautiful Python Code With PEP 8&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the code in VS Code, with a warning highlighted and displayed:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/oop_linting_vscode.b7a1cd7fd5ca.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/oop_linting_vscode.b7a1cd7fd5ca.png&quot; width=&quot;1550&quot; height=&quot;1161&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/oop_linting_vscode.b7a1cd7fd5ca.png&amp;amp;w=387&amp;amp;sig=e3d5c3cc040d87888f6defad5351e17c577b1f8e 387w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/oop_linting_vscode.b7a1cd7fd5ca.png&amp;amp;w=775&amp;amp;sig=79ece2096dcde055c998f33e9fbd51f220088ba8 775w, https://files.realpython.com/media/oop_linting_vscode.b7a1cd7fd5ca.png 1550w&quot; sizes=&quot;75vw&quot; alt=&quot;Linter highlighting a PEP8 issue in Python.&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Python further recognizes using double underscore characters in front of a variable to conceal an attribute in Python. When Python sees a double underscore variable, it changes the variable name internally to make it difficult to access directly. This mechanism &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/#method-names-and-instance-variables&quot;&gt;avoids accidents&lt;/a&gt; but still doesn&amp;rsquo;t make data impossible to access.&lt;/p&gt;
&lt;p&gt;To show this mechanism in action, change the Python &lt;code&gt;Car&lt;/code&gt; class again:&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;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;wheels&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;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;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&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;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&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;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&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;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&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;__cupholders&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, when you try to access the &lt;code&gt;.__cupholders&lt;/code&gt; variable, you see the following error:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;car&lt;/span&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1969&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;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;It was built in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.year}&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;go&quot;&gt;It was built in 1969&lt;/span&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_car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1966&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;It was built in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.year}&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;go&quot;&gt;It was built in 1966&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;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;It has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.__cupholders}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; cupholders.&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&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&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;gr&quot;&gt;AttributeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;&amp;#39;Car&amp;#39; object has no attribute &amp;#39;__cupholders&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So why doesn&amp;rsquo;t the &lt;code&gt;.__cupholders&lt;/code&gt; attribute exist?&lt;/p&gt;
&lt;p&gt;When Python sees an attribute with double underscores, it changes the attribute by prefixing the original name of the attribute with an underscore, followed by the class name. To use the attribute directly, you need to change the name you use as well:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;hll&quot;&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;It has &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car._Car__cupholders}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; cupholders&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;It has 6 cupholders&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you use double underscores to conceal an attribute from the user, Python changes the name in a well-documented manner. This means that a determined developer can still access the attribute directly.&lt;/p&gt;
&lt;p&gt;So if your Java attributes are declared &lt;code&gt;private&lt;/code&gt;, and your Python attributes are prefaced with double underscores, then how do you provide and control access to the data they store?&lt;/p&gt;
&lt;h3 id=&quot;access-control&quot;&gt;Access Control&lt;/h3&gt;
&lt;p&gt;In Java, you access &lt;code&gt;private&lt;/code&gt; attributes using &lt;strong&gt;setters&lt;/strong&gt; and &lt;strong&gt;getters&lt;/strong&gt;. To allow users to paint their cars, add the following code to your Java class:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since &lt;code&gt;.getColor()&lt;/code&gt; and &lt;code&gt;.setColor()&lt;/code&gt; are &lt;code&gt;public&lt;/code&gt;, anyone can call them to change or retrieve the car&amp;rsquo;s color. Java&amp;rsquo;s best practices of using &lt;code&gt;private&lt;/code&gt; attributes accessed with &lt;code&gt;public&lt;/code&gt; &lt;strong&gt;getters&lt;/strong&gt; and &lt;strong&gt;setters&lt;/strong&gt; is one of the reasons why Java code tends to be more verbose than Python.&lt;/p&gt;
&lt;p&gt;As you saw above, you access attributes directly in Python. Since everything is &lt;code&gt;public&lt;/code&gt;, you can access anything at any time from anywhere. You set and get attribute values directly by referring to their names. You can even delete attributes in Python, which isn&amp;rsquo;t possible in Java:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1969&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My car was built in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.year}&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;go&quot;&gt;My car was built in 1969&lt;/span&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_car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1966&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;It was built in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.year}&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;go&quot;&gt;It was built in 1966&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;del&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;It was built in &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.year}&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;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;Car&amp;#39; object has no attribute &amp;#39;year&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, there are times you may want to control access to an attribute. In that case, you can use Python properties.&lt;/p&gt;
&lt;p&gt;In Python, &lt;strong&gt;properties&lt;/strong&gt; provide controllable access to class attributes using Python decorator syntax. (You can learn about decorators in the video course &lt;a href=&quot;https://realpython.com/courses/python-decorators-101/&quot;&gt;Python Decorators 101&lt;/a&gt;.) Properties allow functions to be declared in Python classes that are analogous to Java getter and setter methods, with the added bonus of allowing you to delete attributes as well.&lt;/p&gt;
&lt;p&gt;You can see how properties work by adding one to your &lt;code&gt;Car&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;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&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;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;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &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;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &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;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &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;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &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;_voltage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nd&quot;&gt;@property&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;voltage&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&gt;&lt;span class=&quot;lineno&quot;&gt;10 &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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_voltage&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nd&quot;&gt;@voltage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setter&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;voltage&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;volts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;hll&quot;&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;Warning: this can cause problems!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;15 &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;_voltage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;volts&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nd&quot;&gt;@voltage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deleter&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;voltage&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&gt;&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;&lt;span class=&quot;hll&quot;&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;Warning: the radio will stop working!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;del&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;_voltage&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you expand the notion of the &lt;code&gt;Car&lt;/code&gt; to include electric vehicles. You declare the &lt;code&gt;._voltage&lt;/code&gt; attribute to hold the battery voltage on line 6.&lt;/p&gt;
&lt;p&gt;To provide controlled access, you define a function called &lt;code&gt;voltage()&lt;/code&gt; to return the private value on lines 9 and 10. By using the &lt;code&gt;@property&lt;/code&gt; decoration, you mark it as a getter that anyone can access directly.&lt;/p&gt;
&lt;p&gt;Similarly, you define a setter function on lines 13 to 15, also called &lt;code&gt;voltage()&lt;/code&gt;. However, you decorate this function with &lt;code&gt;@voltage.setter&lt;/code&gt;. Lastly, you use &lt;code&gt;@voltage.deleter&lt;/code&gt; to decorate a third &lt;code&gt;voltage()&lt;/code&gt; on lines 18 to 20, which allows controlled deletion of the attribute.&lt;/p&gt;
&lt;p&gt;The names of the decorated functions are all the same, indicating they control access to the same attribute. The function names also become the name of the attribute you use to access the value. Here&amp;rsquo;s how these properties work in practice:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;lineno&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1969&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &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;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;My car uses &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.voltage}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; volts&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;My car uses 12 volts&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;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;my_car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voltage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;Warning: this can cause problems!&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &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;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;My car now uses &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.voltage}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; volts&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;My car now uses 6 volts&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &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;k&quot;&gt;del&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;my_car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voltage&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;go&quot;&gt;Warning: the radio will stop working!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that you use &lt;code&gt;.voltage&lt;/code&gt; in the highlighted lines above, not &lt;code&gt;._voltage&lt;/code&gt;. This tells Python to use the property functions you defined:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;When you print the value of &lt;code&gt;my_car.voltage&lt;/code&gt; on line 4, Python calls &lt;code&gt;.voltage()&lt;/code&gt; decorated with &lt;code&gt;@property&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When you assign a value to &lt;code&gt;my_car.voltage&lt;/code&gt; on line 7, Python calls &lt;code&gt;.voltage()&lt;/code&gt; decorated with &lt;code&gt;@voltage.setter&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;When you delete &lt;code&gt;my_car.voltage&lt;/code&gt; on line 13, Python calls &lt;code&gt;.voltage()&lt;/code&gt; decorated with &lt;code&gt;@voltage.deleter&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;@property&lt;/code&gt;, &lt;code&gt;@.setter&lt;/code&gt;, and &lt;code&gt;@.deleter&lt;/code&gt; decorations make it possible to control access to attributes without requiring users to use different methods. You can even make attributes appear to be read-only properties by omitting the &lt;code&gt;@.setter&lt;/code&gt; and &lt;code&gt;@.deleter&lt;/code&gt; decorated functions.&lt;/p&gt;
&lt;h3 id=&quot;self-and-this&quot;&gt;&lt;code&gt;self&lt;/code&gt; and &lt;code&gt;this&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;In Java, a class refers to itself with the &lt;code&gt;this&lt;/code&gt; reference:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;this&lt;/code&gt; is implicit in Java code: it doesn&amp;rsquo;t normally need to be written, unless there may be confusion between two variables with the same name. &lt;/p&gt;
&lt;p&gt;You can write the same setter this way:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;newColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since &lt;code&gt;Car&lt;/code&gt; has an attribute named &lt;code&gt;.color&lt;/code&gt;, and there isn&amp;rsquo;t another variable in scope with the same name, a reference to that name works. We used &lt;code&gt;this&lt;/code&gt; in the first example to differentiate between the attribute and parameter both named &lt;code&gt;color&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In Python, the keyword &lt;code&gt;self&lt;/code&gt; serves a similar purpose. It&amp;rsquo;s how you refer to member variables, but unlike Java&amp;rsquo;s &lt;code&gt;this&lt;/code&gt;, it&amp;rsquo;s &lt;em&gt;required&lt;/em&gt; if you want to create or refer to a member attribute:&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;Car&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;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&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;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&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;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&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;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&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;_voltage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&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;voltage&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;hll&quot;&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;_voltage&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python requires each &lt;code&gt;self&lt;/code&gt; in the code above. Each one either creates or refers to the attributes. If you omit them, then Python will create a local variable instead of an attribute.&lt;/p&gt;
&lt;p&gt;The difference between how you use &lt;code&gt;self&lt;/code&gt; and &lt;code&gt;this&lt;/code&gt; in Python and Java is due to underlying differences between the two languages and how they name variables and attributes.&lt;/p&gt;
&lt;h2 id=&quot;methods-and-functions&quot;&gt;Methods and Functions&lt;/h2&gt;
&lt;p&gt;This difference between Python vs Java is, simply put, that Python has functions, and Java doesn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;In Python, the following code is perfectly fine (and very common):&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;say_hi&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;s2&quot;&gt;&amp;quot;Hi!&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;say_hi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Hi!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can call &lt;code&gt;say_hi()&lt;/code&gt; from anywhere it&amp;rsquo;s visible. This function has no reference to &lt;code&gt;self&lt;/code&gt;, which indicates that it&amp;rsquo;s a global function, not a class function. It can&amp;rsquo;t alter or store any data in any classes but can use local and global variables.&lt;/p&gt;
&lt;p&gt;In contrast, every line of Java code you write belongs to a class. Functions can&amp;rsquo;t exist outside of a class, and by definition, all Java functions are methods. In Java, the closest you can get to a pure function is by using a static method:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Utils&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SayHi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Hi!&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;Utils.SayHi()&lt;/code&gt; is callable from anywhere without first creating an instance of &lt;code&gt;Utils&lt;/code&gt;. Since you can call &lt;code&gt;SayHi()&lt;/code&gt; without creating an object first, the &lt;code&gt;this&lt;/code&gt; reference doesn&amp;rsquo;t exist. However, this is still not a function in the sense that &lt;code&gt;say_hi()&lt;/code&gt; is in Python.&lt;/p&gt;
&lt;h2 id=&quot;inheritance-and-polymorphism&quot;&gt;Inheritance and Polymorphism&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)&quot;&gt;Inheritance&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Polymorphism_(computer_science)&quot;&gt;polymorphism&lt;/a&gt; are two fundamental concepts in object-oriented programming.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)&quot;&gt;Inheritance&lt;/a&gt; allows objects to derive attributes and functionality from other objects, creating a hierarchy moving from more general objects to more specific. For example, a &lt;code&gt;Car&lt;/code&gt; and a &lt;code&gt;Boat&lt;/code&gt; are both specific types of &lt;code&gt;Vehicles&lt;/code&gt;. Objects can inherit their behavior from a single parent object or multiple parent objects, and are referred to as child objects when they do.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Polymorphism_(computer_science)&quot;&gt;Polymorphism&lt;/a&gt; allows two or more objects to behave like one another, which allows them to be used interchangeably. For example, if a method or function knows how to paint a &lt;code&gt;Vehicle&lt;/code&gt; object, then it can also paint a &lt;code&gt;Car&lt;/code&gt; or &lt;code&gt;Boat&lt;/code&gt; object, since they inherit their data and behavior from the &lt;code&gt;Vehicle&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;These fundamental OOP concepts are implemented quite differently in Python vs Java.&lt;/p&gt;
&lt;h3 id=&quot;inheritance&quot;&gt;Inheritance&lt;/h3&gt;
&lt;p&gt;Python supports multiple inheritance, or creating classes that inherit behavior from more than one parent class.&lt;/p&gt;
&lt;p&gt;To see how this works, update the &lt;code&gt;Car&lt;/code&gt; class by breaking it into two categories, one for vehicles, and one for devices that use electricity:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vehicle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&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;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&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;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&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;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&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&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;_voltage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Vehicle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&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;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;Vehicle&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;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;Device&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&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;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&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;voltage&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;_voltage&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@voltage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setter&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;voltage&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;volts&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;Warning: this can cause problems!&amp;quot;&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;_voltage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;volts&lt;/span&gt;

    &lt;span class=&quot;nd&quot;&gt;@voltage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;deleter&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;voltage&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;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;Warning: the radio will stop working!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;del&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;_voltage&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A &lt;code&gt;Vehicle&lt;/code&gt; is defined as having &lt;code&gt;.color&lt;/code&gt; and &lt;code&gt;.model&lt;/code&gt; attributes. Then, a &lt;code&gt;Device&lt;/code&gt; is defined to have a &lt;code&gt;._voltage&lt;/code&gt; attribute. Since the original &lt;code&gt;Car&lt;/code&gt; object had these three attributes, it can be redefined to inherit both the &lt;code&gt;Vehicle&lt;/code&gt; and &lt;code&gt;Device&lt;/code&gt; classes. The &lt;code&gt;color&lt;/code&gt;, &lt;code&gt;model&lt;/code&gt;, and &lt;code&gt;_voltage&lt;/code&gt; attributes will be part of the new &lt;code&gt;Car&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;In the &lt;code&gt;.__init__()&lt;/code&gt; for &lt;code&gt;Car&lt;/code&gt;, you call the &lt;code&gt;.__init__()&lt;/code&gt; methods for both of the parent classes to make sure everything is initialized properly. Once done, you can add any other functionality you want to your &lt;code&gt;Car&lt;/code&gt;. In this case, you add a &lt;code&gt;.year&lt;/code&gt; attribute specific to &lt;code&gt;Car&lt;/code&gt; objects, and getter and setter methods for &lt;code&gt;.voltage&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Functionally, the new &lt;code&gt;Car&lt;/code&gt; class behaves as it always has. You create and use &lt;code&gt;Car&lt;/code&gt; objects just as before:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;car&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1969&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My car is &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.color}&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;go&quot;&gt;My car is yellow&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My car uses &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.voltage}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; volts&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;My car uses 12 volts&lt;/span&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_car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;voltage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Warning: this can cause problems!&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;My car now uses &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{my_car.voltage}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; volts&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;My car now uses 6 volts&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Java, on the other hand, only supports single inheritance, which means classes in Java can inherit data and behavior from only a single parent class. However, Java objects can inherit behavior from many different &lt;a href=&quot;https://docs.oracle.com/javase/tutorial/java/concepts/interface.html&quot;&gt;interfaces&lt;/a&gt;. Interfaces provide a group of related methods an object must implement, and allow multiple child classes to behave similarly.&lt;/p&gt;
&lt;p&gt;To see this in action, split the Java &lt;code&gt;Car&lt;/code&gt; class into a parent class and an &lt;code&gt;interface&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Vehicle&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Vehicle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&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;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&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;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getVoltage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Vehicle&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;implements&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;voltage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;kd&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;voltage&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nd&quot;&gt;@Override&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getVoltage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&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;voltage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getYear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Remember that each &lt;code&gt;class&lt;/code&gt; and &lt;code&gt;interface&lt;/code&gt; needs to live in its own file.&lt;/p&gt;
&lt;p&gt;As you did with Python, you create a new class called &lt;code&gt;Vehicle&lt;/code&gt; to hold the more general vehicle related data and functionality. However, to add the &lt;code&gt;Device&lt;/code&gt; functionality, you need to create an &lt;code&gt;interface&lt;/code&gt; instead. This &lt;code&gt;interface&lt;/code&gt; defines a single method to return the voltage of the &lt;code&gt;Device&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Redefining the &lt;code&gt;Car&lt;/code&gt; class requires you to inherit from &lt;code&gt;Vehicle&lt;/code&gt; using &lt;code&gt;extend&lt;/code&gt;, and implement the &lt;code&gt;Device&lt;/code&gt; interface using &lt;code&gt;implements&lt;/code&gt;. In the constructor, you call the parent class constructor using the built-in &lt;code&gt;super()&lt;/code&gt;. Since there is only one parent class, it can only refer to the &lt;code&gt;Vehicle&lt;/code&gt; constructor. To implement the &lt;code&gt;interface&lt;/code&gt;, you write &lt;code&gt;getVoltage()&lt;/code&gt; using the &lt;code&gt;@Override&lt;/code&gt; annotation.&lt;/p&gt;
&lt;p&gt;Rather than getting code reuse from &lt;code&gt;Device&lt;/code&gt; as Python did, Java requires you to implement the same functionality in every class that implements the &lt;code&gt;interface&lt;/code&gt;. Interfaces only define the methods&amp;mdash;they cannot define instance data or implementation details.&lt;/p&gt;
&lt;p&gt;So why is this the case for Java? It all comes down to types.&lt;/p&gt;
&lt;h3 id=&quot;types-and-polymorphism&quot;&gt;Types and Polymorphism&lt;/h3&gt;
&lt;p&gt;Java&amp;rsquo;s strict type checking is what drives its &lt;code&gt;interface&lt;/code&gt; design.&lt;/p&gt;
&lt;p&gt;Every &lt;code&gt;class&lt;/code&gt; and &lt;code&gt;interface&lt;/code&gt; in Java is a type. Therefore, if two Java objects implement the same &lt;code&gt;interface&lt;/code&gt;, then they are considered to be the same type with respect to that &lt;code&gt;interface&lt;/code&gt;. This mechanism allows different classes to be used interchangeably, which is the definition of polymorphism.&lt;/p&gt;
&lt;p&gt;You can implement device charging for your Java objects by creating a &lt;code&gt;.charge()&lt;/code&gt; that takes a &lt;code&gt;Device&lt;/code&gt; to charge. Any object that implements the &lt;code&gt;Device&lt;/code&gt; interface can be passed to &lt;code&gt;.charge()&lt;/code&gt;. This also means that classes that do not implement &lt;code&gt;Device&lt;/code&gt; will generate a compilation error.&lt;/p&gt;
&lt;p&gt;Create the following class in a file called &lt;code&gt;Rhino.java&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rhino&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you can create a new &lt;code&gt;Main.java&lt;/code&gt; to implement &lt;code&gt;.charge()&lt;/code&gt; and explore how &lt;code&gt;Car&lt;/code&gt; and &lt;code&gt;Rhino&lt;/code&gt; objects differ:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
       &lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getVoltage&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&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;args&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1969&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Rhino&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rhino&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rhino&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rhino&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here is what you should see when you try to build this code:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Information:2019-02-02 15:20 - Compilation completed with 
    1 error and 0 warnings in 4 s 395 ms
Main.java
&lt;span class=&quot;hll&quot;&gt;Error:(43, 11) java: incompatible types: Rhino cannot be converted to Device
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since the &lt;code&gt;Rhino&lt;/code&gt; class doesn&amp;rsquo;t implement the &lt;code&gt;Device&lt;/code&gt; interface, it can&amp;rsquo;t be passed into &lt;code&gt;.charge()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;In contrast to Java&amp;rsquo;s strict variable typing, Python uses a concept called &lt;strong&gt;duck typing&lt;/strong&gt;, which in basic terms means that if a variable &amp;ldquo;walks like a duck and quacks like a duck, then it&amp;rsquo;s a duck.&amp;rdquo; Instead of identifying objects by type, Python examines their behavior. You can learn more about the Python type system, and duck typing, in &lt;a href=&quot;https://realpython.com/python-type-checking&quot;&gt;The Ultimate Guide to Python Type Checking&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can explore duck typing by implementing similar device charging capabilities for your Python &lt;code&gt;Device&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&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;nb&quot;&gt;hasattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;device&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;_voltage&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;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;Charging a &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{device._voltage}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; volt device&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;else&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;I can&amp;#39;t charge a &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{device.__class__.__name__}&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;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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Phone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Device&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Rhino&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;n&quot;&gt;my_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1966&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;my_phone&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Phone&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_rhino&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Rhino&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;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Charging a 12 volt device&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_phone&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Charging a 12 volt device&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;charge&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_rhino&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;I can&amp;#39;t charge a Rhino&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;charge()&lt;/code&gt; must check for the existence of the &lt;code&gt;._voltage&lt;/code&gt; attribute in the object it&amp;rsquo;s passed. Since the &lt;code&gt;Device&lt;/code&gt; class defines this attribute, any class that inherits from it (such as &lt;code&gt;Car&lt;/code&gt; and &lt;code&gt;Phone&lt;/code&gt;) will have this attribute, and will therefore show they are charging properly. Classes that do not inherit from &lt;code&gt;Device&lt;/code&gt; (like &lt;code&gt;Rhino&lt;/code&gt;) may not have this attribute, and will not be able to charge (which is good, since charging rhinos can be dangerous).&lt;/p&gt;
&lt;h3 id=&quot;default-methods&quot;&gt;Default Methods&lt;/h3&gt;
&lt;p&gt;All Java classes descend from the &lt;code&gt;Object&lt;/code&gt; class, which contains a set of methods every other class inherits. Subclasses can either override them or keep the defaults. The &lt;code&gt;Object&lt;/code&gt; class defines the following methods:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;    
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hashCode&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;    
    &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;    
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By default, &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-&quot;&gt;&lt;code&gt;equals()&lt;/code&gt;&lt;/a&gt; compares the addresses of the current &lt;code&gt;Object&lt;/code&gt; with a second &lt;code&gt;Object&lt;/code&gt; passed in, and &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--&quot;&gt;&lt;code&gt;hashcode()&lt;/code&gt;&lt;/a&gt; computes a unique identifier that also uses the address of the current &lt;code&gt;Object&lt;/code&gt;. These methods are used in many different contexts in Java. For example, utility classes, such as collections that sort objects based on value, need both of them.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#toString--&quot;&gt;&lt;code&gt;toString()&lt;/code&gt;&lt;/a&gt; returns a &lt;code&gt;String&lt;/code&gt; representation of the &lt;code&gt;Object&lt;/code&gt;. By default, this is the name of the class and the address. This method is called automatically when an &lt;code&gt;Object&lt;/code&gt; is passed to a method that requires a &lt;code&gt;String&lt;/code&gt; argument, such as &lt;code&gt;System.out.println()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1969&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Running this code will use the default &lt;code&gt;.toString()&lt;/code&gt; to show the &lt;code&gt;car&lt;/code&gt; object:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Car@61bbe9ba
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Not very useful, right? You can improve this by overriding the default &lt;code&gt;.toString()&lt;/code&gt;. Add this method to your Java &lt;code&gt;Car&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;toString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;Car: &amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getColor&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&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;getModel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;s&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;getYear&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, when you run the same sample code, you&amp;rsquo;ll see the following:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Car: yellow : Beetle : 1969
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python provides similar functionality with a set of common &lt;a href=&quot;https://dbader.org/blog/python-dunder-methods&quot;&gt;dunder (short for &amp;ldquo;double underscore&amp;rdquo;) methods&lt;/a&gt;. Every Python class inherits these methods, and you can override them to modify their behavior.&lt;/p&gt;
&lt;p&gt;For string representations of an object, Python provides &lt;code&gt;__repr__()&lt;/code&gt; and &lt;code&gt;__str__()&lt;/code&gt;, which you can learn about in &lt;a href=&quot;https://realpython.com/courses/pythonic-oop-string-conversion-__repr__-vs-__str__/&quot;&gt;Pythonic OOP String Conversion: &lt;code&gt;__repr__&lt;/code&gt; vs &lt;code&gt;__str__&lt;/code&gt;&lt;/a&gt;. The unambiguous representation of an object is returned by &lt;code&gt;__repr__()&lt;/code&gt;, while &lt;code&gt;__str__()&lt;/code&gt; returns a human readable representation. These are roughly analogous to &lt;code&gt;.hashcode()&lt;/code&gt; and &lt;code&gt;.toString()&lt;/code&gt; in Java. &lt;/p&gt;
&lt;p&gt;Like Java, Python provides default implementations of these dunder methods:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1966&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;print&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;n&quot;&gt;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;car.Car object at 0x7fe4ca154f98&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;nb&quot;&gt;print&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;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;car.Car object at 0x7fe4ca154f98&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can improve this output by overriding &lt;code&gt;.__str__()&lt;/code&gt;, adding this to your Python &lt;code&gt;Car&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;__str__&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;f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Car &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{self.color}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; : &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{self.model}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; : &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{self.year}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This gives you a much nicer result:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1966&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;print&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;n&quot;&gt;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;car.Car object at 0x7f09e9a7b630&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;nb&quot;&gt;print&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;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Car yellow : Beetle : 1966&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Overriding the dunder method gave us a more readable representation of your &lt;code&gt;Car&lt;/code&gt;. You may want to override the &lt;code&gt;.__repr__()&lt;/code&gt; as well, as it is often useful for debugging.&lt;/p&gt;
&lt;p&gt;Python offers &lt;a href=&quot;https://docs.python.org/3/reference/datamodel.html#special-method-names&quot;&gt;a lot more dunder methods&lt;/a&gt;. Using dunder methods, you can define your object&amp;rsquo;s behavior during iteration, comparison, addition, or making an object callable directly, among other things.&lt;/p&gt;
&lt;h3 id=&quot;operator-overloading&quot;&gt;Operator Overloading&lt;/h3&gt;
&lt;p&gt;Operator overloading refers to redefining how Python operators work when operating on user-defined objects. Python&amp;rsquo;s dunder methods allow you to implement operator overloading, something that Java doesn&amp;rsquo;t offer at all.&lt;/p&gt;
&lt;p&gt;Modify your Python &lt;code&gt;Car&lt;/code&gt; class with the following additional dunder methods:&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;Car&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;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&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;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;color&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;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;model&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;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__str__&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;f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Car &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{self.color}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; : &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{self.model}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; : &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{self.year}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&lt;/span&gt;

&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__eq__&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;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__lt__&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;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&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;Car&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;color&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&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;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; 
&lt;/span&gt;&lt;span class=&quot;hll&quot;&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&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;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;year&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The table below shows the relationship between these dunder methods and the Python operators they represent:&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;Dunder Method&lt;/th&gt;
&lt;th&gt;Operator&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;__eq__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;==&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Do these &lt;code&gt;Car&lt;/code&gt; objects have the same year?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;__lt__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Which &lt;code&gt;Car&lt;/code&gt; is an earlier model?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;__add__&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Add two &lt;code&gt;Car&lt;/code&gt; objects in a nonsensical way&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;When Python sees an expression containing objects, it calls any dunder methods defined that correspond to operators in the expression. The code below uses these new overloaded arithmetic operators on a couple of &lt;code&gt;Car&lt;/code&gt; objects:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1966&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;your_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;red&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Corvette&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1967&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;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;your_car&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;print&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;your_car&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;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;my_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;your_car&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;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;my_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;your_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Car yellowred : BeetleCorvette : 3933 &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There are many more operators you can overload using &lt;a href=&quot;https://docs.python.org/3/reference/datamodel.html#special-method-names&quot;&gt;dunder methods&lt;/a&gt;. They offer a way to enrich your object&amp;rsquo;s behavior in a way that Java&amp;rsquo;s common base class default methods don&amp;rsquo;t.&lt;/p&gt;
&lt;h2 id=&quot;reflection&quot;&gt;Reflection&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Reflection_(computer_programming)&quot;&gt;Reflection&lt;/a&gt; refers to examining an object or class from within the object or class. Both Java and Python offer ways to explore and examine the attributes and methods in a class.&lt;/p&gt;
&lt;h3 id=&quot;examining-an-objects-type&quot;&gt;Examining an Object&amp;rsquo;s Type&lt;/h3&gt;
&lt;p&gt;Both languages have ways to test or check an object&amp;rsquo;s type.&lt;/p&gt;
&lt;p&gt;In Python, you use &lt;code&gt;type()&lt;/code&gt; to display the type of a variable, and &lt;code&gt;isinstance()&lt;/code&gt; to determine if a given variable is an instance or child of a specific class:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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_car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1966&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;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;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;class &amp;#39;car.Car&amp;#39;&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;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&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;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&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;print&lt;/span&gt;&lt;span class=&quot;p&quot;&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;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Device&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;In Java, you query the object for its type using &lt;code&gt;.getClass()&lt;/code&gt;, and use the &lt;code&gt;instanceof&lt;/code&gt; operator to check for a specific class:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;yellow&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;beetle&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1969&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;System&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;car&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;instanceof&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code outputs the following:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;class com.realpython.Car
true
&lt;/pre&gt;&lt;/div&gt;

&lt;h3 id=&quot;examining-an-objects-attributes&quot;&gt;Examining an Object&amp;rsquo;s Attributes&lt;/h3&gt;
&lt;p&gt;In Python, you can view every attribute and function contained in any object (including all the dunder methods) using &lt;code&gt;dir()&lt;/code&gt;. To get the specific details of a given attribute or function, use &lt;code&gt;getattr()&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;nb&quot;&gt;dir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;_Car__cupholders&amp;#39;, &amp;#39;__add__&amp;#39;, &amp;#39;__class__&amp;#39;, &amp;#39;__delattr__&amp;#39;, &amp;#39;__dict__&amp;#39;, &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;__dir__&amp;#39;, &amp;#39;__doc__&amp;#39;, &amp;#39;__eq__&amp;#39;, &amp;#39;__format__&amp;#39;, &amp;#39;__ge__&amp;#39;, &amp;#39;__getattribute__&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;__gt__&amp;#39;, &amp;#39;__hash__&amp;#39;, &amp;#39;__init__&amp;#39;, &amp;#39;__init_subclass__&amp;#39;, &amp;#39;__le__&amp;#39;, &amp;#39;__lt__&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;__module__&amp;#39;, &amp;#39;__ne__&amp;#39;, &amp;#39;__new__&amp;#39;, &amp;#39;__reduce__&amp;#39;, &amp;#39;__reduce_ex__&amp;#39;, &amp;#39;__repr__&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;__setattr__&amp;#39;, &amp;#39;__sizeof__&amp;#39;, &amp;#39;__str__&amp;#39;, &amp;#39;__subclasshook__&amp;#39;, &amp;#39;__weakref__&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;_voltage&amp;#39;, &amp;#39;color&amp;#39;, &amp;#39;model&amp;#39;, &amp;#39;voltage&amp;#39;, &amp;#39;wheels&amp;#39;, &amp;#39;year&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;nb&quot;&gt;getattr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;__format__&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;lt;built-in method __format__ of Car object at 0x7fb4c10f5438&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Java has similar capabilities, but the language&amp;rsquo;s access control and type safety make it more complicated to retrieve. &lt;/p&gt;
&lt;p&gt;&lt;code&gt;.getFields()&lt;/code&gt; retrieves a list of all publicly accessible attributes. However, since none of the attributes of &lt;code&gt;Car&lt;/code&gt; are &lt;code&gt;public&lt;/code&gt;, this code returns an empty array:&lt;/p&gt;
&lt;div class=&quot;highlight java&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Field&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;car&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getFields&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Java treats attributes and methods as separate entities, so &lt;code&gt;public&lt;/code&gt; methods are retrieved using &lt;code&gt;.getDeclaredMethods()&lt;/code&gt;. Since &lt;code&gt;public&lt;/code&gt; attributes will have a corresponding &lt;code&gt;.get&lt;/code&gt; method, one way to discover if a class contains a specific property might look like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;.getDeclaredMethods()&lt;/code&gt; to generate an array of all the methods.&lt;/li&gt;
&lt;li&gt;Loop through all the methods returned:&lt;ul&gt;
&lt;li&gt;For each method discovered, return true if the method:&lt;ul&gt;
&lt;li&gt;Begins with the word &lt;code&gt;get&lt;/code&gt; OR accepts zero arguments&lt;/li&gt;
&lt;li&gt;AND doesn&amp;rsquo;t return &lt;code&gt;void&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;AND includes the name of the property&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Otherwise, return false.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s a quick-and-dirty example:&lt;/p&gt;
&lt;div class=&quot;highlight java&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;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;getProperty&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;String&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;n&quot;&gt;Object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;throws&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Exception&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&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;Method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;declaredMethods&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClass&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getDeclaredMethods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;declaredMethods&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isGetter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;contains&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;toUpperCase&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;              &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;    &lt;span class=&quot;o&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;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Helper function to get if the method is a getter method&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;boolean&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;isGetter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Method&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getName&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;startsWith&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;get&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;         &lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getParameterCount&lt;/span&gt;&lt;span class=&quot;o&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;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; 
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;        &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getReturnType&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;class&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;          &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &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;o&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;getProperty()&lt;/code&gt; is your entry point. Call this with the name of an attribute and an object. It returns &lt;code&gt;true&lt;/code&gt; if the property is found, and &lt;code&gt;false&lt;/code&gt; if not.&lt;/p&gt;
&lt;h3 id=&quot;calling-methods-through-reflection&quot;&gt;Calling Methods Through Reflection&lt;/h3&gt;
&lt;p&gt;Both Java and Python provide mechanisms to call methods through reflection.&lt;/p&gt;
&lt;p&gt;In the Java example above, instead of simply returning &lt;code&gt;true&lt;/code&gt; if the property was found, you could call the method directly. Recall that &lt;code&gt;getDeclaredMethods()&lt;/code&gt; returns an array of &lt;code&gt;Method&lt;/code&gt; objects. The &lt;code&gt;Method&lt;/code&gt; object itself has a method called &lt;code&gt;.invoke()&lt;/code&gt;, which will call the &lt;code&gt;Method&lt;/code&gt;. Instead of returning &lt;code&gt;true&lt;/code&gt; when the correct method is found on line 7 above, you can return &lt;code&gt;method.invoke(object)&lt;/code&gt; instead.&lt;/p&gt;
&lt;p&gt;This capability exists in Python as well. However, since Python doesn&amp;rsquo;t differentiate between functions and attributes, you have to look specifically for entries that are &lt;code&gt;callable&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;method_name&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&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;n&quot;&gt;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;hll&quot;&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;callable&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;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&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;method_name&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;__add__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__class__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__delattr__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__dir__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__eq__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__format__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__ge__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__getattribute__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__gt__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__init__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__init_subclass__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__le__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__lt__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__ne__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__new__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__reduce__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__reduce_ex__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__repr__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__setattr__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__sizeof__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__str__&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__subclasshook__&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Python methods are simpler to manage and call than in Java. Adding the &lt;code&gt;()&lt;/code&gt; operator (and any required arguments) is all you need to do.&lt;/p&gt;
&lt;p&gt;The code below will find an object&amp;rsquo;s &lt;code&gt;.__str__()&lt;/code&gt; and call it through reflection:&lt;/p&gt;
&lt;div class=&quot;highlight python repl&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;method_name&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&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;n&quot;&gt;my_car&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;attr&lt;/span&gt; &lt;span class=&quot;o&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;my_car&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;method_name&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;callable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attr&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;method_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;__str__&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;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;attr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Car yellow : Beetle : 1966&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, every attribute returned by &lt;code&gt;dir()&lt;/code&gt; is checked. You get the actual attribute object using &lt;code&gt;getattr()&lt;/code&gt;, and check if it&amp;rsquo;s a callable function using &lt;code&gt;callable()&lt;/code&gt;. If so, you then check if its name is &lt;code&gt;__str__()&lt;/code&gt;, and then call it.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Throughout the course of this article, you learned how object-oriented principles differ in Python vs Java. As you read, you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Built a basic class in both Java and Python&lt;/li&gt;
&lt;li&gt;Explored how object attributes work in Python vs Java&lt;/li&gt;
&lt;li&gt;Compared and contrasted Java methods and Python functions&lt;/li&gt;
&lt;li&gt;Discovered inheritance and polymorphism mechanisms in both languages&lt;/li&gt;
&lt;li&gt;Investigated reflection across Python vs Java&lt;/li&gt;
&lt;li&gt;Applied everything in a complete class implementation in both languages&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you want to learn more about OOP in Python, be sure to read &lt;a href=&quot;https://realpython.com/python3-object-oriented-programming/&quot;&gt;Object-Oriented Programming (OOP) in Python 3&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Understanding the differences in Python vs Java when handling objects, and the syntax choices each language makes, will help you apply best practices and make your next project smoother.&lt;/p&gt;
&lt;p&gt;In order to compare some concrete examples side by side, you can download our sample code to get the complete commented object definitions for the Java &lt;code&gt;Car&lt;/code&gt;, &lt;code&gt;Device&lt;/code&gt;, and &lt;code&gt;Vehicle&lt;/code&gt; classes, as well as the complete commented definitions for the Python &lt;code&gt;Car&lt;/code&gt; and &lt;code&gt;Vehicle&lt;/code&gt; classes:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Sample Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/optins/view/oop-python-vs-java/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-oop-python-vs-java&quot; data-focus=&quot;false&quot;&gt;Click here to download the commented sample object definitions and source code&lt;/a&gt; for the Java and Python objects in this article.&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>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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 set up Continuous Integration for your Python project to automatically create environments, install dependencies, and run tests. You&amp;rsquo;ll learn how to work with GitHub, CircleCI, and PyTest.&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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 repl&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>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>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>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>
  

</feed>
