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

  
    <entry>
      <title>Thinking Recursively in Python</title>
      <id>https://realpython.com/courses/thinking-recursively-python/</id>
      <link href="https://realpython.com/courses/thinking-recursively-python/"/>
      <updated>2019-11-12T14:00:00+00:00</updated>
      <summary>In this course, you&#39;ll learn how to work with recursion in your Python programs by mastering concepts such as recursive functions and recursive data structures.</summary>
      <content type="html">
        &lt;p&gt;In this course, you&amp;rsquo;ll learn about &lt;strong&gt;recursion&lt;/strong&gt;. Recursion is a powerful tool you can use to solve a problem that can be broken down into smaller variations of itself. You can create very complex recursive algorithms with only a few lines of code.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&amp;rsquo;ll cover:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What recursion is&lt;/li&gt;
&lt;li&gt;How to define a recursive function&lt;/li&gt;
&lt;li&gt;How practical examples of recursive functions work&lt;/li&gt;
&lt;li&gt;How to maintain state&lt;/li&gt;
&lt;li&gt;How to optimize recursion&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>PyCon Africa 2019 (Recap)</title>
      <id>https://realpython.com/pycon-africa-2019-recap/</id>
      <link href="https://realpython.com/pycon-africa-2019-recap/"/>
      <updated>2019-11-11T14:00:00+00:00</updated>
      <summary>The first-ever pan-African PyCon took place in Accra, Ghana in August 2019 and brought together Pythonistas from 26 different countries. The conference had 33 talks and 8 workshops covering topics such as machine learning, web development, robotics, and community building.</summary>
      <content type="html">
        &lt;p&gt;&lt;a href=&quot;https://africa.pycon.org/&quot;&gt;PyCon Africa&lt;/a&gt; was a wonderful, inspiring, and technically enlightening conference that took place in Accra, Ghana from August 6 to 10, 2019 at the University of Ghana. This conference was the very first &lt;strong&gt;pan-African conference&lt;/strong&gt; for Python developers and was attended by 323 Pythonistas from 26 different countries. Most of the attendees traveled from countries around Africa, and a number of speakers came from the US, the Netherlands, Germany, Brazil, and Italy.&lt;/p&gt;
&lt;p&gt;Python is becoming more and more adopted all across the globe. In Africa, Python is earning a special place for itself, where it&amp;rsquo;s used extensively for &lt;a href=&quot;https://realpython.com/tutorials/web-dev/&quot;&gt;web development&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/tutorials/data-science/&quot;&gt;data science&lt;/a&gt;. African businesses are looking for developers with Python skills in these areas, and having a &lt;strong&gt;PyCon in Africa&lt;/strong&gt; provides a foundation to help support African programmers.&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;what-happened-at-pycon-africa&quot;&gt;What Happened at PyCon Africa&lt;/h2&gt;
&lt;p&gt;On the day before the main conference started, attendees took some time to settle in. Those who were just getting started with Python attended a Beginners Day Session led by Joey Darko to help them set up their computers for Python development. I joined another group of international travelers on a tour of Accra, Ghana. We visited many tourist sites such as the Independence Square, the cultural center, and some of the local markets to get a feel for the Ghanaian way of life.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/pycon_africa_tour.fbb9132c0ded.JPG&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/pycon_africa_tour.fbb9132c0ded.JPG&quot; width=&quot;1074&quot; height=&quot;716&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycon_africa_tour.fbb9132c0ded.JPG&amp;amp;w=268&amp;amp;sig=f761f4604c1d5149a8ed86d0056197272107fe8f 268w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycon_africa_tour.fbb9132c0ded.JPG&amp;amp;w=537&amp;amp;sig=550c822fb9a941e22b229b9a89c6c0b93dbb29cb 537w, https://files.realpython.com/media/pycon_africa_tour.fbb9132c0ded.JPG 1074w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCon Africa Delegates On A Tour Of Accra&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;KhoPhi.Photography&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The following day was dedicated to workshops, with two running concurrently in both the morning and afternoon sessions. The  &lt;a href=&quot;https://djangogirls.org/&quot;&gt;Django Girls&lt;/a&gt; workshop introduced women and Django beginners to Django development. Other workshops were focused on concepts like data visualization, testing, and iterators.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-django_girls_pycon_africa.8ef8e946afb5.jpg&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/Optimized-django_girls_pycon_africa.8ef8e946afb5.jpg&quot; width=&quot;1200&quot; height=&quot;583&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-django_girls_pycon_africa.8ef8e946afb5.jpg&amp;amp;w=300&amp;amp;sig=5c34eabfb26f161e1394712540be76f9f18b1ab7 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-django_girls_pycon_africa.8ef8e946afb5.jpg&amp;amp;w=600&amp;amp;sig=70ecd6646574f8a46a25e83bee68ceec724b710d 600w, https://files.realpython.com/media/Optimized-django_girls_pycon_africa.8ef8e946afb5.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Django Girls Group Photo&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Django Girls (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;KhoPhi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;main-conference&quot;&gt;Main Conference&lt;/h2&gt;
&lt;p&gt;The main conference started on August 8 and kicked off with an opening ceremony that featured traditional Ghanaian dance and welcoming remarks from &lt;a href=&quot;https://realpython.com/interview-marlene-mhangami/&quot;&gt;Marlene Mhangami&lt;/a&gt;, the Python Africa Chair. &lt;a href=&quot;https://africa.pycon.org/schedule/&quot;&gt;Each day&lt;/a&gt; of the conference had an opening and closing keynote talk.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon_africa_dance.edf5eb3558aa.jpg&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/Optimized-pycon_africa_dance.edf5eb3558aa.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_dance.edf5eb3558aa.jpg&amp;amp;w=300&amp;amp;sig=f3a03eb9d16493e5df95df09e70be0fe1057a2d5 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_dance.edf5eb3558aa.jpg&amp;amp;w=600&amp;amp;sig=39ed902f563d4d8083bf8109251d5336b54b7370 600w, https://files.realpython.com/media/Optimized-pycon_africa_dance.edf5eb3558aa.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Traditional Ghanaian dancers&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Traditional Ghanaian dance (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;KhoPhi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon_africa_marlene.3f67708c9ad2.jpg&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/Optimized-pycon_africa_marlene.3f67708c9ad2.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_marlene.3f67708c9ad2.jpg&amp;amp;w=300&amp;amp;sig=c7593ec4ff8dee3946a9de21dc495e24a4dc72f6 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_marlene.3f67708c9ad2.jpg&amp;amp;w=600&amp;amp;sig=760c5f2d7631840fcdf6d8b57af8b1b5999906a4 600w, https://files.realpython.com/media/Optimized-pycon_africa_marlene.3f67708c9ad2.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Marlene Mhangami Keynote&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Welcoming remarks by Marlene Mhangami (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;KhoPhi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;Let&amp;rsquo;s take a look at some of the talks that were given over the two days of the conference.&lt;/p&gt;
&lt;h2 id=&quot;moustapha-cisse-the-potential-for-positive-impact-through-ai&quot;&gt;Moustapha Cisse: The Potential for Positive Impact Through AI&lt;/h2&gt;
&lt;p&gt;Moustapha Cisse is the head of &lt;a href=&quot;https://en.wikipedia.org/wiki/Google_AI_Centre_in_Ghana&quot;&gt;Google&amp;rsquo;s AI Center in Accra&lt;/a&gt; and he gave the opening keynote on the first day of the main conference. Moustapha&amp;rsquo;s talk was about how African technologists can use technology to solve African problems. In his talk, he discussed some of the work he&amp;rsquo;s involved in at Google and in the AI space, like using Artificial Intelligence for disease prediction, and satellite images to gather information and statistics for AI-enabled flood forecasting.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-moustapha.95d4ca5a95a5.jpg&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/Optimized-moustapha.95d4ca5a95a5.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-moustapha.95d4ca5a95a5.jpg&amp;amp;w=300&amp;amp;sig=8f16dafb8cf8e573015c0536041ca5b0eac9a93d 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-moustapha.95d4ca5a95a5.jpg&amp;amp;w=600&amp;amp;sig=edd1b5f9c9adea47bda824e69fb8b20e0a8480cb 600w, https://files.realpython.com/media/Optimized-moustapha.95d4ca5a95a5.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Moustapha Cisse PyCon Africa Talk&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Moustapha Cisse, Head of Google AI Center Accra (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;KhoPhi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;meili-triantafyllidi-lessons-learned-from-6-years-in-pyladies-berlin&quot;&gt;Meili Triantafyllidi: Lessons Learned From 6 Years in PyLadies Berlin&lt;/h2&gt;
&lt;p&gt;Meili Triantafyllidi is the co-founder of PyLadies Berlin. There are a number of &lt;a href=&quot;https://www.pyladies.com/&quot;&gt;PyLadies&lt;/a&gt; and women-focused Python user groups around Africa. These groups are doing a lot of amazing work, but like anything in life, there&amp;rsquo;s always room for improvement. &lt;/p&gt;
&lt;p&gt;Meili Triantafyllidi gave a &lt;a href=&quot;https://speakerdeck.com/meili/lessons-learned-from-6-years-in-pyladies-berlin&quot;&gt;timely talk&lt;/a&gt; on the lessons she learned from six years of running PyLadies Berlin. In her talk, she shared tips and best practices for making events more inclusive, accessible, and safe. Her talk also covered information on how to run events, get the right speakers, and improve public speaking skills.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-meili_pycon_africa.8defefa8fde5.jpg&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/Optimized-meili_pycon_africa.8defefa8fde5.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-meili_pycon_africa.8defefa8fde5.jpg&amp;amp;w=300&amp;amp;sig=a5823b483d4e7ff352afa556bd52e984280f0fa8 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-meili_pycon_africa.8defefa8fde5.jpg&amp;amp;w=600&amp;amp;sig=4085ae5b3d8228d5fd77da3bb9120e24ee8eae5e 600w, https://files.realpython.com/media/Optimized-meili_pycon_africa.8defefa8fde5.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Meili Triantafyllidi PyLadies talk&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Meili Triantafyllidi (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;KhoPhi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;A PyLadies meeting was held after Meili&amp;rsquo;s talk. The meeting established a common purpose and plans to support female programmers in Africa, including through the creation of a dedicated PyLadies Africa channel in the PyLadies Slack group.&lt;/p&gt;
&lt;h2 id=&quot;candy-tricia-khohliwe-web-virtual-reality-and-a-frame&quot;&gt;Candy Tricia Khohliwe: Web Virtual Reality and A-Frame&lt;/h2&gt;
&lt;p&gt;Candy Khohliwe, a Mozilla Tech Speaker, gave a talk about &lt;a href=&quot;https://webvr.info/&quot;&gt;WebVR&lt;/a&gt;, an open technology that allows you to experience virtual reality in your browser no matter what device you use. The focus of Candy&amp;rsquo;s talk was &lt;a href=&quot;https://en.wikipedia.org/wiki/A-Frame_(virtual_reality_framework)&quot;&gt;A-Frame&lt;/a&gt;, a web framework for creating 3D and WebVR experiences using HTML. From this informative talk, I learned how to use A-Frame to create and draw WebVR components. I look forward to trying it out in future projects!&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon-africa-candy-khohliwe.6949c95996f5.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-66&quot; src=&quot;https://files.realpython.com/media/Optimized-pycon-africa-candy-khohliwe.6949c95996f5.jpg&quot; width=&quot;600&quot; height=&quot;900&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon-africa-candy-khohliwe.6949c95996f5.jpg&amp;amp;w=150&amp;amp;sig=6c6bc2bfdbca0b3dcbbba95ff98a1e3aeca35e0e 150w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon-africa-candy-khohliwe.6949c95996f5.jpg&amp;amp;w=300&amp;amp;sig=98eec4a8b00b109f3bc2e87d0c523da29a844c0b 300w, https://files.realpython.com/media/Optimized-pycon-africa-candy-khohliwe.6949c95996f5.jpg 600w&quot; sizes=&quot;75vw&quot; alt=&quot;Candy Khohliwe WebVR Talk&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Candy Tricia Khohliwe (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;KhoPhi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;nicholas-del-grosso-unravelling-the-spaghetti-tips-for-refactoring-your-code&quot;&gt;Nicholas Del Grosso: Unravelling the Spaghetti (Tips for Refactoring Your Code)&lt;/h2&gt;
&lt;p&gt;Nick Del Grosso gave a talk on refactoring code. He explained how project code can get messy and took us through the process of refactoring it safely. He also discussed strategies for identifying dead code, choosing good variable names, and using tools to help refactor code.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon-nick-del-grosso.dfe10c862f91.jpg&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/Optimized-pycon-nick-del-grosso.dfe10c862f91.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon-nick-del-grosso.dfe10c862f91.jpg&amp;amp;w=300&amp;amp;sig=7f42610cdd78936315f05254755a7b5891ac6165 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon-nick-del-grosso.dfe10c862f91.jpg&amp;amp;w=600&amp;amp;sig=5881e4b73b991ddf73acaa5e76cb73d8d6f2beee 600w, https://files.realpython.com/media/Optimized-pycon-nick-del-grosso.dfe10c862f91.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Nicholas Del Grosso PyCon Africa Talk&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Nicholas Del Grosso (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;KhoPhi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;jessica-upani-is-this-python-thing-really-working&quot;&gt;Jessica Upani: Is This Python Thing Really Working?&lt;/h2&gt;
&lt;p&gt;Jessica Upani from the Namibian Python community gave an enlightening talk about the different Python community groups in Namibia. She discussed the challenges they overcame and what lessons other African Python communities can learn from them.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon_africa_jessica_upani.841c87667d81.jpg&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/Optimized-pycon_africa_jessica_upani.841c87667d81.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_jessica_upani.841c87667d81.jpg&amp;amp;w=300&amp;amp;sig=5f6c598693b0a2897d59ac9c59c4ec72ced861ff 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_jessica_upani.841c87667d81.jpg&amp;amp;w=600&amp;amp;sig=4c8a00a52a8fffd9297ec5ed1bc19abff5fa34d9 600w, https://files.realpython.com/media/Optimized-pycon_africa_jessica_upani.841c87667d81.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Jessica  Upani PyCon Africa Talk&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;Khophi.Photography&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;kelvin-oyana-bridging-the-talent-gap-between-python-communities-and-industry&quot;&gt;Kelvin Oyana: Bridging the Talent Gap Between Python Communities and Industry&lt;/h2&gt;
&lt;p&gt;Kelvin&amp;rsquo;s talk was about the divide between what companies expect from developers and what developers can actually do. He also offered insight into how this gap can be bridged, both by communities and individual developers.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon_africa-kelvin_oyana.e3ad29cc072b.jpg&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/Optimized-pycon_africa-kelvin_oyana.e3ad29cc072b.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa-kelvin_oyana.e3ad29cc072b.jpg&amp;amp;w=300&amp;amp;sig=d3df93c81d0305364eca9438e4e4a063fc4e27dc 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa-kelvin_oyana.e3ad29cc072b.jpg&amp;amp;w=600&amp;amp;sig=936639bfa7f4aed2fe65f9f4ed59ddd62f54d693 600w, https://files.realpython.com/media/Optimized-pycon_africa-kelvin_oyana.e3ad29cc072b.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Kelvin Oyana Pycon Africa Talk&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Kelvin Oyana (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;Khophi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;daniele-procida-the-worlds-simplest-cheapest-plotter&quot;&gt;Daniele Procida: The World&amp;rsquo;s Simplest, Cheapest Plotter&lt;/h2&gt;
&lt;p&gt;Daniele Procida is a Django core developer and one of the members of the PyCon Africa organizing &lt;a href=&quot;https://africa.pycon.org/team/&quot;&gt;team&lt;/a&gt;. In his talk, Daniele presented an interesting &lt;a href=&quot;https://brachiograph.readthedocs.io/en/latest/&quot;&gt;project&lt;/a&gt;: a simple pen plotter he built using cardboard, a Rasberry Pi, some servo motors, and Python software. His project embodies the spirit of resourcefulness and innovation that characterizes African enterprise.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon_africa_daniele_procida.2dbace731d25.jpg&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/Optimized-pycon_africa_daniele_procida.2dbace731d25.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_daniele_procida.2dbace731d25.jpg&amp;amp;w=300&amp;amp;sig=67bdfa6eb8faca3d01a529902dc1a21abc2548d7 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_daniele_procida.2dbace731d25.jpg&amp;amp;w=600&amp;amp;sig=73ed883e302c7a1528e234ef7552df92ecc3d727 600w, https://files.realpython.com/media/Optimized-pycon_africa_daniele_procida.2dbace731d25.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Daniele Procida PyCon Africa Talk&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Daniele Procida (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;Khophi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;ewa-jodlowska-keynote&quot;&gt;Ewa Jodlowska: Keynote&lt;/h2&gt;
&lt;p&gt;Ewa Jodlowska, the Executive Director of the &lt;a href=&quot;https://www.python.org/psf/&quot;&gt;Python Software Foundation (PSF)&lt;/a&gt;, gave a keynote talk about the PSF, how it works with the global community, and its plans for the future. Ewa shed more light on the different programs the PSF runs to foster the growth of the Python community, such as the Sponsorship Program and the Python Ambassador Program in South America.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon-africa-ewa.6f9cb20b9504.jpg&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/Optimized-pycon-africa-ewa.6f9cb20b9504.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon-africa-ewa.6f9cb20b9504.jpg&amp;amp;w=300&amp;amp;sig=c771277dd32ad9da88aa47aaef2578f1901c2d3d 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon-africa-ewa.6f9cb20b9504.jpg&amp;amp;w=600&amp;amp;sig=23b992e78b6ef954c0fe58c7f7c67ca8187cdc9e 600w, https://files.realpython.com/media/Optimized-pycon-africa-ewa.6f9cb20b9504.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Ewa Jodlowska PyCon Africa Keynote Talk&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Ewa Jodlowska (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;Khophi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;anna-makarudze-what-the-african-developer-can-do-to-increase-diversity-in-tech&quot;&gt;Anna Makarudze: What the African Developer Can Do to Increase Diversity in Tech&lt;/h2&gt;
&lt;p&gt;Anna Makarudze gave the closing keynote on the first day of the main conference. She&amp;rsquo;s a Software Engineer at &lt;a href=&quot;https://www.britecore.com/&quot;&gt;BriteCore&lt;/a&gt; (one of the diamond sponsors of PyCon Africa), the Vice President of the Django Software Foundation, and the Fundraising Coordinator for the &lt;a href=&quot;https://www.djangoproject.com/foundation/&quot;&gt;Django Girls Foundation&lt;/a&gt;. Anna drew on her experiences in these organizations to discuss how conferences, organizations, and individual developers can increase diversity figures in tech.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/anna2.d1743996174a.jpg&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/anna2.d1743996174a.jpg&quot; width=&quot;600&quot; height=&quot;900&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/anna2.d1743996174a.jpg&amp;amp;w=150&amp;amp;sig=e21c29ea107dd2f760e896506137328d57baed09 150w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/anna2.d1743996174a.jpg&amp;amp;w=300&amp;amp;sig=5c84fb15728d730ef12c2e2d3afbf959cac030a6 300w, https://files.realpython.com/media/anna2.d1743996174a.jpg 600w&quot; sizes=&quot;75vw&quot; alt=&quot;Anna Makarudze Keynote At PyCon Africa&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Anna Makarudze (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;Khophi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;panel-discussion-the-role-of-the-african-python-developer-in-the-community&quot;&gt;Panel Discussion: The Role of the African Python Developer in the Community&lt;/h2&gt;
&lt;p&gt;There was a panel discussion of leaders in business, technology, and community development. Marlene Manghami moderated the discussion on the role of the African Python community in the global tech space. Her panelists were Solomon Apenya, Daniel Roy Greenfeld, and James Yankah. &lt;/p&gt;
&lt;p&gt;Solomon Apenya is a Senior Consultant at &lt;a href=&quot;https://andela.com/&quot;&gt;Andela&lt;/a&gt;, a company that finds and builds distributed engineering teams in Africa. Daniel Roy Greenfeld is co-author of &lt;em&gt;Two Scoops of Django&lt;/em&gt; and VP of Implementation Engineering at &lt;a href=&quot;https://www.britecore.com/&quot;&gt;BriteCore&lt;/a&gt;. James Yankah is the Managing Director of &lt;a href=&quot;http://bromptongroupgh.com/&quot;&gt;Brompton Group&lt;/a&gt;, a group of companies that offer recruitment, training, management, logistics, and security services.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon-africa-panel.72710f1b3453.jpg&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/Optimized-pycon-africa-panel.72710f1b3453.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon-africa-panel.72710f1b3453.jpg&amp;amp;w=300&amp;amp;sig=3b6b069815f66ebabf5da678b459de8623d9ec17 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon-africa-panel.72710f1b3453.jpg&amp;amp;w=600&amp;amp;sig=64fe9945e3847088697f9395d5d076954b4d6a5b 600w, https://files.realpython.com/media/Optimized-pycon-africa-panel.72710f1b3453.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Panel Discussion At PyCon Africa&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Image: &lt;a href=&quot;http://khophi.photography/&quot; target=&quot;_blank&quot;&gt;Khophi Photography&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;anthony-shaw-standing-out-in-a-world-of-20-million-developers&quot;&gt;Anthony Shaw: Standing Out in a World of 20 Million Developers&lt;/h2&gt;
&lt;p&gt;On the last day of the conference, I had the pleasure of meeting and listening to &lt;a href=&quot;https://realpython.com/team/ashaw/&quot;&gt;Anthony Shaw&lt;/a&gt;, a fellow &lt;em&gt;Real Python&lt;/em&gt; author. Anthony gave a talk targeted at new developers to help them succeed in their development careers. In the &lt;a href=&quot;https://speakerdeck.com/tonybaloney/getting-ahead-in-a-world-of-20-million-developers&quot;&gt;talk&lt;/a&gt;, Anthony discussed ways to get ahead, grow your skill set, learn new technologies, and fight doubt and impostor syndrome. He concluded with tips on how to nail technical interviews.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon-africa-anthony-shaw.b43a55f28161.jpg&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/Optimized-pycon-africa-anthony-shaw.b43a55f28161.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon-africa-anthony-shaw.b43a55f28161.jpg&amp;amp;w=300&amp;amp;sig=6e40e2a1687fff56cef8f1b8b3ac2b3348e782c0 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon-africa-anthony-shaw.b43a55f28161.jpg&amp;amp;w=600&amp;amp;sig=9333157f2b509240c3b1602502d449daea7c8849 600w, https://files.realpython.com/media/Optimized-pycon-africa-anthony-shaw.b43a55f28161.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Anthony Shaw PyCon Africa Talk&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Anthony Shaw (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;Khophi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;closing-keynote-kojo-idrissa&quot;&gt;Closing Keynote: Kojo Idrissa&lt;/h2&gt;
&lt;p&gt;The closing keynote on the last day of the conference was given by &lt;a href=&quot;https://twitter.com/transition&quot;&gt;Kojo Idrissa&lt;/a&gt;, an organizer for DjangoCon and a Django Events Foundation North America (DEFNA) Ambassador. Kojo reflected on lessons from the past and how the African diaspora has had an effect on us all.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon_africa_kojo.4817c592dbda.jpg&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/Optimized-pycon_africa_kojo.4817c592dbda.jpg&quot; width=&quot;1200&quot; height=&quot;800&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_kojo.4817c592dbda.jpg&amp;amp;w=300&amp;amp;sig=3c13e8aecd5ad27392d5b48326b2eac90ae8846d 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_kojo.4817c592dbda.jpg&amp;amp;w=600&amp;amp;sig=17b27dd926e15dd623fef16321b141009b9c52bc 600w, https://files.realpython.com/media/Optimized-pycon_africa_kojo.4817c592dbda.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Kojo Idrissa PyCon Africa Talk&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Kojo Idrissa (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;Khophi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;sprints-day&quot;&gt;Sprints Day&lt;/h2&gt;
&lt;p&gt;The day after the main conference was dedicated to sprints! This is where people group up to work on various open source Python projects. I was part of a team that worked on &lt;a href=&quot;https://github.com/cookiecutter/cookiecutter&quot;&gt;Cookie Cutter&lt;/a&gt; and other related projects. I submitted a PR that got merged into the project and I also helped mentor other team members. &lt;/p&gt;
&lt;p&gt;I highly recommend anyone who has not attended a sprint before to do so! It&amp;rsquo;s a great way to practice your skills, contribute to an open source project, and meet the developers involved with the project.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/sprints.b4182ec9e033.jpg&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/sprints.b4182ec9e033.jpg&quot; width=&quot;1074&quot; height=&quot;716&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/sprints.b4182ec9e033.jpg&amp;amp;w=268&amp;amp;sig=ce864ec51b441f3cedb345db2159160468b37783 268w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/sprints.b4182ec9e033.jpg&amp;amp;w=537&amp;amp;sig=fc838971a61f2d07646dc1dacbc5db8bd8994ffe 537w, https://files.realpython.com/media/sprints.b4182ec9e033.jpg 1074w&quot; sizes=&quot;75vw&quot; alt=&quot;A Group Of Developers During A Sprints Session At Pycon Africa&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Sprints (Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;Khophi.Photography&lt;/a&gt;)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;h2 id=&quot;summary&quot;&gt;Summary&lt;/h2&gt;
&lt;p&gt;PyCon Africa was a huge success and nothing short of fantastic! It was a good start for the African community because it brought together, for the first time, Python developers from the different African Python communities. It also allowed us to hear from representatives of the PSF about how the Python community is organized and funded. For many, this was the first time that people from the different communities met in person after years of online collaboration.&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-pycon_africa_group.33a7bc40895b.jpg&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/Optimized-pycon_africa_group.33a7bc40895b.jpg&quot; width=&quot;1200&quot; height=&quot;597&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_group.33a7bc40895b.jpg&amp;amp;w=300&amp;amp;sig=305c07135e35fc369d0953330175546034bcfc1c 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-pycon_africa_group.33a7bc40895b.jpg&amp;amp;w=600&amp;amp;sig=78d0d94acb412945bf4a7ab012c9c953090fd2ad 600w, https://files.realpython.com/media/Optimized-pycon_africa_group.33a7bc40895b.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCon Africa Group Photo&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Image: &lt;a href=&quot;https://www.khophi.photography/&quot; target=&quot;_blank&quot;&gt;Khophi Photography&lt;/a&gt;&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;For me, the experience was worth the sacrifice and expense because I got to meet and talk to people from all over the world and learn about how they use Python in their work or studies. I gave a lightning talk on how to &lt;a href=&quot;https://vuyisile.com/how-to-send-desktop-notifications-in-linux/&quot;&gt;send desktop notifications from Python scripts&lt;/a&gt; using Python and other tools native to Linux. &lt;/p&gt;
&lt;p&gt;Another highlight of attending PyCon Africa was that I got to meet many of our readers, and a number of them attributed their success to much of the content they read here on &lt;em&gt;Real Python&lt;/em&gt;. Anthony Shaw and I also gave away many &lt;em&gt;Real Python&lt;/em&gt; stickers. Here&amp;rsquo;s a photo we took with Edison, a friend and &lt;em&gt;Real Python&lt;/em&gt; reader:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/Optimized-IMG_20190809_113244.149c0fd85db5.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-66&quot; src=&quot;https://files.realpython.com/media/Optimized-IMG_20190809_113244.149c0fd85db5.jpg&quot; width=&quot;1200&quot; height=&quot;888&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-IMG_20190809_113244.149c0fd85db5.jpg&amp;amp;w=300&amp;amp;sig=f89dfe06eb6d0a60a7551cef40e40b2084ef671c 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/Optimized-IMG_20190809_113244.149c0fd85db5.jpg&amp;amp;w=600&amp;amp;sig=623e2edd0a47505095b93643d29456a745c77460 600w, https://files.realpython.com/media/Optimized-IMG_20190809_113244.149c0fd85db5.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;Real Python Authors and Reader: Vuyisile, Anthony, And Edison&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;One problem that the organizers faced was making the conference affordable to as many people as possible. Travel within Africa is expensive and difficult for many Africans. For instance, an entry visa to Ghana alone costs $100 to $200 U.S. dollars. Add to that the cost of travel and lodging, and the event was out of reach for many people who were interested in attending.&lt;/p&gt;
&lt;p&gt;Voluntary donations from individuals and corporate sponsorship from &lt;em&gt;Real Python&lt;/em&gt;, BriteCore, Andela, and several other sponsors helped cover the cost of tickets, accommodation, and travel for those that needed it. If you&amp;rsquo;d like to get more African people involved in Python, then consider supporting future Python events in Africa and hiring African developers to work remotely in your teams.&lt;/p&gt;
&lt;p&gt;At the time of this writing, videos from the conference have not been made available, but there is a &lt;a href=&quot;https://www.youtube.com/watch?v=43wJnYZ6Zd0&quot;&gt;highlight video&lt;/a&gt; that also features interviews with some of the attendees. You can also read the &lt;a href=&quot;https://africa.pycon.org/report/&quot;&gt;official report&lt;/a&gt; from the conference organizers. If you&amp;rsquo;re thinking of attending a PyCon near you, then check out &lt;a href=&quot;https://realpython.com/pycon-guide/&quot;&gt;How to Get the Most Out of PyCon&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>When to Use a List Comprehension in Python</title>
      <id>https://realpython.com/list-comprehension-python/</id>
      <link href="https://realpython.com/list-comprehension-python/"/>
      <updated>2019-11-06T14:00:00+00:00</updated>
      <summary>Python list comprehensions make it easy to create lists while performing sophisticated filtering, mapping, and conditional logic on their members. In this tutorial, you&#39;ll learn when to use a list comprehension in Python and how to create them effectively.</summary>
      <content type="html">
        &lt;p&gt;Python is famous for allowing you to write code that&amp;rsquo;s elegant, easy to write, and almost as easy to read as plain English. One of the language&amp;rsquo;s most distinctive features is the &lt;strong&gt;list comprehension&lt;/strong&gt;, which you can use to create powerful functionality within a single line of code. However, many developers struggle to fully leverage the more advanced features of a list comprehension in Python. Some programmers even use them too much, which can lead to code that&amp;rsquo;s less efficient and harder to read.&lt;/p&gt;
&lt;p&gt;By the end of this tutorial, you&amp;rsquo;ll understand the full power of Python list comprehensions and how to use their features comfortably. You&amp;rsquo;ll also gain an understanding of the trade-offs that come with using them so that you can determine when other approaches are more preferable.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this tutorial, you&amp;rsquo;ll learn how to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Rewrite loops and &lt;code&gt;map()&lt;/code&gt; calls as a &lt;strong&gt;list comprehension&lt;/strong&gt; in Python&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Choose&lt;/strong&gt; between comprehensions, loops, and &lt;code&gt;map()&lt;/code&gt; calls&lt;/li&gt;
&lt;li&gt;Supercharge your comprehensions with &lt;strong&gt;conditional logic&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use comprehensions&lt;/strong&gt; to replace &lt;code&gt;filter()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Profile&lt;/strong&gt; your code to solve performance questions&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Free Bonus:&lt;/strong&gt; &lt;a href=&quot;&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-python-tricks-sample&quot; data-focus=&quot;false&quot;&gt;Click here to get access to a chapter from Python Tricks: The Book&lt;/a&gt; that shows you Python&#39;s best practices with simple examples you can apply instantly to write more beautiful + Pythonic code.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;how-to-create-lists-in-python&quot;&gt;How to Create Lists in Python&lt;/h2&gt;
&lt;p&gt;There are a few different ways you can create &lt;a href=&quot;https://realpython.com/python-lists-tuples/&quot;&gt;lists&lt;/a&gt; in Python. To better understand the trade-offs of using a list comprehension in Python, let&amp;rsquo;s first see how to create lists with these approaches.&lt;/p&gt;
&lt;h3 id=&quot;using-for-loops&quot;&gt;Using &lt;code&gt;for&lt;/code&gt; Loops&lt;/h3&gt;
&lt;p&gt;The most common type of loop is the &lt;a href=&quot;https://realpython.com/courses/python-for-loop/&quot;&gt;&lt;code&gt;for&lt;/code&gt;&lt;/a&gt; loop. You can use a &lt;code&gt;for&lt;/code&gt; loop to create a list of elements in three steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Instantiate an empty list.&lt;/li&gt;
&lt;li&gt;Loop over an iterable or &lt;a href=&quot;https://realpython.com/python-range/&quot;&gt;range&lt;/a&gt; of elements.&lt;/li&gt;
&lt;li&gt;Append each element to the end of the list.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you want to create a list containing the first ten perfect squares, then you can complete these steps in three lines of 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;squares&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;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;10&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;squares&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;i&lt;/span&gt; &lt;span class=&quot;o&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;squares&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you instantiate an empty list, &lt;code&gt;squares&lt;/code&gt;. Then, you use a &lt;code&gt;for&lt;/code&gt; loop to iterate over &lt;code&gt;range(10)&lt;/code&gt;. Finally, you multiply each number by itself and append the result to the end of the list.&lt;/p&gt;
&lt;h3 id=&quot;using-map-objects&quot;&gt;Using &lt;code&gt;map()&lt;/code&gt; Objects&lt;/h3&gt;
&lt;p&gt;&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; provides an alternative approach that&amp;rsquo;s based in &lt;a href=&quot;https://realpython.com/courses/functional-programming-python/&quot;&gt;functional programming&lt;/a&gt;. You pass in a function and an iterable, and &lt;code&gt;map()&lt;/code&gt; will create an object. This object contains the output you would get from running each iterable element through the supplied function.&lt;/p&gt;
&lt;p&gt;As an example, consider a situation in which you need to calculate the price after tax for a list of transactions:&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;txns&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;mf&quot;&gt;1.09&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;23.56&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;57.84&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.56&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;6.78&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TAX_RATE&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;08&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;get_price_with_tax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&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;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TAX_RATE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final_prices&lt;/span&gt; &lt;span class=&quot;o&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;get_price_with_tax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txns&lt;/span&gt;&lt;span class=&quot;p&quot;&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;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final_prices&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1.1772000000000002, 25.4448, 62.467200000000005, 4.9248, 7.322400000000001]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you have an iterable &lt;code&gt;txns&lt;/code&gt; and a function &lt;code&gt;get_price_with_tax()&lt;/code&gt;. You pass both of these arguments to &lt;code&gt;map()&lt;/code&gt;, and store the resulting object in &lt;code&gt;final_prices&lt;/code&gt;. You can easily convert this map object into a list using &lt;code&gt;list()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;using-list-comprehensions&quot;&gt;Using List Comprehensions&lt;/h3&gt;
&lt;p&gt;List comprehensions are a third way of making lists. With this elegant approach, you could rewrite the &lt;code&gt;for&lt;/code&gt; loop from the first example in just a single line of 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;squares&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;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&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;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;squares&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Rather than creating an empty list and adding each element to the end, you simply define the list and its contents at the same time by following this format:&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;new_list = [expression for member in iterable]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Every list comprehension in Python includes three elements:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;expression&lt;/code&gt;&lt;/strong&gt; is the member itself, a call to a method, or any other valid expression that returns a value. In the example above, the expression &lt;code&gt;i * i&lt;/code&gt; is the square of the member value.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;member&lt;/code&gt;&lt;/strong&gt; is the object or value in the list or iterable. In the example above, the member value is &lt;code&gt;i&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;iterable&lt;/code&gt;&lt;/strong&gt; is a list, &lt;a href=&quot;https://realpython.com/python-sets/&quot;&gt;set&lt;/a&gt;, sequence, &lt;a href=&quot;https://realpython.com/introduction-to-python-generators/&quot;&gt;generator&lt;/a&gt;, or any other object that can return its elements one at a time. In the example above, the iterable is &lt;code&gt;range(10)&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Because the &lt;strong&gt;expression&lt;/strong&gt; requirement is so flexible, a list comprehension in Python works well in many places where you would use &lt;code&gt;map()&lt;/code&gt;. You can rewrite the pricing example with its own list 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;txns&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;mf&quot;&gt;1.09&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;23.56&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;57.84&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;4.56&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;6.78&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TAX_RATE&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;08&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;get_price_with_tax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&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;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TAX_RATE&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;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final_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;n&quot;&gt;get_price_with_tax&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;n&quot;&gt;txns&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;final_prices&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1.1772000000000002, 25.4448, 62.467200000000005, 4.9248, 7.322400000000001]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The only distinction between this implementation and &lt;code&gt;map()&lt;/code&gt; is that the list comprehension in Python returns a list, not a map object.&lt;/p&gt;
&lt;h3 id=&quot;benefits-of-using-list-comprehensions&quot;&gt;Benefits of Using List Comprehensions&lt;/h3&gt;
&lt;p&gt;List comprehensions are often described as being more &lt;a href=&quot;https://realpython.com/courses/idiomatic-python-101/&quot;&gt;Pythonic&lt;/a&gt; than loops or &lt;code&gt;map()&lt;/code&gt;. But rather than blindly accepting that assessment, it&amp;rsquo;s worth it to understand the benefits of using a list comprehension in Python when compared to the alternatives. Later on, you&amp;rsquo;ll learn about a few scenarios where the alternatives are a better choice.&lt;/p&gt;
&lt;p&gt;One main benefit of using a list comprehension in Python is that it&amp;rsquo;s a single tool that you can use in many different situations. In addition to standard &lt;a href=&quot;https://realpython.com/python-lists-tuples/&quot;&gt;list creation&lt;/a&gt;, list comprehensions can also be used for mapping and filtering. You don&amp;rsquo;t have to use a different approach for each scenario.&lt;/p&gt;
&lt;p&gt;This is the main reason why list comprehensions are considered &lt;strong&gt;Pythonic&lt;/strong&gt;, as Python embraces simple, powerful tools that you can use in a wide variety of situations. As an added side benefit, whenever you use a list comprehension in Python, you won&amp;rsquo;t need to remember the proper order of arguments like you would when you call &lt;code&gt;map()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;List comprehensions are also more &lt;strong&gt;declarative&lt;/strong&gt; than loops, which means they&amp;rsquo;re easier to read and understand. Loops require you to focus on how the list is created. You have to manually create an empty list, loop over the elements, and add each of them to the end of the list. With a list comprehension in Python, you can instead focus on &lt;em&gt;what&lt;/em&gt; you want to go in the list and trust that Python will take care of &lt;em&gt;how&lt;/em&gt; the list construction takes place.&lt;/p&gt;
&lt;h2 id=&quot;how-to-supercharge-your-comprehensions&quot;&gt;How to Supercharge Your Comprehensions&lt;/h2&gt;
&lt;p&gt;In order to understand the full value that &lt;a href=&quot;https://realpython.com/courses/using-list-comprehensions-effectively/&quot;&gt;list comprehensions&lt;/a&gt; can provide, it&amp;rsquo;s helpful to understand their range of possible functionality. You&amp;rsquo;ll also want to understand the changes that are coming to the list comprehension in Python 3.8.&lt;/p&gt;
&lt;h3 id=&quot;using-conditional-logic&quot;&gt;Using Conditional Logic&lt;/h3&gt;
&lt;p&gt;Earlier, you saw this formula for how to create list comprehensions:&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;new_list = [expression for member in iterable]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;While this formula is accurate, it&amp;rsquo;s also a bit incomplete. A more complete description of the comprehension formula adds support for optional &lt;strong&gt;conditionals&lt;/strong&gt;. The most common way to add &lt;a href=&quot;https://realpython.com/python-conditional-statements/&quot;&gt;conditional logic&lt;/a&gt; to a list comprehension is to add a conditional to the end of the 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;go&quot;&gt;new_list = [expression for member in iterable (if conditional)]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, your conditional statement comes just before the closing bracket.&lt;/p&gt;
&lt;p&gt;Conditionals are important because they allow list comprehensions to filter out unwanted values, which would normally require a call to &lt;code&gt;filter()&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;sentence&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;the rocket came back from mars&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;vowels&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;i&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;sentence&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&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;s1&quot;&gt;&amp;#39;aeiou&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;vowels&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;e&amp;#39;, &amp;#39;o&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;a&amp;#39;, &amp;#39;o&amp;#39;, &amp;#39;a&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code block, the conditional statement filters out any characters in &lt;code&gt;sentence&lt;/code&gt; that aren&amp;rsquo;t a vowel.&lt;/p&gt;
&lt;p&gt;The conditional can test any valid expression. If you need a more complex filter, then you can even move the conditional logic to a separate function:&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;sentence&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;The rocket, who was named Ted, came back &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;from Mars because he missed his friends.&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;is_consonant&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;letter&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;vowels&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;aeiou&amp;#39;&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;letter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isalpha&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;n&quot;&gt;letter&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;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;vowels&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;consonants&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;i&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;sentence&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;is_consonant&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;go&quot;&gt;[&amp;#39;T&amp;#39;, &amp;#39;h&amp;#39;, &amp;#39;r&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;k&amp;#39;, &amp;#39;t&amp;#39;, &amp;#39;w&amp;#39;, &amp;#39;h&amp;#39;, &amp;#39;w&amp;#39;, &amp;#39;s&amp;#39;, &amp;#39;n&amp;#39;, &amp;#39;m&amp;#39;, &amp;#39;d&amp;#39;, \&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;T&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;m&amp;#39;, &amp;#39;b&amp;#39;, &amp;#39;c&amp;#39;, &amp;#39;k&amp;#39;, &amp;#39;f&amp;#39;, &amp;#39;r&amp;#39;, &amp;#39;m&amp;#39;, &amp;#39;M&amp;#39;, &amp;#39;r&amp;#39;, &amp;#39;s&amp;#39;, &amp;#39;b&amp;#39;, \&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;c&amp;#39;, &amp;#39;s&amp;#39;, &amp;#39;h&amp;#39;, &amp;#39;m&amp;#39;, &amp;#39;s&amp;#39;, &amp;#39;s&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;h&amp;#39;, &amp;#39;s&amp;#39;, &amp;#39;f&amp;#39;, &amp;#39;r&amp;#39;, &amp;#39;n&amp;#39;, &amp;#39;d&amp;#39;, &amp;#39;s&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you create a complex filter &lt;code&gt;is_consonant()&lt;/code&gt; and pass this function as the conditional statement for your list comprehension. Note that the member value &lt;code&gt;i&lt;/code&gt; is also passed as an argument to your function.&lt;/p&gt;
&lt;p&gt;You can place the conditional at the end of the statement for simple filtering, but what if you want to &lt;em&gt;change&lt;/em&gt; a member value instead of filtering it out? In this case, it&amp;rsquo;s useful to place the conditional near the &lt;em&gt;beginning&lt;/em&gt; of the 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;go&quot;&gt;new_list = [expression (if conditional) for member in iterable]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this formula, you can use conditional logic to select from multiple possible output options. For example, if you have a list of prices, then you may want to replace negative prices with &lt;code&gt;0&lt;/code&gt; and leave the positive values unchanged:&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;original_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;mf&quot;&gt;1.25&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;9.45&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;10.22&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.78&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;5.92&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;1.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;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;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&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;original_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;prices&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1.25, 0, 10.22, 3.78, 0, 1.16]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, your expression &lt;code&gt;i&lt;/code&gt; contains a conditional statement, &lt;code&gt;if i &amp;gt; 0 else 0&lt;/code&gt;. This tells Python to output the value of &lt;code&gt;i&lt;/code&gt; if the number is positive, but to change &lt;code&gt;i&lt;/code&gt; to &lt;code&gt;0&lt;/code&gt; if the number is negative. If this seems overwhelming, then it may be helpful to view the conditional logic as its own function:&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_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&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;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;price&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;price&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;/span&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;n&quot;&gt;get_price&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;n&quot;&gt;original_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;prices&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1.25, 0, 10.22, 3.78, 0, 1.16]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, your conditional statement is contained within &lt;code&gt;get_price()&lt;/code&gt;, and you can use it as part of your list comprehension expression.&lt;/p&gt;
&lt;h3 id=&quot;using-set-and-dictionary-comprehensions&quot;&gt;Using Set and Dictionary Comprehensions&lt;/h3&gt;
&lt;p&gt;While the list comprehension in Python is a common tool, you can also create set and dictionary comprehensions. A &lt;strong&gt;set comprehension&lt;/strong&gt; is almost exactly the same as a list comprehension in Python. The difference is that set comprehensions make sure the output contains no duplicates. You can create a set comprehension by using curly braces instead of brackets:&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;quote&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;life, uh, finds a way&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;unique_vowels&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;i&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;quote&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&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;s1&quot;&gt;&amp;#39;aeiou&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;unique_vowels&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&amp;#39;a&amp;#39;, &amp;#39;e&amp;#39;, &amp;#39;u&amp;#39;, &amp;#39;i&amp;#39;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Your set comprehension outputs all the unique vowels it found in &lt;code&gt;quote&lt;/code&gt;. Unlike lists, sets don&amp;rsquo;t guarantee that items will be saved in any particular order. This is why the first member of the set is &lt;code&gt;a&lt;/code&gt;, even though the first vowel in &lt;code&gt;quote&lt;/code&gt; is &lt;code&gt;i&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Dictionary comprehensions&lt;/strong&gt; are similar, with the additional requirement of defining a key:&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;squares&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;i&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;n&quot;&gt;i&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;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;squares&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To create the &lt;code&gt;squares&lt;/code&gt; dictionary, you use curly braces (&lt;code&gt;{}&lt;/code&gt;) as well as a key-value pair (&lt;code&gt;i: i * i&lt;/code&gt;) in your expression.&lt;/p&gt;
&lt;h3 id=&quot;using-the-walrus-operator&quot;&gt;Using the Walrus Operator&lt;/h3&gt;
&lt;p&gt;Python 3.8 will introduce the &lt;a href=&quot;https://www.python.org/dev/peps/pep-0572/&quot;&gt;assignment expression&lt;/a&gt;, also known as the &lt;strong&gt;walrus operator&lt;/strong&gt;. To understand how you can use it, consider the following example.&lt;/p&gt;
&lt;p&gt;Say you need to make ten requests to an API that will return temperature data. You only want to return results that are greater than 100 degrees Fahrenheit. Assume that each request will return different data. In this case, there&amp;rsquo;s no way to use a list comprehension in Python to solve the problem. The formula &lt;code&gt;expression for member in iterable (if conditional)&lt;/code&gt; provides no way for the conditional to assign data to a variable that the expression can access.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;walrus operator&lt;/strong&gt; solves this problem. It allows you to run an expression while simultaneously assigning the output value to a variable. The following example shows how this is possible, using &lt;code&gt;get_weather_data()&lt;/code&gt; to generate fake weather 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;random&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;get_weather_data&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;random&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randrange&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;110&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hot_temps&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;temp&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&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;20&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;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;get_weather_data&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;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hot_temps&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[107, 102, 109, 104, 107, 109, 108, 101, 104]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You won&amp;rsquo;t often need to use the assignment expression inside of a list comprehension in Python, but it&amp;rsquo;s a useful tool to have at your disposal when necessary.&lt;/p&gt;
&lt;h2 id=&quot;when-not-to-use-a-list-comprehension-in-python&quot;&gt;When Not to Use a List Comprehension in Python&lt;/h2&gt;
&lt;p&gt;List comprehensions are useful and can help you write elegant code that&amp;rsquo;s easy to read and debug, but they&amp;rsquo;re not the right choice for all circumstances. They might make your code run more slowly or use more memory. If your code is less performant or harder to understand, then it&amp;rsquo;s probably better to choose an alternative.&lt;/p&gt;
&lt;h3 id=&quot;watch-out-for-nested-comprehensions&quot;&gt;Watch Out for Nested Comprehensions&lt;/h3&gt;
&lt;p&gt;Comprehensions can be &lt;strong&gt;nested&lt;/strong&gt; to create combinations of lists, dictionaries, and sets within a collection. For example, say a climate laboratory is tracking the high temperature in five different cities for the first week of June. The perfect data structure for storing this data could be a Python list comprehension nested within 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;cities&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;Austin&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Tacoma&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Topeka&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Sacramento&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Charlotte&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;temps&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;city&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;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&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;7&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;city&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cities&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;temps&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    &amp;#39;Austin&amp;#39;: [0, 0, 0, 0, 0, 0, 0],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    &amp;#39;Tacoma&amp;#39;: [0, 0, 0, 0, 0, 0, 0],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    &amp;#39;Topeka&amp;#39;: [0, 0, 0, 0, 0, 0, 0],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    &amp;#39;Sacramento&amp;#39;: [0, 0, 0, 0, 0, 0, 0],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    &amp;#39;Charlotte&amp;#39;: [0, 0, 0, 0, 0, 0, 0]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You create the outer collection &lt;code&gt;temps&lt;/code&gt; with a dictionary comprehension. The expression is a key-value pair, which contains yet another comprehension. This code will quickly generate a list of data for each city in &lt;code&gt;cities&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Nested lists are a common way to create &lt;strong&gt;matrices&lt;/strong&gt;, which are often used for mathematical purposes. Take a look at the code block below:&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;matrix&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;i&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;5&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;_&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;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;matrix&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    [0, 1, 2, 3, 4],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    [0, 1, 2, 3, 4],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    [0, 1, 2, 3, 4],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    [0, 1, 2, 3, 4],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    [0, 1, 2, 3, 4],&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    [0, 1, 2, 3, 4]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The outer list comprehension &lt;code&gt;[... for _ in range(6)]&lt;/code&gt; creates six rows, while the inner list comprehension &lt;code&gt;[i for i in range(5)]&lt;/code&gt; fills each of these rows with values.&lt;/p&gt;
&lt;p&gt;So far, the purpose of each nested comprehension is pretty intuitive. However, there are other situations, such as &lt;strong&gt;flattening&lt;/strong&gt; nested lists, where the logic arguably makes your code more confusing. Take this example, which uses a nested list comprehension to flatten a matrix:&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;matrix = [&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&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;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;1&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;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;2&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;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flat&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;num&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;matrix&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flat&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[0, 0, 0, 1, 1, 1, 2, 2, 2]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code to flatten the matrix is concise, but it may not be so intuitive to understand how it works. On the other hand, if you were to use &lt;code&gt;for&lt;/code&gt; loops to flatten the same matrix, then your code will be much more straightforward:&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;matrix&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;... &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&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;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;1&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;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;2&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;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;flat&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;row&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;matrix&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;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&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;gp&quot;&gt;... &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;flat&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;num&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;flat&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[0, 0, 0, 1, 1, 1, 2, 2, 2]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you can see that the code traverses one row of the matrix at a time, pulling out all the elements in that row before moving on to the next one.&lt;/p&gt;
&lt;p&gt;While the single-line nested list comprehension might seem more Pythonic, what&amp;rsquo;s most important is to write code that your team can easily understand and modify. When you choose your approach, you&amp;rsquo;ll have to make a judgment call based on whether you think the comprehension helps or hurts readability.&lt;/p&gt;
&lt;h3 id=&quot;choose-generators-for-large-datasets&quot;&gt;Choose Generators for Large Datasets&lt;/h3&gt;
&lt;p&gt;A list comprehension in Python works by loading the entire output list into memory. For small or even medium-sized lists, this is generally fine. If you want to sum the squares of the first one-thousand integers, then a list comprehension will solve this problem admirably:&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;sum&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;n&quot;&gt;i&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;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)])&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;332833500&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But what if you wanted to sum the squares of the first &lt;em&gt;billion&lt;/em&gt; integers? If you tried then on your machine, then you may notice that your computer becomes non-responsive. That&amp;rsquo;s because Python is trying to create a list with one billion integers, which consumes more memory than your computer would like. Your computer may not have the resources it needs to generate an enormous list and store it in memory. If you try to do it anyway, then your machine could slow down or even crash.&lt;/p&gt;
&lt;p&gt;When the size of a list becomes problematic, it&amp;rsquo;s often helpful to use a &lt;a href=&quot;https://realpython.com/introduction-to-python-generators/&quot;&gt;generator&lt;/a&gt; instead of a list comprehension in Python. A &lt;strong&gt;generator&lt;/strong&gt; doesn&amp;rsquo;t create a single, large data structure in memory, but instead returns an iterable. Your code can ask for the next value from the iterable as many times as necessary or until you&amp;rsquo;ve reached the end of your sequence, while only storing a single value at a time.&lt;/p&gt;
&lt;p&gt;If you were to sum the first billion squares with a generator, then your program will likely run for a while, but it shouldn&amp;rsquo;t cause your computer to freeze. The example below uses a generator:&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;sum&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;n&quot;&gt;i&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;1000000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;333333332833333333500000000&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can tell this is a generator because the expression isn&amp;rsquo;t surrounded by brackets or curly braces. Optionally, generators can be surrounded by parentheses.&lt;/p&gt;
&lt;p&gt;The example above still requires a lot of work, but it performs the operations &lt;strong&gt;lazily&lt;/strong&gt;.  Because of lazy evaluation, values are only calculated when they&amp;rsquo;re explicitly requested. After the generator yields a value (for example, &lt;code&gt;567 * 567&lt;/code&gt;), it can add that value to the running sum, then discard that value and generate the next value (&lt;code&gt;568 * 568&lt;/code&gt;). When the sum function requests the next value, the cycle starts over. This process keeps the memory footprint small.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;map()&lt;/code&gt; also operates lazily, meaning memory won&amp;rsquo;t be an issue if you choose to use it in this case:&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;sum&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;k&quot;&gt;lambda&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;i&lt;/span&gt;&lt;span class=&quot;o&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;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;333333332833333333500000000&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;s up to you whether you prefer the generator expression or &lt;code&gt;map()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;profile-to-optimize-performance&quot;&gt;Profile to Optimize Performance&lt;/h3&gt;
&lt;p&gt;So, which approach is faster? Should you use list comprehensions or one of their alternatives? Rather than adhere to a single rule that&amp;rsquo;s true in all cases, it&amp;rsquo;s more useful to ask yourself whether or not performance &lt;strong&gt;matters&lt;/strong&gt; in your specific circumstance. If not, then it&amp;rsquo;s usually best to choose whatever approach leads to the cleanest code!&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re in a scenario where performance is important, then it&amp;rsquo;s typically best to &lt;strong&gt;profile&lt;/strong&gt; different approaches and listen to the data. &lt;a href=&quot;https://docs.python.org/3/library/timeit.html&quot;&gt;&lt;code&gt;timeit&lt;/code&gt;&lt;/a&gt; is a useful library for timing how long it takes chunks of code to run. You can use &lt;code&gt;timeit&lt;/code&gt; to compare the runtime of &lt;code&gt;map()&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt; loops, and list comprehensions:&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;random&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;timeit&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TAX_RATE&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;08&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;txns&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;random&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randrange&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&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;100000&lt;/span&gt;&lt;span class=&quot;p&quot;&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;get_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&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;gp&quot;&gt;... &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TAX_RATE&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_prices_with_map&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;list&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;get_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txns&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_prices_with_comprehension&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;get_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&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;txn&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txns&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_prices_with_loop&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;o&quot;&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txn&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;txns&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;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;get_price&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&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;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;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;timeit&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;n&quot;&gt;get_prices_with_map&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;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2.0554370979998566&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeit&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;n&quot;&gt;get_prices_with_comprehension&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;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2.3982384680002724&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeit&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;n&quot;&gt;get_prices_with_loop&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;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3.0531821520007725&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you define three methods that each use a different approach for creating a list. Then, you tell &lt;code&gt;timeit&lt;/code&gt; to run each of those functions 100 times each. &lt;code&gt;timeit&lt;/code&gt; returns the total time it took to run those 100 executions.&lt;/p&gt;
&lt;p&gt;As the code demonstrates, the biggest difference is between the loop-based approach and &lt;code&gt;map()&lt;/code&gt;, with the loop taking 50% longer to execute. Whether or not this matters depends on the needs of your application.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;In this tutorial, you learned how to use a &lt;strong&gt;list comprehension&lt;/strong&gt; in Python to accomplish complex tasks without making your code overly complicated.&lt;/p&gt;
&lt;p&gt;Now you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Simplify loops and &lt;code&gt;map()&lt;/code&gt; calls with declarative &lt;strong&gt;list comprehensions&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Supercharge your comprehensions with &lt;strong&gt;conditional logic&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Create &lt;strong&gt;set&lt;/strong&gt; and &lt;strong&gt;dictionary&lt;/strong&gt; comprehensions&lt;/li&gt;
&lt;li&gt;Determine when code clarity or performance dictates an &lt;strong&gt;alternative approach&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Whenever you have to choose a list creation method, try multiple implementations and consider what&amp;rsquo;s easiest to read and understand in your specific scenario. If performance is important, then you can use profiling tools to give you actionable data instead of relying on hunches or guesses about what works the best.&lt;/p&gt;
&lt;p&gt;Remember that while Python list comprehensions get a lot of attention, your intuition and ability to use data when it counts will help you write clean code that serves the task at hand. This, ultimately, is the key to making your code Pythonic!&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>Cool New Features in Python 3.8</title>
      <id>https://realpython.com/courses/cool-new-features-python-38/</id>
      <link href="https://realpython.com/courses/cool-new-features-python-38/"/>
      <updated>2019-11-05T14:00:00+00:00</updated>
      <summary>What does Python 3.8 bring to the table? Learn about some of the biggest changes and see you how you can best make use of them.</summary>
      <content type="html">
        &lt;p&gt;In this course, you&amp;rsquo;ll get a look into the newest version of Python. On October 14th, 2019 the first official version of &lt;strong&gt;Python 3.8&lt;/strong&gt; became ready.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&amp;rsquo;ll learn about the following:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using &lt;strong&gt;assignment expressions&lt;/strong&gt; to simplify some code constructs&lt;/li&gt;
&lt;li&gt;Enforcing &lt;strong&gt;positional-only arguments&lt;/strong&gt; in your own functions&lt;/li&gt;
&lt;li&gt;Specifying more &lt;strong&gt;precise type hints&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Using &lt;strong&gt;f-strings&lt;/strong&gt; for simpler &lt;strong&gt;debugging&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With a few exceptions, Python 3.8 contains many small improvements over the earlier versions. Towards the end of the course, you’ll see many of these less attention-grabbing changes, as well as a discussion about some of the optimizations that make Python 3.8 faster than its predecessors.&lt;/p&gt;
&lt;p&gt;If you want to learn more, additional resources will be referenced and linked to throughout the 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>Build a Mobile Application With the Kivy Python Framework</title>
      <id>https://realpython.com/mobile-app-kivy-python/</id>
      <link href="https://realpython.com/mobile-app-kivy-python/"/>
      <updated>2019-11-04T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn how to build a mobile application with Python and the Kivy GUI framework. You&#39;ll discover how to develop an application that can run on your desktop as well as your phone. Then, you&#39;ll package your app for iOS, Android, Windows, and macOS.</summary>
      <content type="html">
        &lt;p&gt;These days, developers are highly likely to be working on a mobile or web application. Python doesn&amp;rsquo;t have built-in mobile development capabilities, but there are packages you can use to create mobile applications, like Kivy, &lt;a href=&quot;https://riverbankcomputing.com/software/pyqt/intro&quot;&gt;PyQt&lt;/a&gt;, or even Beeware&amp;rsquo;s &lt;a href=&quot;https://toga.readthedocs.io/en/latest/&quot;&gt;Toga&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;These libraries are all major players in the Python mobile space. However, there are some benefits you&amp;rsquo;ll see if you choose to create mobile applications with &lt;strong&gt;Kivy&lt;/strong&gt;. Not only will your application look the same on all platforms, but you also won&amp;rsquo;t need to compile your code after every change. What&amp;rsquo;s more, you&amp;rsquo;ll be able to use Python&amp;rsquo;s clear syntax to build your applications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this tutorial, you&amp;rsquo;ll learn how to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Work with Kivy widgets&lt;/li&gt;
&lt;li&gt;Lay out the UI&lt;/li&gt;
&lt;li&gt;Add events&lt;/li&gt;
&lt;li&gt;Use the KV language&lt;/li&gt;
&lt;li&gt;Create a calculator application&lt;/li&gt;
&lt;li&gt;Package your application for iOS, Android, Windows, and macOS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This tutorial assumes you&amp;rsquo;re familiar with object-oriented programming. If you&amp;rsquo;re not, then check out &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;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-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;understanding-the-kivy-framework&quot;&gt;Understanding the Kivy Framework&lt;/h2&gt;
&lt;p&gt;Kivy was first released in early 2011. This cross-platform Python framework can be deployed to Windows, Mac, Linux, and Raspberry Pi. It supports &lt;a href=&quot;https://en.wikipedia.org/wiki/Multi-touch&quot;&gt;multitouch&lt;/a&gt; events in addition to regular keyboard and mouse inputs. Kivy even supports GPU acceleration of its graphics, since they&amp;rsquo;re built using OpenGL ES2. The project uses the MIT license, so you can use this library for free and commercial software.&lt;/p&gt;
&lt;p&gt;When you create an application with Kivy, you&amp;rsquo;re creating a &lt;a href=&quot;https://en.wikipedia.org/wiki/Natural_user_interface&quot;&gt;Natural User Interface&lt;/a&gt; or &lt;strong&gt;NUI&lt;/strong&gt;. The idea behind a Natural User Interface is that the user can easily learn how to use your software with little to no instruction.&lt;/p&gt;
&lt;p&gt;Kivy does not attempt to use native controls or widgets. All of its widgets are custom-drawn. This means that Kivy applications will look the same across all platforms. However, it also means that your app&amp;rsquo;s look and feel will differ from your user&amp;rsquo;s native applications. This could be a benefit or a drawback, depending on your audience.&lt;/p&gt;
&lt;h2 id=&quot;installing-kivy&quot;&gt;Installing Kivy&lt;/h2&gt;
&lt;p&gt;Kivy has many dependencies, so it&amp;rsquo;s recommended that you install it into a Python virtual environment. You can use either Python&amp;rsquo;s built-in &lt;a href=&quot;https://docs.python.org/3/library/venv.html&quot;&gt;&lt;code&gt;venv&lt;/code&gt;&lt;/a&gt; library or the &lt;a href=&quot;https://virtualenv.pypa.io/en/latest/&quot;&gt;&lt;code&gt;virtualenv&lt;/code&gt;&lt;/a&gt; package. If you&amp;rsquo;ve never used a Python virtual environment before, then check out &lt;a href=&quot;https://realpython.com/python-virtual-environments-a-primer/&quot;&gt;Python Virtual Environments: A Primer&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how you can create a Python 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; python3 -m venv my_kivy_project
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will copy your Python 3 executable into a folder called &lt;code&gt;my_kivy_project&lt;/code&gt; and add a few other subfolders to that directory.&lt;/p&gt;
&lt;p&gt;To use your virtual environment, you need to activate it. On Mac and Linux, you can do that by executing the following while inside the &lt;code&gt;my_kivy_project&lt;/code&gt; folder:&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; bin/activate
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The command for Windows is similar, but the location of the activate script is inside of the &lt;code&gt;Scripts&lt;/code&gt; folder instead of &lt;code&gt;bin&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now that you have an activated Python virtual environment, you can run &lt;a href=&quot;https://realpython.com/what-is-pip/&quot;&gt;&lt;code&gt;pip&lt;/code&gt;&lt;/a&gt; to install Kivy. On Linux and Mac, you&amp;rsquo;ll run 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; python -m pip install kivy
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;On Windows, installation is a bit more complex. Check out the official documentation for how to install &lt;a href=&quot;https://kivy.org/doc/stable/installation/installation-windows.html#install-win-dist&quot;&gt;Kivy on Windows&lt;/a&gt;. (Mac users can also download a &lt;code&gt;dmg&lt;/code&gt; file and install Kivy that way.)&lt;/p&gt;
&lt;p&gt;If you run into any issues installing Kivy on your platform, then see the Kivy download page for additional &lt;a href=&quot;https://kivy.org/#download&quot;&gt;instructions&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;working-with-kivy-widgets&quot;&gt;Working With Kivy Widgets&lt;/h2&gt;
&lt;p&gt;A &lt;strong&gt;widget&lt;/strong&gt; is an onscreen control that the user will interact with. All graphical user interface toolkits come with a set of widgets. Some common widgets that you may have used include buttons, combo boxes, and tabs. Kivy has many widgets built into its framework.&lt;/p&gt;
&lt;h3 id=&quot;running-a-hello-kivy-program&quot;&gt;Running a &amp;ldquo;Hello, Kivy!&amp;rdquo; Program&lt;/h3&gt;
&lt;p&gt;To see how Kivy works, take a look at the following &amp;ldquo;Hello, World!&amp;rdquo; application:&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;kivy.app&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.label&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Label&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MainApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;App&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;build&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;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;text&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello from Kivy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                      &lt;span class=&quot;n&quot;&gt;size_hint&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;o&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;o&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;pos_hint&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;center_x&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;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;center_y&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;5&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;label&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;s1&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MainApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Every Kivy application needs to subclass &lt;code&gt;App&lt;/code&gt; and override &lt;code&gt;build()&lt;/code&gt;. This is where you&amp;rsquo;ll put your UI code or make calls to other functions that define your UI code. In this case, you create a &lt;code&gt;Label&lt;/code&gt; widget and pass in its &lt;code&gt;text&lt;/code&gt;, &lt;code&gt;size_hint&lt;/code&gt;, and &lt;code&gt;pos_hint&lt;/code&gt;. These last two arguments are not required.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;size_hint&lt;/code&gt; tells Kivy the proportions to use when creating the widget. It takes two numbers:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The first number is the &lt;code&gt;x&lt;/code&gt; size hint and refers to the &lt;strong&gt;width&lt;/strong&gt; of the control.&lt;/li&gt;
&lt;li&gt;The second number is the &lt;code&gt;y&lt;/code&gt; size hint and refers to the &lt;strong&gt;height&lt;/strong&gt; of the control.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Both of these numbers can be anywhere between 0 and 1. The default value for both hints is 1. You can also use &lt;code&gt;pos_hint&lt;/code&gt; to position the widget. In the code block above, you tell Kivy to center the widget on the x and y axes.&lt;/p&gt;
&lt;p&gt;To make the application run, you instantiate your &lt;code&gt;MainApp&lt;/code&gt; class and then call &lt;code&gt;run()&lt;/code&gt;. When you do so, you should see the following on your screen:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/01_mdriscoll_hello_kivy.879d11e41080.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/01_mdriscoll_hello_kivy.879d11e41080.png&quot; width=&quot;802&quot; height=&quot;625&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/01_mdriscoll_hello_kivy.879d11e41080.png&amp;amp;w=200&amp;amp;sig=d5031afebc246d3b428e37946b4451638982493b 200w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/01_mdriscoll_hello_kivy.879d11e41080.png&amp;amp;w=401&amp;amp;sig=c69d4068b30c3e2cd42dfaf25a03d7880c7c65d9 401w, https://files.realpython.com/media/01_mdriscoll_hello_kivy.879d11e41080.png 802w&quot; sizes=&quot;75vw&quot; alt=&quot;Hello World in Kivy&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Kivy also outputs a lot of text to &lt;code&gt;stdout&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;go&quot;&gt;[INFO   ] [Logger      ] Record log in /home/mdriscoll/.kivy/logs/kivy_19-06-07_2.txt&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Kivy        ] v1.11.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Kivy        ] Installed at &amp;quot;/home/mdriscoll/code/test/lib/python3.6/site-packages/kivy/__init__.py&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Python      ] v3.6.7 (default, Oct 22 2018, 11:32:17)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[GCC 8.2.0]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Python      ] Interpreter at &amp;quot;/home/mdriscoll/code/test/bin/python&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Factory     ] 184 symbols loaded&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Image       ] Providers: img_tex, img_dds, img_sdl2, img_gif (img_pil, img_ffpyplayer ignored)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Text        ] Provider: sdl2([&amp;#39;text_pango&amp;#39;] ignored)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Window      ] Provider: sdl2([&amp;#39;window_egl_rpi&amp;#39;] ignored)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [GL          ] Using the &amp;quot;OpenGL&amp;quot; graphics system&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [GL          ] Backend used &amp;lt;sdl2&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [GL          ] OpenGL version &amp;lt;b&amp;#39;4.6.0 NVIDIA 390.116&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [GL          ] OpenGL vendor &amp;lt;b&amp;#39;NVIDIA Corporation&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [GL          ] OpenGL renderer &amp;lt;b&amp;#39;NVS 310/PCIe/SSE2&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [GL          ] OpenGL parsed version: 4, 6&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [GL          ] Shading version &amp;lt;b&amp;#39;4.60 NVIDIA&amp;#39;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [GL          ] Texture max size &amp;lt;16384&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [GL          ] Texture max units &amp;lt;32&amp;gt;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Window      ] auto add sdl2 input provider&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Window      ] virtual keyboard not allowed, single mode, not docked&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [Base        ] Start application main loop&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[INFO   ] [GL          ] NPOT texture support is available&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is useful for debugging your application.&lt;/p&gt;
&lt;p&gt;Next, you&amp;rsquo;ll try adding an &lt;code&gt;Image&lt;/code&gt; widget and see how that differs from a &lt;code&gt;Label&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;displaying-an-image&quot;&gt;Displaying an Image&lt;/h3&gt;
&lt;p&gt;Kivy has a couple of different image-related widgets to choose from. You can use &lt;code&gt;Image&lt;/code&gt; to load local images from your hard drive or &lt;code&gt;AsyncImage&lt;/code&gt; to load an image from a URL. For this example, you&amp;rsquo;ll stick with the standard &lt;code&gt;Image&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.app&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.image&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MainApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;App&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;build&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;img&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;source&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/path/to/real_python.png&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;size_hint&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;o&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;pos_hint&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;center_x&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;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;center_y&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;5&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;img&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;s1&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MainApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you import &lt;code&gt;Image&lt;/code&gt; from the &lt;code&gt;kivy.uix.image&lt;/code&gt; sub-package. The &lt;code&gt;Image&lt;/code&gt; class takes a lot of different parameters, but the one that you want to use is &lt;code&gt;source&lt;/code&gt;. This tells Kivy which image to load. Here, you pass a fully-qualified path to the image. The rest of the code is the same as what you saw in the previous example.&lt;/p&gt;
&lt;p&gt;When you run this code, you&amp;rsquo;ll see something like the following:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/02_mdriscoll_hello_image.607fbd03a04d.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/02_mdriscoll_hello_image.607fbd03a04d.png&quot; width=&quot;802&quot; height=&quot;625&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/02_mdriscoll_hello_image.607fbd03a04d.png&amp;amp;w=200&amp;amp;sig=a51c04666978ded099696482f5960b7506619a1d 200w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/02_mdriscoll_hello_image.607fbd03a04d.png&amp;amp;w=401&amp;amp;sig=4d5d8ce1f721bb6f1978b54dc4a405b1a20afec9 401w, https://files.realpython.com/media/02_mdriscoll_hello_image.607fbd03a04d.png 802w&quot; sizes=&quot;75vw&quot; alt=&quot;Showing an image with Kivy&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The text from the previous example has been replaced with an image.&lt;/p&gt;
&lt;p&gt;Now you&amp;rsquo;ll learn how to add and arrange multiple widgets in your application.&lt;/p&gt;
&lt;h2 id=&quot;laying-out-the-ui&quot;&gt;Laying Out the UI&lt;/h2&gt;
&lt;p&gt;Each GUI framework that you use has its own method of arranging widgets. For example, in &lt;a href=&quot;https://realpython.com/python-gui-with-wxpython/&quot;&gt;wxPython&lt;/a&gt; you&amp;rsquo;ll use sizers, while in Tkinter you use a layout or geometry manager. With Kivy, you&amp;rsquo;ll use &lt;strong&gt;Layouts&lt;/strong&gt;. There are several different types of Layouts that you can use. Here are some of the most common ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BoxLayout&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;FloatLayout&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GridLayout&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can search Kivy&amp;rsquo;s &lt;a href=&quot;https://kivy.org/doc/stable/api-kivy.uix.layout.html&quot;&gt;documentation&lt;/a&gt; for a full list of available Layouts. You can also look in &lt;code&gt;kivy.uix&lt;/code&gt; for the actual source code.&lt;/p&gt;
&lt;p&gt;Try out the &lt;code&gt;BoxLayout&lt;/code&gt; with 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.app&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.button&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.boxlayout&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BoxLayout&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;red&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;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;green&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;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;blue&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;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;purple&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;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&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;HBoxLayoutExample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;App&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;build&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;layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BoxLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;padding&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;n&quot;&gt;colors&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;red&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;green&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;blue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;purple&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;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;btn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&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;s2&quot;&gt;&amp;quot;Button #&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;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;n&quot;&gt;background_color&lt;/span&gt;&lt;span class=&quot;o&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;choice&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;colors&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;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_widget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;btn&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;layout&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;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;HBoxLayoutExample&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you import &lt;code&gt;BoxLayout&lt;/code&gt; from &lt;code&gt;kivy.uix.boxlayout&lt;/code&gt; and instantiate it. Then you create a list of colors, which are themselves lists of &lt;a href=&quot;https://en.wikipedia.org/wiki/RGB_color_model&quot;&gt;Red-Blue-Green (RGB)&lt;/a&gt; colors. Finally, you loop over a &lt;a href=&quot;https://realpython.com/python-range/&quot;&gt;&lt;code&gt;range&lt;/code&gt;&lt;/a&gt; of 5, creating a button &lt;code&gt;btn&lt;/code&gt; for each iteration. To make things a bit more fun, you set the &lt;code&gt;background_color&lt;/code&gt; of the button to a random color. You then add the button to your layout with &lt;code&gt;layout.add_widget(btn)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When you run this code, you&amp;rsquo;ll see something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/kivy_hboxlayout.a8ac0394109e.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/kivy_hboxlayout.a8ac0394109e.png&quot; width=&quot;802&quot; height=&quot;625&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/kivy_hboxlayout.a8ac0394109e.png&amp;amp;w=200&amp;amp;sig=f2281e2abc44db9763df3071e84287295ad7d70a 200w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/kivy_hboxlayout.a8ac0394109e.png&amp;amp;w=401&amp;amp;sig=b494c0c4f3fae3c74a58781870defdabe27a2e7b 401w, https://files.realpython.com/media/kivy_hboxlayout.a8ac0394109e.png 802w&quot; sizes=&quot;75vw&quot; alt=&quot;Using a Horizontal BoxLayout in Kivy&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are 5 randomly-colored buttons, one for each iteration of your &lt;a href=&quot;https://realpython.com/courses/python-for-loop/&quot;&gt;&lt;code&gt;for&lt;/code&gt;&lt;/a&gt; loop.&lt;/p&gt;
&lt;p&gt;When you create a layout, there are a few arguments you should know:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;padding&lt;/code&gt;:&lt;/strong&gt; You can specify the &lt;code&gt;padding&lt;/code&gt; in pixels between the layout and its children in one of three ways:&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;A four-argument list:&lt;/strong&gt; [&lt;code&gt;padding_left&lt;/code&gt;, &lt;code&gt;padding_top&lt;/code&gt;, &lt;code&gt;padding_right&lt;/code&gt;, &lt;code&gt;padding_bottom&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A two-argument list:&lt;/strong&gt; [&lt;code&gt;padding_horizontal&lt;/code&gt;, &lt;code&gt;padding_vertical&lt;/code&gt;]&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A singular argument:&lt;/strong&gt; &lt;code&gt;padding=10&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;spacing&lt;/code&gt;:&lt;/strong&gt; You can add space between the children widgets with this argument.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;orientation&lt;/code&gt;:&lt;/strong&gt; You can change the default &lt;code&gt;orientation&lt;/code&gt; of the &lt;code&gt;BoxLayout&lt;/code&gt; from horizontal to vertical.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;adding-events&quot;&gt;Adding Events&lt;/h2&gt;
&lt;p&gt;Like most GUI toolkits, Kivy is mostly &lt;strong&gt;event-based&lt;/strong&gt;. The framework responds to user keypresses, mouse events, and touch events. Kivy has the concept of a &lt;strong&gt;Clock&lt;/strong&gt; that you can use to schedule function calls for some time in the future.&lt;/p&gt;
&lt;p&gt;Kivy also has the concept of &lt;a href=&quot;https://kivy.org/doc/stable/api-kivy.properties.html&quot;&gt;&lt;code&gt;Properties&lt;/code&gt;&lt;/a&gt;, which works with the &lt;a href=&quot;https://kivy.org/doc/stable/api-kivy.event.html#kivy.event.EventDispatcher&quot;&gt;&lt;code&gt;EventDispatcher&lt;/code&gt;&lt;/a&gt;. Properties help you do validation checking. They also let you fire events whenever a widget changes its size or position.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s add a &lt;strong&gt;button event&lt;/strong&gt; to your button code from 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;kivy.app&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.button&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MainApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;App&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;build&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;button&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&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;s1&quot;&gt;&amp;#39;Hello from Kivy&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                        &lt;span class=&quot;n&quot;&gt;size_hint&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;o&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;o&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;pos_hint&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;center_x&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;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;center_y&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;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_press&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;on_press_button&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_press_button&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;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&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;s1&quot;&gt;&amp;#39;You pressed the button!&amp;#39;&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&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;s1&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MainApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you call &lt;code&gt;button.bind()&lt;/code&gt; and link the &lt;code&gt;on_press&lt;/code&gt; event to &lt;code&gt;MainApp.on_press_button()&lt;/code&gt;. This method implicitly takes in the widget &lt;code&gt;instance&lt;/code&gt;, which is the &lt;code&gt;button&lt;/code&gt; object itself. Finally, a message will print to &lt;code&gt;stdout&lt;/code&gt; whenever the user presses your button.&lt;/p&gt;
&lt;h2 id=&quot;using-the-kv-language&quot;&gt;Using the KV Language&lt;/h2&gt;
&lt;p&gt;Kivy also provides a design language called &lt;strong&gt;KV&lt;/strong&gt; that you can use with your Kivy applications. The KV language lets you separate your interface design from the application&amp;rsquo;s logic. This follows the &lt;a href=&quot;http://en.wikipedia.org/wiki/Separation_of_concerns&quot;&gt;separation of concerns&lt;/a&gt; principle and is part of the &lt;a href=&quot;https://realpython.com/the-model-view-controller-mvc-paradigm-summarized-with-legos/&quot;&gt;Model-View-Controller&lt;/a&gt; architectural pattern. You can update the previous example to use the KV language:&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;kivy.app&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.button&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ButtonApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;App&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;build&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;Button&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_press_button&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;s1&quot;&gt;&amp;#39;You pressed the button!&amp;#39;&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;s1&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ButtonApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code might look a bit odd at first glance, as it creates a &lt;code&gt;Button&lt;/code&gt; without setting any of its attributes or binding it to any events. What&amp;rsquo;s happening here is that Kivy will automatically look for a file that has the same name as the class in lowercase, without the &lt;code&gt;App&lt;/code&gt; part of the class name.&lt;/p&gt;
&lt;p&gt;In this case, the class name is &lt;code&gt;ButtonApp&lt;/code&gt;, so Kivy will look for a file named &lt;code&gt;button.kv&lt;/code&gt;. If that file exists and is properly formatted, then Kivy will use it to load up the UI. Go ahead and create this file and add the following code:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&amp;lt;Button&amp;gt;:
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;    text: &amp;#39;Press me&amp;#39;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;    size_hint: (.5, .5)
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;    pos_hint: {&amp;#39;center_x&amp;#39;: .5, &amp;#39;center_y&amp;#39;: .5}
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;    on_press: app.on_press_button()
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s what each line does:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 1&lt;/strong&gt; matches the &lt;code&gt;Button&lt;/code&gt; call in your Python code. It tells Kivy to look into the instantiated object for a button definition.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 2&lt;/strong&gt; sets the button&amp;rsquo;s &lt;code&gt;text&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 3&lt;/strong&gt; sets the width and height with &lt;code&gt;size_hint&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 4&lt;/strong&gt; sets the button&amp;rsquo;s position with &lt;code&gt;pos_hint&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 5&lt;/strong&gt; sets the &lt;code&gt;on_press&lt;/code&gt; event handler. To tell Kivy where the event handler is, you use &lt;code&gt;app.on_press_button()&lt;/code&gt;. Here, Kivy knows will look in the &lt;code&gt;Application&lt;/code&gt; class for a method called &lt;code&gt;.on_press_button()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can set up all of your widgets and layouts inside one or more KV language files. The KV language also supports importing Python modules in KV, creating dynamic classes, and much more. For full details, check out Kivy&amp;rsquo;s &lt;a href=&quot;https://kivy.org/doc/stable/guide/lang.html&quot;&gt;guide to the KV Language&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now you&amp;rsquo;re ready to create a real application!&lt;/p&gt;
&lt;h2 id=&quot;creating-a-kivy-application&quot;&gt;Creating a Kivy Application&lt;/h2&gt;
&lt;p&gt;One of the best ways to learn a new skill is by creating something useful. With that in mind, you&amp;rsquo;ll use Kivy to build a calculator that supports the following operations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Addition&lt;/li&gt;
&lt;li&gt;Subtraction&lt;/li&gt;
&lt;li&gt;Multiplication&lt;/li&gt;
&lt;li&gt;Division&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this application, you&amp;rsquo;ll need a series of buttons in some kind of layout. You&amp;rsquo;ll also need a box along the top of your app to display the equations and their results. Here&amp;rsquo;s a sketch of your calculator:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/kvcalc_mock.637f132ddd19.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/kvcalc_mock.637f132ddd19.png&quot; width=&quot;332&quot; height=&quot;441&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/kvcalc_mock.637f132ddd19.png&amp;amp;w=83&amp;amp;sig=24baffc9b90c5ebfd76fa4ccd64d54c213d862bb 83w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/kvcalc_mock.637f132ddd19.png&amp;amp;w=166&amp;amp;sig=137bbfbc04a536469fdf53a307523f7de67a4d84 166w, https://files.realpython.com/media/kvcalc_mock.637f132ddd19.png 332w&quot; sizes=&quot;75vw&quot; alt=&quot;Kivy Calculator Mockup&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now that you have a goal for the UI, you can go ahead and write the 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;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.app&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.boxlayout&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BoxLayout&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.button&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.textinput&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TextInput&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MainApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;App&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;build&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;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;operators&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;/&amp;quot;&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;s2&quot;&gt;&amp;quot;+&amp;quot;&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;lineno&quot;&gt; 9 &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;last_was_operator&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;lineno&quot;&gt;10 &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;last_button&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;lineno&quot;&gt;11 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;main_layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BoxLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;orientation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;vertical&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;solution&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TextInput&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;multiline&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;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;n&quot;&gt;halign&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;right&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;font_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;55&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;main_layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_widget&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;solution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;buttons&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;lineno&quot;&gt;17 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;7&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;9&amp;quot;&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;lineno&quot;&gt;18 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;4&amp;quot;&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;s2&quot;&gt;&amp;quot;6&amp;quot;&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;lineno&quot;&gt;19 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;3&amp;quot;&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;lineno&quot;&gt;20 &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;s2&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;C&amp;quot;&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;lineno&quot;&gt;21 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;        &lt;span class=&quot;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;buttons&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;h_layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BoxLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;            &lt;span class=&quot;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;row&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;n&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &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;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;                    &lt;span class=&quot;n&quot;&gt;pos_hint&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;center_x&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;center_y&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &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;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_press&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;on_button_press&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;                &lt;span class=&quot;n&quot;&gt;h_layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_widget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31 &lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;main_layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_widget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;equals_button&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;34 &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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos_hint&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;center_x&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;center_y&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;35 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;36 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;equals_button&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_press&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;on_solution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;37 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;main_layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_widget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;equals_button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;38 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;39 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main_layout&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s how your calculator code works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;In lines 8 to 10&lt;/strong&gt;, you create a list of &lt;code&gt;operators&lt;/code&gt; and a couple of handy values, &lt;code&gt;last_was_operator&lt;/code&gt; and &lt;code&gt;last_button&lt;/code&gt;, that you&amp;rsquo;ll use later on.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In lines 11 to 15&lt;/strong&gt;, you create a top-level layout &lt;code&gt;main_layout&lt;/code&gt; and add a read-only &lt;code&gt;TextInput&lt;/code&gt; widget to it.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In lines 16 to 21&lt;/strong&gt;, you create a nested list of lists containing most of your &lt;code&gt;buttons&lt;/code&gt; for the calculator.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In line 22&lt;/strong&gt;, you start a &lt;code&gt;for&lt;/code&gt; loop over those &lt;code&gt;buttons&lt;/code&gt;. For each nested list you&amp;rsquo;ll do the following:&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;In line 23&lt;/strong&gt;, you create a &lt;code&gt;BoxLayout&lt;/code&gt; with a horizontal orientation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In line 24&lt;/strong&gt;, you start another &lt;code&gt;for&lt;/code&gt; loop over the items in the nested list.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In lines 25 to 39&lt;/strong&gt;, you create the buttons for the row, bind them to an event handler, and add the buttons to the horizontal &lt;code&gt;BoxLayout&lt;/code&gt; from line 23.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In line 31&lt;/strong&gt;, you add this layout to &lt;code&gt;main_layout&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In lines 33 to 37&lt;/strong&gt;, you create the equals button (&lt;code&gt;=&lt;/code&gt;), bind it to an event handler, and add it to &lt;code&gt;main_layout&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The next step is to create the &lt;code&gt;.on_button_press()&lt;/code&gt; event handler. Here&amp;rsquo;s what that code looks like:&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;41 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_button_press&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;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;42 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;current&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;solution&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;lineno&quot;&gt;43 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;button_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instance&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;lineno&quot;&gt;44 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;45 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;46 &lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Clear the solution widget&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;47 &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;solution&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;s2&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;48 &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;lineno&quot;&gt;49 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;50 &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;last_was_operator&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_text&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;operators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;51 &lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# Don&amp;#39;t add two operators right after each other&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;52 &lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;53 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&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;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_text&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;operators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;54 &lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;# First character cannot be an operator&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;55 &lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;56 &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;lineno&quot;&gt;57 &lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;new_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_text&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;58 &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;solution&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;new_text&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;59 &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;last_button&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_text&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;60 &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;last_was_operator&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;last_button&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;operators&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Most of the widgets in your application will call &lt;code&gt;.on_button_press()&lt;/code&gt;. Here&amp;rsquo;s how it works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 41&lt;/strong&gt; takes the &lt;code&gt;instance&lt;/code&gt; argument so you can access which widget called the function.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 42 and 43&lt;/strong&gt; extract and store the value of the &lt;code&gt;solution&lt;/code&gt; and the button &lt;code&gt;text&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 45 to 47&lt;/strong&gt; check to see which button was pressed. If the user pressed &lt;code&gt;C&lt;/code&gt;, then you&amp;rsquo;ll clear the &lt;code&gt;solution&lt;/code&gt;. Otherwise, move on to the &lt;code&gt;else&lt;/code&gt; statement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 49&lt;/strong&gt; checks if the solution has any pre-existing value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 50 to 52&lt;/strong&gt; check if the last button pressed was an operator button. If it was, then &lt;code&gt;solution&lt;/code&gt; won&amp;rsquo;t be updated. This is to prevent the user from having two operators in a row. For example, &lt;code&gt;1 */&lt;/code&gt; is not a valid statement.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 53 to 55&lt;/strong&gt; check to see if the first character is an operator. If it is, then &lt;code&gt;solution&lt;/code&gt; won&amp;rsquo;t be updated, since the first value can&amp;rsquo;t be an operator value.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 56 to 58&lt;/strong&gt; drop to the &lt;code&gt;else&lt;/code&gt; clause. If none of the previous conditions are met, then update &lt;code&gt;solution&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 59&lt;/strong&gt; sets &lt;code&gt;last_button&lt;/code&gt; to the label of the last button pressed.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 60&lt;/strong&gt; sets &lt;code&gt;last_was_operator&lt;/code&gt; to &lt;code&gt;True&lt;/code&gt; or &lt;code&gt;False&lt;/code&gt; depending on whether or not it was an operator character.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last bit of code to write is &lt;code&gt;.on_solution()&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;lineno&quot;&gt;62 &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_solution&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;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;63 &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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;solution&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;lineno&quot;&gt;64 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;65 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;solution&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;nb&quot;&gt;eval&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;solution&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;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;66 &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;solution&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;solution&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once again, you grab the current text from &lt;code&gt;solution&lt;/code&gt; and use Python&amp;rsquo;s built-in &lt;code&gt;eval()&lt;/code&gt; to execute it. If the user created a formula like &lt;code&gt;1+2&lt;/code&gt;, then &lt;code&gt;eval()&lt;/code&gt; will run your code and return the result. Finally, you set the result as the new value for the &lt;code&gt;solution&lt;/code&gt; widget.&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;eval()&lt;/code&gt; is somewhat &lt;a href=&quot;https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html&quot;&gt;dangerous&lt;/a&gt; because it can run arbitrary code. Most developers avoid using it because of that fact. However, since you&amp;rsquo;re only allowing integers, operators, and the period as input to &lt;code&gt;eval()&lt;/code&gt;, it&amp;rsquo;s safe to use in this context.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;When you run this code, your application will look like this on a desktop computer:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/kvcalc.20e9d0008d8f.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/kvcalc.20e9d0008d8f.png&quot; width=&quot;802&quot; height=&quot;625&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/kvcalc.20e9d0008d8f.png&amp;amp;w=200&amp;amp;sig=14bb299a8782091ae35f060237c79f97208dccd8 200w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/kvcalc.20e9d0008d8f.png&amp;amp;w=401&amp;amp;sig=230ee2d4a7c2b0596e48fd9e94c1a284b26cdfbf 401w, https://files.realpython.com/media/kvcalc.20e9d0008d8f.png 802w&quot; sizes=&quot;75vw&quot; alt=&quot;Kivy Calculator&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To see the full code for this example, expand the code block below.&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card4a6b31&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;#collapse4a6b31&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse4a6b31&quot;&gt;Complete Code Example&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse4a6b31&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse4a6b31&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse4a6b31&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card4a6b31&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;p&gt;Here&amp;rsquo;s the full code for the calculator:&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;kivy.app&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.boxlayout&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BoxLayout&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.button&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;kivy.uix.textinput&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TextInput&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MainApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;App&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;build&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;operators&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;/&amp;quot;&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;s2&quot;&gt;&amp;quot;+&amp;quot;&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_was_operator&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;last_button&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;n&quot;&gt;main_layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BoxLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;orientation&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;vertical&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;solution&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TextInput&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;multiline&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;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;n&quot;&gt;halign&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;right&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;font_size&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;55&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;main_layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_widget&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;solution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;buttons&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;s2&quot;&gt;&amp;quot;7&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;9&amp;quot;&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;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;4&amp;quot;&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;s2&quot;&gt;&amp;quot;6&amp;quot;&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;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;2&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;3&amp;quot;&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;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;s2&quot;&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;C&amp;quot;&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;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;buttons&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;h_layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BoxLayout&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;row&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&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;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;pos_hint&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;center_x&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;center_y&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&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;button&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_press&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;on_button_press&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;h_layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_widget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;main_layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_widget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;h_layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;n&quot;&gt;equals_button&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Button&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;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;pos_hint&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;center_x&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;center_y&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.5&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;equals_button&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;on_press&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;on_solution&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;main_layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;add_widget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;equals_button&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;main_layout&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_button_press&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;instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;current&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;solution&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;n&quot;&gt;button_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;instance&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;C&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Clear the solution widget&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;solution&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;s2&quot;&gt;&amp;quot;&amp;quot;&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;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&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;last_was_operator&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_text&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;operators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;# Don&amp;#39;t add two operators right after each other&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&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;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_text&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;operators&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;c1&quot;&gt;# First character cannot be an operator&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;return&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;new_text&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_text&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;solution&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;new_text&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;last_button&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;button_text&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;last_was_operator&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;last_button&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;operators&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;on_solution&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;instance&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;solution&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;solution&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;nb&quot;&gt;eval&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;solution&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;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;solution&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;solution&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;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MainApp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&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;/pre&gt;&lt;/div&gt;

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

&lt;/div&gt;
&lt;p&gt;It&amp;rsquo;s time to deploy your application!&lt;/p&gt;
&lt;h2 id=&quot;packaging-your-app-for-android&quot;&gt;Packaging Your App for Android&lt;/h2&gt;
&lt;p&gt;Now that you&amp;rsquo;ve finished the code for your application, you can share it with others. One great way to do that is to turn your code into an application that can run on your Android phone. To accomplish this, first you&amp;rsquo;ll need to install a package called &lt;code&gt;buildozer&lt;/code&gt; with &lt;code&gt;pip&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; pip install buildozer
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, create a new folder and navigate to it in your terminal. Once you&amp;rsquo;re there, you&amp;rsquo;ll need to run 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; buildozer init
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will create a &lt;code&gt;buildozer.spec&lt;/code&gt; file that you&amp;rsquo;ll use to configure your build. For this example, you can edit the first few lines of the spec file as follows:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;[app]

# (str) Title of your application
title = KvCalc

# (str) Package name
package.name = kvcalc

# (str) Package domain (needed for android/ios packaging)
package.domain = org.kvcalc
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Feel free to browse the rest of the file to see what else you can change.&lt;/p&gt;
&lt;p&gt;At this point, you&amp;rsquo;re almost ready to build your application, but first, you&amp;rsquo;ll want to install the &lt;a href=&quot;https://buildozer.readthedocs.io/en/latest/installation.html#targeting-android&quot;&gt;dependencies&lt;/a&gt; for &lt;code&gt;buildozer&lt;/code&gt;. Once those are installed, copy your calculator application into your new folder and rename it to &lt;code&gt;main.py&lt;/code&gt;. This is required by &lt;code&gt;buildozer&lt;/code&gt;. If you don&amp;rsquo;t have the file named correctly, then the build will fail.&lt;/p&gt;
&lt;p&gt;Now you can run 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; buildozer -v android debug
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The build step takes a long time! On my machine, it took 15 to 20 minutes. Depending on your hardware, it may take even longer, so feel free to grab a cup of coffee or go for a run while you wait. &lt;code&gt;Buildozer&lt;/code&gt; will download whatever Android SDK pieces it needs during the build process. If everything goes according to plan, then you&amp;rsquo;ll have a file named something like &lt;code&gt;kvcalc-0.1-debug.apk&lt;/code&gt; in your &lt;code&gt;bin&lt;/code&gt; folder.&lt;/p&gt;
&lt;p&gt;The next step is to connect your Android phone to your computer and copy the &lt;code&gt;apk&lt;/code&gt; file to it. Then you can open the file browser on your phone and click on the &lt;code&gt;apk&lt;/code&gt; file. Android should ask you if you&amp;rsquo;d like to install the application. You may see a warning since the app was downloaded from outside Google Play, but you should still be able to install it.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the calculator running on my Samsung S9:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/KvCalc2.c7cedde01dcf.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-33&quot; src=&quot;https://files.realpython.com/media/KvCalc2.c7cedde01dcf.jpg&quot; width=&quot;340&quot; height=&quot;700&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/KvCalc2.c7cedde01dcf.jpg&amp;amp;w=85&amp;amp;sig=41eb184190792f53dfb7d25db4a07ef98872acdb 85w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/KvCalc2.c7cedde01dcf.jpg&amp;amp;w=170&amp;amp;sig=85284c9ec0b51148fc7de27e3d335d8bd2edd1d6 170w, https://files.realpython.com/media/KvCalc2.c7cedde01dcf.jpg 340w&quot; sizes=&quot;75vw&quot; alt=&quot;Kivy Calculator Running on Android Phone&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;buildozer&lt;/code&gt; tool has several other commands you can use. Check out the &lt;a href=&quot;https://buildozer.readthedocs.io/en/latest/index.html&quot;&gt;documentation&lt;/a&gt; to see what else you can do.&lt;/p&gt;
&lt;p&gt;You can also package the app using &lt;code&gt;python-for-android&lt;/code&gt; if you need more fine-grained control. You won&amp;rsquo;t cover this here, but if you&amp;rsquo;re interested, check out the project&amp;rsquo;s &lt;a href=&quot;https://python-for-android.readthedocs.io/en/latest/quickstart/&quot;&gt;quickstart&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;packaging-your-app-for-ios&quot;&gt;Packaging Your App for iOS&lt;/h2&gt;
&lt;p&gt;The instructions for building an application for iOS are a bit more complex than Android. For the most up-to-date information, you should always use Kivy&amp;rsquo;s official packaging &lt;a href=&quot;https://kivy.org/doc/stable/guide/packaging-ios.html&quot;&gt;documentation&lt;/a&gt;. You&amp;rsquo;ll need to run the following commands before you can package your application for iOS on your Mac:&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; brew install autoconf automake libtool pkg-config
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; brew link libtool
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; sudo easy_install pip
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; sudo pip install &lt;span class=&quot;nv&quot;&gt;Cython&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;==&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;.29.10
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once those are all installed successfully, you&amp;rsquo;ll need to compile the distribution using the following commands:&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; git clone git://github.com/kivy/kivy-ios
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;cd&lt;/span&gt; kivy-ios
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./toolchain.py build python3 kivy
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you get an error that says &lt;code&gt;iphonesimulator&lt;/code&gt; can&amp;rsquo;t be found, then see this &lt;a href=&quot;https://stackoverflow.com/questions/39564420/i-get-xcrun-error-sdk-iphonesimulator-cannot-be-located-when-running-the-t&quot;&gt;StackOverflow answer&lt;/a&gt; for ways to solve that issue. Then try running the above commands again.&lt;/p&gt;
&lt;p&gt;If you run into SSL errors, then you probably don&amp;rsquo;t have Python&amp;rsquo;s OpenSSL setup. This command should fix that:&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;cd&lt;/span&gt; /Applications/Python&lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;&lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;.7/
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; ./Install&lt;span class=&quot;se&quot;&gt;\ &lt;/span&gt;Certificates.command
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now go back and try running the &lt;code&gt;toolchain&lt;/code&gt; command again.&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve run all the previous commands successfully, you can create your Xcode project using the &lt;code&gt;toolchain&lt;/code&gt; script. Your main application&amp;rsquo;s entry point &lt;em&gt;must&lt;/em&gt; be named &lt;code&gt;main.py&lt;/code&gt; before you create the Xcode project. Here is the command you&amp;rsquo;ll 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;go&quot;&gt;./toolchain.py create &amp;lt;title&amp;gt; &amp;lt;app_directory&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There should be a directory named &lt;code&gt;title&lt;/code&gt; with your Xcode project in it. Now you can open that project in Xcode and work on it from there. Note that if you want to submit your application to the App Store, then you&amp;rsquo;ll have to create a developer account at &lt;a href=&quot;https://developer.apple.com/&quot;&gt;developer.apple.com&lt;/a&gt; and pay their yearly fee.&lt;/p&gt;
&lt;h2 id=&quot;packaging-your-app-for-windows&quot;&gt;Packaging Your App for Windows&lt;/h2&gt;
&lt;p&gt;You can package your Kivy application for Windows using PyInstaller. If you&amp;rsquo;ve never used it before, then check out &lt;a href=&quot;https://realpython.com/pyinstaller-python/&quot;&gt;Using PyInstaller to Easily Distribute Python Applications&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can install PyInstaller using &lt;code&gt;pip&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; pip install pyinstaller
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The following command will package your application:&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; pyinstaller main.py -w
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This command will create a Windows executable and several other files. The &lt;code&gt;-w&lt;/code&gt; argument tells PyInstaller that this is a windowed application, rather than a command-line application. If you&amp;rsquo;d rather have PyInstaller create a single executable file, then you can pass in the &lt;code&gt;--onefile&lt;/code&gt; argument in addition to &lt;code&gt;-w&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;packaging-your-app-for-macos&quot;&gt;Packaging Your App for macOS&lt;/h2&gt;
&lt;p&gt;You can use &lt;a href=&quot;https://www.pyinstaller.org/&quot;&gt;PyInstaller&lt;/a&gt; to create a Mac executable just like you did for Windows. The only requirement is that you run this command on a Mac:&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; pyinstaller main.py -w --onefile
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will create a single file executable in the &lt;code&gt;dist&lt;/code&gt; folder. The executable will be the same name as the Python file that you passed to PyInstaller. If you&amp;rsquo;d like to reduce the file size of the executable, or you&amp;rsquo;re using GStreamer in your application, then check out Kivy&amp;rsquo;s &lt;a href=&quot;https://kivy.org/doc/stable/guide/packaging-osx.html&quot;&gt;packaging page for macOS&lt;/a&gt; for more information.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Kivy is a really interesting GUI framework that you can use to create desktop user interfaces and mobile applications on both iOS and Android. Kivy applications will not look like the native apps on any platform. This can be an advantage if you want your application to look and feel different from the competition!&lt;/p&gt;
&lt;p&gt;In this tutorial, you learned the basics of Kivy including how to add widgets, hook up events, lay out multiple widgets, and use the KV language. Then you created your first Kivy application and learned how to distribute it on other platforms, including mobile!&lt;/p&gt;
&lt;p&gt;There are many widgets and concepts about Kivy that you didn&amp;rsquo;t cover here, so be sure to check out Kivy&amp;rsquo;s &lt;a href=&quot;https://kivy.org&quot;&gt;website&lt;/a&gt; for tutorials, sample applications, and much more.&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;To learn more about Kivy, check out these resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://kivy.org/doc/stable/guide/basic.html&quot;&gt;Kivy Programming Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://kivy.org/doc/stable/guide/packaging.html&quot;&gt;Kivy Packaging Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://likegeeks.com/kivy-tutorial/&quot;&gt;Build Desktop GUI Apps Using Python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To see how you might create a desktop application with another Python GUI framework, check out &lt;a href=&quot;https://realpython.com/python-gui-with-wxpython/&quot;&gt;How to Build a Python GUI Application With wxPython&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>Python REST APIs With Flask, Connexion, and SQLAlchemy – Part 4</title>
      <id>https://realpython.com/flask-connexion-rest-api-part-4/</id>
      <link href="https://realpython.com/flask-connexion-rest-api-part-4/"/>
      <updated>2019-10-30T14:00:00+00:00</updated>
      <summary>In Part 4 of this series, you&#39;ll learn how to create a Single-Page Application (SPA) to interface with the REST API backend that you built in Part 3. Your SPA will use HTML, CSS, and JavaScript to present this REST API to a user as a browser-based web application.</summary>
      <content type="html">
        &lt;p&gt;In &lt;a href=&quot;https://realpython.com/flask-connexion-rest-api-part-3/&quot;&gt;Part 3&lt;/a&gt; of this series, you added relationships to the REST API and to the database that supports it. This gave you a powerful tool you can use to build interesting programs that send persistent data, as well as the relationships between that data, to a database system. Having a REST API gives you the ability to create a &lt;a href=&quot;https://en.wikipedia.org/wiki/Single-page_application&quot;&gt;Single-Page Application (SPA)&lt;/a&gt; with HTML, CSS, and JavaScript. This is a good starting point before you make the jump to more powerful front-end frameworks, like Angular or React.&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;Structure an &lt;strong&gt;HTML&lt;/strong&gt; file to act as the template of a single-page web application&lt;/li&gt;
&lt;li&gt;Use &lt;a href=&quot;https://en.wikipedia.org/wiki/Cascading_Style_Sheets&quot;&gt;Cascading Style Sheets (CSS)&lt;/a&gt; to style the presentation of an application&lt;/li&gt;
&lt;li&gt;Use native &lt;strong&gt;JavaScript&lt;/strong&gt; to add interactivity to an application&lt;/li&gt;
&lt;li&gt;Use JavaScript to make HTTP &lt;a href=&quot;https://en.wikipedia.org/wiki/Ajax_(programming)&quot;&gt;AJAX&lt;/a&gt; requests to the REST API you developed in &lt;a href=&quot;https://realpython.com/flask-connexion-rest-api-part-3/&quot;&gt;Part 3&lt;/a&gt; of this series&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can get all of the code you&amp;rsquo;ll see in this tutorial at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/rest-api-flask-series/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-rest-api-flask-series&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to learn about Python REST APIs with Flask, Connexion, and SQLAlchemy in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;who-this-article-is-for&quot;&gt;Who This Article Is For&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://realpython.com/flask-connexion-rest-api/&quot;&gt;Part 1&lt;/a&gt; of this series guided you through building a REST API, and &lt;a href=&quot;https://realpython.com/flask-connexion-rest-api-part-2/&quot;&gt;Part 2&lt;/a&gt; showed you how to connect that REST API to a database. In &lt;a href=&quot;https://realpython.com/flask-connexion-rest-api-part-3/&quot;&gt;Part 3&lt;/a&gt;, you added relationships to the REST API and the supporting database.&lt;/p&gt;
&lt;p&gt;This article is about presenting that REST API to a user as a browser-based web application. This combination gives you both &lt;a href=&quot;https://en.wikipedia.org/wiki/Front_and_back_ends&quot;&gt;front-end and back-end&lt;/a&gt; abilities, which is a useful and powerful skill set.&lt;/p&gt;
&lt;h2 id=&quot;creating-single-page-applications&quot;&gt;Creating Single-Page Applications&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://realpython.com/flask-connexion-rest-api-part-3/&quot;&gt;Part 3&lt;/a&gt; of this series, you added relationships to the REST API and database to represent notes associated with people. In other words, you created a kind of mini-blog. The web applications you built in part 3 showed you one way to present and interact with the REST API. You navigated between three &lt;strong&gt;Single-Page Applications (SPA)&lt;/strong&gt; to access different parts of the REST API.&lt;/p&gt;
&lt;p&gt;While you could have combined that functionality into a single SPA, that approach would make the concepts of styling and interactivity more complex, without much added value. For that reason, each page was a complete, standalone SPA.&lt;/p&gt;
&lt;p&gt;In this article, you&amp;rsquo;ll focus on the &lt;strong&gt;People SPA&lt;/strong&gt;, which presents the list of people in the database and provides an editor feature to create new people and update or delete existing ones. The Home and Notes pages are conceptually similar.&lt;/p&gt;
&lt;h3 id=&quot;what-existing-frameworks-are-there&quot;&gt;What Existing Frameworks Are There?&lt;/h3&gt;
&lt;p&gt;There are existing libraries that provide inbuilt and robust functionality for creating SPA systems. For example, the &lt;a href=&quot;https://getbootstrap.com/&quot;&gt;Bootstrap&lt;/a&gt; library provides a popular framework of styles for creating consistent and good-looking web applications. It has JavaScript extensions that add interactivity to the styled DOM elements.&lt;/p&gt;
&lt;p&gt;There are also powerful web application frameworks, like &lt;a href=&quot;https://en.wikipedia.org/wiki/React_(JavaScript_library)&quot;&gt;React&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Angular_(web_framework)&quot;&gt;Angular&lt;/a&gt;, that give you complete web application development systems. These are useful when you want to create large, multi-page SPAs that would be cumbersome to build from scratch.&lt;/p&gt;
&lt;h3 id=&quot;why-build-your-own&quot;&gt;Why Build Your Own?&lt;/h3&gt;
&lt;p&gt;With the availability of tools like those listed above, why would you choose to create an SPA from scratch? Take Bootstrap, for instance. You can use it to create SPAs that look excellent, and you can certainly use it with your JavaScript code!&lt;/p&gt;
&lt;p&gt;The problem is that Bootstrap has a steep learning curve you&amp;rsquo;ll need to climb if you want to use it well. It also adds a lot of Bootstrap-specific attributes to the DOM elements defined in your HTML content. Likewise, tools like React and Angular also have significant learning curves you&amp;rsquo;ll need to overcome. However, there&amp;rsquo;s still a place for web applications that don&amp;rsquo;t rely on tools like these. &lt;/p&gt;
&lt;p&gt;Often, when you&amp;rsquo;re building a web application, you want to build a &lt;strong&gt;proof-of-concept&lt;/strong&gt; first to see if the application is at all useful. You&amp;rsquo;ll want to get this up and running quickly, so it can be faster for you to roll your own prototype and upgrade it later. Since you won&amp;rsquo;t invest much time in the prototype, it won&amp;rsquo;t be too costly to start over and create a new application with a supported, fully-featured framework.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a gap between what you&amp;rsquo;re going to develop with the People app in this article and what you could build with a complete framework. It&amp;rsquo;s up to you to decide where the tipping point is between providing the functionality yourself or adopting a framework.&lt;/p&gt;
&lt;h2 id=&quot;parts-of-single-page-applications&quot;&gt;Parts of Single-Page Applications&lt;/h2&gt;
&lt;p&gt;There are a few main forms of &lt;strong&gt;interactivity&lt;/strong&gt; in traditional web-based systems. You can navigate between pages and submit a page with new information. You can fill out forms containing input fields, radio buttons, checkboxes, and more. When you perform these activities, the webserver responds by sending new files to your browser. Then, your browser &lt;a href=&quot;https://en.wikipedia.org/wiki/Browser_engine&quot;&gt;renders&lt;/a&gt; the content again.&lt;/p&gt;
&lt;p&gt;Single-page applications break this pattern by loading everything they need first. Then, any interactivity or navigation is handled by JavaScript or by calls to the server behind the scenes. These activities update the page content &lt;strong&gt;dynamically&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;There are three major components of a single-page application:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;HTML&lt;/strong&gt; provides the content of a web page, or what is rendered by your browser.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;CSS&lt;/strong&gt; provides the presentation, or style, of a web page. It defines how the content of the page should look when rendered by your browser.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;JavaScript&lt;/strong&gt; provides the interactivity of a web page. It also handles communication with the back-end server.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Next, you&amp;rsquo;ll take a closer look at each of these major components.&lt;/p&gt;
&lt;h3 id=&quot;html&quot;&gt;HTML&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/HTML&quot;&gt;HTML&lt;/a&gt; is a text file delivered to your browser that provides the primary &lt;strong&gt;content&lt;/strong&gt; and &lt;strong&gt;structure&lt;/strong&gt; for a single-page application. This structure includes the definitions for &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;class&lt;/code&gt; attributes, which are used by CSS to style the content and JavaScript to interact with the structure. Your browser parses the HTML file to create the &lt;a href=&quot;https://en.wikipedia.org/wiki/Document_Object_Model&quot;&gt;Document Object Model (DOM)&lt;/a&gt;, which it uses to render the content to the display.&lt;/p&gt;
&lt;p&gt;The markup within an HTML file includes &lt;strong&gt;tags&lt;/strong&gt;, like paragraph tags &lt;code&gt;&amp;lt;p&amp;gt;...&amp;lt;/p&amp;gt;&lt;/code&gt; and header tags &lt;code&gt;&amp;lt;h1&amp;gt;...&amp;lt;/h1&amp;gt;&lt;/code&gt;. These tags become elements within the DOM as your browser parses the HTML and renders it to the display. The HTML file also contains links to external resources that your browser will load as it parses the HTML. For the SPA you&amp;rsquo;re building in this article, these external resources are CSS and JavaScript files.&lt;/p&gt;
&lt;h3 id=&quot;css&quot;&gt;CSS&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Cascading_Style_Sheets&quot;&gt;Cascading Style Sheets (CSS)&lt;/a&gt; are files that contain &lt;strong&gt;styling&lt;/strong&gt; information that will be applied to whatever DOM structure is rendered from an HTML file. In this way, the content of a web page can be separated from its presentation.&lt;/p&gt;
&lt;p&gt;In CSS, the style for a DOM structure is determined by &lt;strong&gt;selectors&lt;/strong&gt;. A selector is just a method of matching a style to elements within the DOM. For example, the &lt;code&gt;p&lt;/code&gt; selector in the code block below applies styling information to all paragraph elements:&lt;/p&gt;
&lt;div class=&quot;highlight css&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;bold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;cyan&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;The above style will apply to all paragraph elements in the DOM. The text will appear as bold and have a background color of cyan.&lt;/p&gt;
&lt;p&gt;The &lt;strong&gt;cascading&lt;/strong&gt; part of CSS means that styles defined later, or in a CSS file loaded after another, will take precedence over any previously defined style. For example, you can define a second paragraph style after the style above:&lt;/p&gt;
&lt;div class=&quot;highlight css&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;bold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;cyan&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;hll&quot;&gt;&lt;span class=&quot;nt&quot;&gt;p&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;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cornflower&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;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This new style definition would modify the existing style so that all paragraph elements in the DOM will have a background color of &lt;code&gt;cornflower&lt;/code&gt;. This overrides the &lt;code&gt;background-color&lt;/code&gt; of the previous style, but it leaves the &lt;code&gt;font-weight&lt;/code&gt; setting intact. You could also define the new paragraph style in a CSS file of its own.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;class&lt;/code&gt; attributes let you apply a style to specific individual elements in the DOM. For example, the HTML to render a new DOM might look like this:&lt;/p&gt;
&lt;div class=&quot;highlight html&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    This is some introductory text
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;

&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&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;s&quot;&gt;&amp;quot;panel&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
    This is some text contained within a panel
&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will create two paragraph elements within the DOM. The first has no &lt;code&gt;class&lt;/code&gt; attribute, but the second has a &lt;code&gt;class&lt;/code&gt; attribute of &lt;code&gt;panel&lt;/code&gt;. Then, you can create a CSS style like this:&lt;/p&gt;
&lt;div class=&quot;highlight css&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;font-weight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;bold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;margin-left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;margin-right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;auto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;lightgrey&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;hll&quot;&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;panel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;border&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;kt&quot;&gt;px&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;solid&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;darkgrey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;border-radius&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;kt&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;padding&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;kt&quot;&gt;px&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;background-color&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;lightskyblue&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, you define a style for any elements that have the &lt;code&gt;panel&lt;/code&gt; attribute. When your browser renders the DOM, the two paragraph elements should look like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/people_paragraphs.07d6d12ab5da.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/people_paragraphs.07d6d12ab5da.png&quot; width=&quot;969&quot; height=&quot;111&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/people_paragraphs.07d6d12ab5da.png&amp;amp;w=242&amp;amp;sig=2f842e77fa0cab1a9df12dfc71c0ca8964184716 242w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/people_paragraphs.07d6d12ab5da.png&amp;amp;w=484&amp;amp;sig=e64a95b00370b0b177c8def19cec57af8be9494a 484w, https://files.realpython.com/media/people_paragraphs.07d6d12ab5da.png 969w&quot; sizes=&quot;75vw&quot; alt=&quot;people paragraphs example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Both paragraph elements have the first style definition applied to them because the &lt;code&gt;p&lt;/code&gt; selector selects them both. But only the second paragraph has the &lt;code&gt;.panel&lt;/code&gt; style applied to it because it&amp;rsquo;s the only element with the class attribute &lt;code&gt;panel&lt;/code&gt; that matches that selector. The second paragraph gets new styling information from the &lt;code&gt;.panel&lt;/code&gt; style, and overrides the &lt;code&gt;background-color&lt;/code&gt; style defined in the &lt;code&gt;p&lt;/code&gt; style.&lt;/p&gt;
&lt;h3 id=&quot;javascript&quot;&gt;JavaScript&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/JavaScript&quot;&gt;JavaScript&lt;/a&gt; provides all of the interactive features for an SPA, as well as dynamic communication with the REST API provided by the server. It also performs all of the updates to the DOM, allowing an SPA to act much like a full &lt;a href=&quot;https://en.wikipedia.org/wiki/Graphical_user_interface&quot;&gt;Graphical User Interface (GUI)&lt;/a&gt; application like Word or Excel.&lt;/p&gt;
&lt;p&gt;As JavaScript has evolved, it&amp;rsquo;s become easier and more consistent to work with the DOM provided by modern browsers. You&amp;rsquo;ll be using a few conventions, like namespaces and separation of concerns, to help keep your JavaScript code from conflicting with other libraries you might include.&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&amp;rsquo;ll be creating Single-Page Applications using native JavaScript. In particular, you&amp;rsquo;ll use the &lt;a href=&quot;https://en.wikipedia.org/wiki/ECMAScript#ES2017&quot;&gt;ES2017&lt;/a&gt; version, which works with many modern browsers, but could be problematic if your goal is to support older browser versions.&lt;/p&gt;
&lt;/div&gt;
&lt;h4 id=&quot;modules-and-namespaces&quot;&gt;Modules and Namespaces&lt;/h4&gt;
&lt;p&gt;You might already know about namespaces in Python and why they&amp;rsquo;re valuable. In short, &lt;strong&gt;namespaces&lt;/strong&gt; give you a way to keep the names in your program unique to prevent conflicts. For example, if you wanted to use &lt;code&gt;log()&lt;/code&gt; from both the &lt;code&gt;math&lt;/code&gt; and &lt;code&gt;cmath&lt;/code&gt; modules, then your code might look 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;math&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;cmath&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;math&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;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2.302585092994046&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cmath&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;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(2.302585092994046+0j)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The Python code above imports both the &lt;code&gt;math&lt;/code&gt; and &lt;code&gt;cmath&lt;/code&gt; modules, then calls &lt;code&gt;log(10)&lt;/code&gt; from each module. The first call returns a real number and the second returns a complex number, which &lt;code&gt;cmath&lt;/code&gt; has functions for. Each instance of &lt;code&gt;log()&lt;/code&gt; is unique to its own namespace (&lt;code&gt;math&lt;/code&gt; or &lt;code&gt;cmath&lt;/code&gt;), meaning the calls to &lt;code&gt;log()&lt;/code&gt; don&amp;rsquo;t conflict with each other.&lt;/p&gt;
&lt;p&gt;Modern JavaScript has the ability to &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import&quot;&gt;import&lt;/a&gt; modules and assign namespaces to those modules. This is useful if you need to import other JavaScript libraries where there might be a name conflict.&lt;/p&gt;
&lt;p&gt;If you look at the end of the &lt;code&gt;people.js&lt;/code&gt; file, then you&amp;rsquo;ll see this:&lt;/p&gt;
&lt;div class=&quot;highlight javascript&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;301 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Create the MVC components&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;302 &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;model&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;nx&quot;&gt;Model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;303 &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;view&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;nx&quot;&gt;View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;304 &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;controller&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;nx&quot;&gt;Controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;305 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;306 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// Export the MVC components as the default&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;307 &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;308 &lt;/span&gt;    &lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;309 &lt;/span&gt;    &lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;310 &lt;/span&gt;    &lt;span class=&quot;nx&quot;&gt;controller&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;311 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code above creates the three components of the MVC system, which you&amp;rsquo;ll see later on in this article. The default export from the module is a JavaScript literal object. You import this module at the bottom of the &lt;code&gt;people.html&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight html&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;50 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;module&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;51 &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Give the imported MVC components a namespace&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;52 &lt;/span&gt;    &lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MVC&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/static/js/people.js&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;53 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;54 &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Create an intentional global variable referencing the import&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;55 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mvc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MVC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;56 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s how this code works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 50&lt;/strong&gt; uses &lt;code&gt;type=&quot;module&quot;&lt;/code&gt; to tell the system that the file is a module and not just a JavaScript file.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 52&lt;/strong&gt; imports the default object from &lt;code&gt;people.js&lt;/code&gt; and assigns it the name &lt;code&gt;MVC&lt;/code&gt;. This creates a namespace called &lt;code&gt;MVC&lt;/code&gt;. You can give the imported object any name that doesn&amp;rsquo;t conflict with other JavaScript libraries you might not have control over.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 55&lt;/strong&gt; creates a global variable, which is a convenient step. You can use this to inspect the &lt;code&gt;mvc&lt;/code&gt; object with a JavaScript debugger and look at &lt;code&gt;model&lt;/code&gt;, &lt;code&gt;view&lt;/code&gt;, and &lt;code&gt;controller&lt;/code&gt;.&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;Note:&lt;/strong&gt; Because &lt;code&gt;MVC&lt;/code&gt; is an imported module and not just an included file, JavaScript will default to &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode&quot;&gt;strict mode&lt;/a&gt;, which has some advantages over non-strict mode. One of the biggest is that you can&amp;rsquo;t use undefined variables. &lt;/p&gt;
&lt;p&gt;Without strict mode turned on, this is perfectly legal:&lt;/p&gt;
&lt;div class=&quot;highlight javascript&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;myName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;myNane&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello World&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Do you see the error? The first line creates a variable called &lt;code&gt;myName&lt;/code&gt; and assigns the literal string &lt;code&gt;&quot;Hello&quot;&lt;/code&gt; to it. The second line &lt;em&gt;looks&lt;/em&gt; like it changes the contents of the variable to &lt;code&gt;&quot;Hello World&quot;&lt;/code&gt;, but that isn&amp;rsquo;t the case!&lt;/p&gt;
&lt;p&gt;In the second line, &lt;code&gt;&quot;Hello World&quot;&lt;/code&gt; is assigned to the variable name &lt;code&gt;myNane&lt;/code&gt;, which is misspelled with an &lt;code&gt;n&lt;/code&gt;. In non-strict JavaScript, this creates two variables:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The correct variable &lt;code&gt;myName&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The unintended typo version &lt;code&gt;myNane&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Imagine if these two lines of JavaScript code were separated by many others. This could create a run-time bug that&amp;rsquo;s difficult to find! When you use strict mode, you eliminate errors like this one by raising an exception should your code attempt to use an undeclared variable.&lt;/p&gt;
&lt;/div&gt;
&lt;h4 id=&quot;naming-conventions&quot;&gt;Naming Conventions&lt;/h4&gt;
&lt;p&gt;For the most part, the JavaScript code you&amp;rsquo;re using here is in &lt;a href=&quot;https://en.wikipedia.org/wiki/Camel_case&quot;&gt;camel case&lt;/a&gt;. This naming convention is widely used in the JavaScript community, so the code examples reflect that. However, your Python code will use &lt;a href=&quot;https://en.wikipedia.org/wiki/Snake_case&quot;&gt;snake case&lt;/a&gt;, which is more conventional in the Python community.&lt;/p&gt;
&lt;p&gt;This difference in naming can be confusing where your JavaScript code interacts with Python code, and especially where shared variables enter the REST API interface. Be sure to keep these differences in mind as you write your code.&lt;/p&gt;
&lt;h4 id=&quot;separation-of-concerns&quot;&gt;Separation of Concerns&lt;/h4&gt;
&lt;p&gt;The code that drives an SPA can be complicated. You can use the &lt;a href=&quot;https://realpython.com/the-model-view-controller-mvc-paradigm-summarized-with-legos/&quot;&gt;Model–View–Controller (MVC)&lt;/a&gt; architectural pattern to simplify things by creating a &lt;a href=&quot;https://en.wikipedia.org/wiki/Separation_of_concerns&quot;&gt;separation of concerns&lt;/a&gt;. The Home, People, and Notes SPAs use the following MVC pattern:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Model&lt;/strong&gt; provides all access to the server REST API. Anything presented on the display comes from the model. Any changes to the data go through the model and back to the REST API.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The View&lt;/strong&gt; controls all display handling and DOM updates. The view is the only part of the SPA that interacts with the DOM and causes the browser to render and re-render any changes to the display.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The Controller&lt;/strong&gt; handles all user interaction and any user data entered, like click events. Because the controller reacts to user input, it also interacts with the Model and View based on that user input.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s a visual representation of the MVC concept as implemented in the SPA code:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/mvc.b7675fb5f043.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/mvc.b7675fb5f043.png&quot; width=&quot;975&quot; height=&quot;750&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/mvc.b7675fb5f043.png&amp;amp;w=243&amp;amp;sig=ae7027093f809e4f437686b820066c9aff8b0cf2 243w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/mvc.b7675fb5f043.png&amp;amp;w=487&amp;amp;sig=ea5db7d8c6d0331b56dcc4c334157ae68e8c9ca8 487w, https://files.realpython.com/media/mvc.b7675fb5f043.png 975w&quot; sizes=&quot;75vw&quot; alt=&quot;JavaScript MVC Diagram&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;Model / View / Controller&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;In the illustration above, the Controller has a strong connection with both the Model and the View. Again, this is because any user interaction the Controller handles might require reaching out to the REST API to get or update data.  It may even require updating the display.&lt;/p&gt;
&lt;p&gt;The dotted line that goes from the Model to the Controller indicates a weak connection. Because calls to the REST API are &lt;a href=&quot;https://realpython.com/python-async-features/&quot;&gt;asynchronous&lt;/a&gt;, the data that the Model provides to the Controller returns at a later time.&lt;/p&gt;
&lt;h2 id=&quot;creating-the-people-spa&quot;&gt;Creating the People SPA&lt;/h2&gt;
&lt;p&gt;Your mini-blog demonstration app has pages for Home, People, and Notes. Each of these pages is a complete, standalone SPA. They all use the same design and structure, so even though you&amp;rsquo;re focusing on the People application here, you&amp;rsquo;ll understand how to construct all of them.&lt;/p&gt;
&lt;h3 id=&quot;people-html&quot;&gt;People HTML&lt;/h3&gt;
&lt;p&gt;The Python &lt;a href=&quot;https://realpython.com/tutorials/flask/&quot;&gt;Flask&lt;/a&gt; web framework provides the &lt;a href=&quot;https://realpython.com/primer-on-jinja-templating/&quot;&gt;Jinja2&lt;/a&gt; templating engine, which you&amp;rsquo;ll use for the People SPA. There are parts of the SPA that are common to all three pages, so each page uses the Jinja2 &lt;strong&gt;template inheritance&lt;/strong&gt; feature to share those common elements.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll provide the HTML content for the People SPA in two files: &lt;code&gt;parent.html&lt;/code&gt; and &lt;code&gt;people.html&lt;/code&gt; files. You can get the code for these files at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/rest-api-flask-series/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-rest-api-flask-series&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to learn about Python REST APIs with Flask, Connexion, and SQLAlchemy in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s what your &lt;code&gt;parent.html&lt;/code&gt; will look like:&lt;/p&gt;
&lt;div class=&quot;highlight html&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;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;lang&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;en&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;    {% block head %}
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{% block title %}{% endblock %} Page&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;    {% endblock %}
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&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;s&quot;&gt;&amp;quot;navigation&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;span&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;s&quot;&gt;&amp;quot;buttons&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&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;p&quot;&gt;&amp;gt;&lt;/span&gt;Home&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/people&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;People&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;span&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;s&quot;&gt;&amp;quot;page_name&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;span&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;s&quot;&gt;&amp;quot;spacer&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;{% block body %}
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;{% endblock %}
&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;{% block javascript %}
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;{% endblock %}
&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;parent.html&lt;/code&gt; has a few major elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 1&lt;/strong&gt; sets the document type as &lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/code&gt;. All new HTML pages begin with this declaration. Modern browsers know this means to use the HTML 5 standard, while older browsers will fall back to the latest standard they can support.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 4&lt;/strong&gt; tells the browser to use UTF-8 encoding.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 10 to 19&lt;/strong&gt; define the navigation bar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 21 and 22&lt;/strong&gt; are Jinja2 block markers, which will be replaced by content in &lt;code&gt;people.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 25 and 26&lt;/strong&gt; are Jinja2 block markers that act as a placeholder for JavaScript code.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The &lt;code&gt;people.html&lt;/code&gt; file will inherit the &lt;code&gt;parent.html&lt;/code&gt; code. You can expand the code block below to see the whole file:&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_carddd1115&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;#collapsedd1115&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsedd1115&quot;&gt;people.html&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapsedd1115&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapsedd1115&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapsedd1115&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_carddd1115&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;div class=&quot;highlight html&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;{% extends &amp;quot;parent.html&amp;quot; %}
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;{% block title %}People{% endblock %}
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;{% block head %}
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;{% endblock %}
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;{% block page_name %}Person Create/Update/Delete Page{% endblock %}
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;{% block body %}
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&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;s&quot;&gt;&amp;quot;container&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;url_person_id&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;hidden&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;{{ person_id }}&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&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;s&quot;&gt;&amp;quot;section editor&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;                &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Person ID:&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;                &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;span&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;person_id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;span&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;fname&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;First Name
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;                &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;fname&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;br&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;label&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;for&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;lname&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Last Name
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;                &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;input&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;lname&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;text&amp;quot;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;label&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;br&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;/&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;create&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Create&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;update&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Update&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;delete&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Delete&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;reset&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Reset&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;button&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&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;s&quot;&gt;&amp;quot;people&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;                &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;caption&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;People&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;caption&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31 &lt;/span&gt;                &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;thead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;                    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;tr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33 &lt;/span&gt;                        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Creation/Update Timestamp&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;34 &lt;/span&gt;                        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;Person&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;th&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;35 &lt;/span&gt;                    &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;tr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;36 &lt;/span&gt;                &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;thead&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;37 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;38 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;39 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&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;s&quot;&gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;40 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;41 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;42 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&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;s&quot;&gt;&amp;quot;error&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;43 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;div&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;44 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;45 &lt;/span&gt;{% endblock %}
&lt;/pre&gt;&lt;/div&gt;

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

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;people.html&lt;/code&gt; has just two major differences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 1&lt;/strong&gt; tells Jinja2 that this template inherits from the &lt;code&gt;parent.html&lt;/code&gt; template.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 7 to 45&lt;/strong&gt; create the body of the page. This includes the editing section and an empty table to present the list of people. This is the content inserted in the &lt;code&gt;{% block body %}{% endblock %}&lt;/code&gt; section of the &lt;code&gt;parent.html&lt;/code&gt; file.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The HTML page generated by &lt;code&gt;parent.html&lt;/code&gt; and &lt;code&gt;people.html&lt;/code&gt; contains no styling information. Instead, the page is rendered in the default style of whatever browser you use to view it. Here&amp;rsquo;s what your app looks like when rendered by the Chrome browser:&lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/people_page_before.18c070ff3f0b.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/people_page_before.18c070ff3f0b.png&quot; width=&quot;919&quot; height=&quot;180&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/people_page_before.18c070ff3f0b.png&amp;amp;w=229&amp;amp;sig=9d24e5b12ab14f6cb4639e64aac6bdbe369f14cb 229w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/people_page_before.18c070ff3f0b.png&amp;amp;w=459&amp;amp;sig=53d4493d98f5bb0c969b64f9074d89209bfd3d2d 459w, https://files.realpython.com/media/people_page_before.18c070ff3f0b.png 919w&quot; sizes=&quot;75vw&quot; alt=&quot;people page before styling and javascript&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;People HTML page before styling&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;It doesn&amp;rsquo;t look much like a Single-Page Application! Let&amp;rsquo;s see what you can do about that.&lt;/p&gt;
&lt;h3 id=&quot;people-css&quot;&gt;People CSS&lt;/h3&gt;
&lt;p&gt;To style the People SPA, you first need to add the &lt;a href=&quot;https://necolas.github.io/normalize.css/&quot;&gt;&lt;code&gt;normalize.css&lt;/code&gt;&lt;/a&gt; style sheet. This will make sure that all browsers consistently render elements more closely to HTML 5 standards. The specific CSS for the People SPA is supplied by two style sheets:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;parent.css&lt;/code&gt;, which you pull in with &lt;code&gt;parent.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;people.css&lt;/code&gt;, which you pull in with &lt;code&gt;people.html&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can get the code for these stylesheets at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/rest-api-flask-series/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-rest-api-flask-series&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to learn about Python REST APIs with Flask, Connexion, and SQLAlchemy in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll add both &lt;code&gt;normalize.css&lt;/code&gt; and &lt;code&gt;parent.css&lt;/code&gt; to the &lt;code&gt;&amp;lt;head&amp;gt;...&amp;lt;/head&amp;gt;&lt;/code&gt; section of &lt;code&gt;parent.html&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight html&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;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;    {% block head %}
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;{% block title %}{% endblock %} Page&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.0/normalize.min.css&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/static/css/parent.css&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;    {% endblock %}
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here&amp;rsquo;s what these new lines do:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 5&lt;/strong&gt; gets &lt;code&gt;normalize.css&lt;/code&gt; from a &lt;a href=&quot;https://en.wikipedia.org/wiki/Content_delivery_network&quot;&gt;content delivery network (CDN)&lt;/a&gt;, so you don&amp;rsquo;t have to download it yourself.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 6&lt;/strong&gt; gets &lt;code&gt;parent.css&lt;/code&gt; from your app&amp;rsquo;s &lt;code&gt;static&lt;/code&gt; folder.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the most part, &lt;code&gt;parent.css&lt;/code&gt; sets the styles for the navigation and error elements. It also changes the default font to Google&amp;rsquo;s Roboto font using these lines:&lt;/p&gt;
&lt;div class=&quot;highlight css&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nt&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;://&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;fonts&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;googleapis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;css&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;family&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;Roboto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nd&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;700&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;lineno&quot;&gt; 6 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;body&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;nc&quot;&gt;ui-btn&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;k&quot;&gt;font-family&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Roboto&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;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You pull in the Roboto font from a Google CDN. Then, you apply this font to all elements in the SPA body that also have a class of &lt;code&gt;.ui-btn&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Likewise, &lt;code&gt;people.css&lt;/code&gt; contains styling information specific to the HTML elements that create the People SPA. You add &lt;code&gt;people.css&lt;/code&gt; to the &lt;code&gt;people.html&lt;/code&gt; file inside the Jinja2 &lt;code&gt;{% block head %}&lt;/code&gt; section:&lt;/p&gt;
&lt;div class=&quot;highlight html&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 3 &lt;/span&gt;{% block head %}
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;    {{ super() }}
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;link&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;rel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;stylesheet&amp;quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;href&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;/static/css/people.css&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;{% endblock %}
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The file contains a few new lines:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 2&lt;/strong&gt; has a call to {{ super() }}. This tells Jinja2 to include anything that exists in the &lt;code&gt;{% block head %}&lt;/code&gt; section of &lt;code&gt;parent.html&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 3&lt;/strong&gt; pulls in the &lt;code&gt;people.css&lt;/code&gt; file from your app&amp;rsquo;s static folder.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After you include the stylesheets, your People SPA will look more 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/people_page_after_styling.da1b340d7576.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/people_page_after_styling.da1b340d7576.png&quot; width=&quot;1233&quot; height=&quot;292&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/people_page_after_styling.da1b340d7576.png&amp;amp;w=308&amp;amp;sig=52b5d28b3d6d887250b2cf30f195bd561172b764 308w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/people_page_after_styling.da1b340d7576.png&amp;amp;w=616&amp;amp;sig=8911942773da69695e186617b5adc1e5d383bbc2 616w, https://files.realpython.com/media/people_page_after_styling.da1b340d7576.png 1233w&quot; sizes=&quot;75vw&quot; alt=&quot;People page after styling, but before JavaScript&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;People HTML page after styling, but before JavaScript&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The People SPA is looking better, but it&amp;rsquo;s still incomplete. Where are the rows of people data in the table? All the buttons in the editor section are enabled, so why don&amp;rsquo;t they do anything? You&amp;rsquo;ll fix these issues in the next section with some JavaScript.&lt;/p&gt;
&lt;h3 id=&quot;people-javascript&quot;&gt;People JavaScript&lt;/h3&gt;
&lt;p&gt;You&amp;rsquo;ll pull JavaScript files into the People SPA just like you did with the CSS files. You&amp;rsquo;ll add the following bit of code to the bottom of &lt;code&gt;people.html&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight html&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;48 &lt;/span&gt;{% block javascript %}
&lt;span class=&quot;lineno&quot;&gt;49 &lt;/span&gt;{{ super() }}
&lt;span class=&quot;lineno&quot;&gt;50 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;script&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;module&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;51 &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Give the imported MVC components a namespace&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;52 &lt;/span&gt;    &lt;span class=&quot;kr&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MVC&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/static/js/people.js&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;53 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;54 &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Create an intentional global variable referencing the import&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;55 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mvc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MVC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;56 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;script&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;57 &lt;/span&gt;{% endblock %}
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Notice the &lt;code&gt;type=&quot;module&quot;&lt;/code&gt; declaration on the opening &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag in line 50. This tells the system that the script is a JavaScript module. The ES6 &lt;code&gt;import&lt;/code&gt; syntax will be used to pull the exported parts of the code into the browser context.&lt;/p&gt;
&lt;h2 id=&quot;the-people-mvc&quot;&gt;The People MVC&lt;/h2&gt;
&lt;p&gt;All of the SPA pages use a variation of the &lt;a href=&quot;https://realpython.com/the-model-view-controller-mvc-paradigm-summarized-with-legos/&quot;&gt;MVC&lt;/a&gt; pattern. Here&amp;rsquo;s an example implementation in JavaScript:&lt;/p&gt;
&lt;div class=&quot;highlight javascript&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;// Create the MVC components&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;model&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;nx&quot;&gt;Model&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;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;view&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;nx&quot;&gt;View&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;kr&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;controller&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;nx&quot;&gt;Controller&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&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;c1&quot;&gt;// Export the MVC components as the default&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&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;nx&quot;&gt;model&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;nx&quot;&gt;view&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;nx&quot;&gt;controller&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code doesn&amp;rsquo;t do anything just yet, but you can use it to see the following elements of MVC structure and implementation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 2&lt;/strong&gt; creates an instance of the Model class and assigns it to &lt;code&gt;model&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 3&lt;/strong&gt; creates an instance of the View class and assigns it to &lt;code&gt;view&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 4&lt;/strong&gt; creates an instance of the Controller class and assigns it to &lt;code&gt;controller&lt;/code&gt;. Note that you pass both &lt;code&gt;model&lt;/code&gt; and &lt;code&gt;view&lt;/code&gt; to the constructor. This is how the controller gets a link to the &lt;code&gt;model&lt;/code&gt; and &lt;code&gt;view&lt;/code&gt; instance variables.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 7 to 11&lt;/strong&gt; export a JavaScript literal object as the default export.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because you pull in &lt;code&gt;people.js&lt;/code&gt; at the bottom of &lt;code&gt;people.html&lt;/code&gt;, the JavaScript is executed &lt;em&gt;after&lt;/em&gt; your browser creates the SPA DOM elements. This means that JavaScript can safely access the elements on the page and begin to interact with the DOM.&lt;/p&gt;
&lt;p&gt;Again, the code above doesn&amp;rsquo;t do anything just yet. To make it work, you&amp;rsquo;ll need to define your Model, View, and Controller.&lt;/p&gt;
&lt;h3 id=&quot;people-model&quot;&gt;People Model&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;Model&lt;/strong&gt; is responsible for communicating with the REST API provided by the Flask server. Any data that comes from the database, and any data the SPA changes or creates, must go through the Model. All communication with the REST API is done using HTTP &lt;a href=&quot;https://en.wikipedia.org/wiki/Ajax_(programming)&quot;&gt;AJAX&lt;/a&gt; calls initiated by JavaScript.&lt;/p&gt;
&lt;p&gt;Modern JavaScript provides &lt;code&gt;fetch()&lt;/code&gt;, which you can use to make AJAX calls. The code for your Model class implements one AJAX method to read the REST API URL endpoint &lt;code&gt;/api/people&lt;/code&gt; and get all the people in the database:&lt;/p&gt;
&lt;div class=&quot;highlight javascript&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;kr&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Model&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;nx&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;read&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;lineno&quot;&gt; 3 &lt;/span&gt;        &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;options&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;lineno&quot;&gt; 4 &lt;/span&gt;            &lt;span class=&quot;nx&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;GET&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;            &lt;span class=&quot;nx&quot;&gt;cache&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;no-cache&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;nx&quot;&gt;headers&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;lineno&quot;&gt; 7 &lt;/span&gt;                &lt;span class=&quot;s2&quot;&gt;&amp;quot;Content-Type&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;application/json&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;                &lt;span class=&quot;s2&quot;&gt;&amp;quot;accepts&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;application/json&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &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;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Call the REST endpoint and wait for data&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;        &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fetch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;`/api/people`&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;options&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;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;json&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;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &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 how this code works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 1&lt;/strong&gt; defines the class &lt;code&gt;Model&lt;/code&gt;. This is what will be exported later as part of the &lt;code&gt;mvc&lt;/code&gt; object.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 2&lt;/strong&gt; begins the definition of an &lt;a href=&quot;https://realpython.com/python-async-features/&quot;&gt;asynchronous&lt;/a&gt; method called &lt;code&gt;read()&lt;/code&gt;. The &lt;code&gt;async&lt;/code&gt; keyword in front of &lt;code&gt;read()&lt;/code&gt; tells JavaScript that this method performs asynchronous work.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 3 to 9&lt;/strong&gt; create an &lt;code&gt;options&lt;/code&gt; object with parameters for the HTTP call, like the method and what the call expects for data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 12&lt;/strong&gt; uses &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API&quot;&gt;&lt;code&gt;fetch()&lt;/code&gt;&lt;/a&gt; to make an asynchronous HTTP call to the &lt;code&gt;/api/people&lt;/code&gt; URL REST endpoint provided by the server. The keyword &lt;code&gt;await&lt;/code&gt; in front of &lt;code&gt;fetch()&lt;/code&gt; tells JavaScript to wait asynchronously for the call to complete. When this is finished, the results are assigned to &lt;code&gt;response&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 13&lt;/strong&gt; asynchronously converts the JSON string in the response to a JavaScript object and assigns it to &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 14&lt;/strong&gt; returns the data to the caller.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Essentially, this code tells JavaScript to make a &lt;code&gt;GET&lt;/code&gt; HTTP request to &lt;code&gt;/api/people&lt;/code&gt;, and that the caller is expecting a &lt;code&gt;Content-Type&lt;/code&gt; of &lt;code&gt;application/json&lt;/code&gt; and &lt;code&gt;json&lt;/code&gt; data. Recall that a &lt;code&gt;GET&lt;/code&gt; HTTP call equates to &lt;code&gt;Read&lt;/code&gt; in a &lt;a href=&quot;https://en.wikipedia.org/wiki/Create,_read,_update_and_delete&quot;&gt;CRUD&lt;/a&gt;-oriented system. &lt;/p&gt;
&lt;p&gt;Based on the Connexion configuration defined in &lt;code&gt;swagger.yml&lt;/code&gt;, this HTTP call will call &lt;code&gt;def read_all()&lt;/code&gt;. This function is defined in &lt;code&gt;people.py&lt;/code&gt; and queries the SQLite database to build a list of people to return to the caller. You can get the code for all of these files at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/rest-api-flask-series/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-rest-api-flask-series&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to learn about Python REST APIs with Flask, Connexion, and SQLAlchemy in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;In the browser, JavaScript executes in a single thread and is intended to respond to user actions. Because of this, it&amp;rsquo;s a bad idea to block JavaScript execution that&amp;rsquo;s waiting for something to complete, like an HTTP request to a server.&lt;/p&gt;
&lt;p&gt;What if the request went out across a very slow network, or the server itself was down and would never respond? If JavaScript were to block and wait for the HTTP request to complete in these kinds of conditions, then it might finish in seconds, minutes, or perhaps not at all. While JavaScript is blocked, nothing else in the browser would react to user actions!&lt;/p&gt;
&lt;p&gt;To prevent this blocking behavior, HTTP requests are executed &lt;strong&gt;asynchronously&lt;/strong&gt;. This means that an HTTP request returns to the event loop immediately before the request completes. The &lt;strong&gt;event loop&lt;/strong&gt; exists in any JavaScript application that runs in the browser. The loop continuously waits for an event to complete so it can run the code associated with that event.&lt;/p&gt;
&lt;p&gt;When you place the &lt;code&gt;await&lt;/code&gt; keyword before &lt;code&gt;fetch()&lt;/code&gt;, you tell the event loop where to return when the HTTP request completes. At that point, the request is complete and any data returned by the call is assigned to &lt;code&gt;response&lt;/code&gt;. Then, &lt;code&gt;controller&lt;/code&gt; calls &lt;code&gt;this.model.read()&lt;/code&gt; to receive the data returned by the method. This creates a weak link with the &lt;code&gt;controller&lt;/code&gt;, as the &lt;code&gt;model&lt;/code&gt; doesn&amp;rsquo;t know anything about what called it, just what it returned to that caller.&lt;/p&gt;
&lt;h3 id=&quot;people-view&quot;&gt;People View&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;this.view&lt;/code&gt; is responsible for interacting with the DOM, which is shown by the display. It can change, add, and delete items from the DOM, which are then re-rendered to the display. The &lt;code&gt;controller&lt;/code&gt; makes calls to the view&amp;rsquo;s methods to update the display. The &lt;code&gt;View&lt;/code&gt; is another JavaScript class with methods the controller can call. &lt;/p&gt;
&lt;p&gt;Below is a slightly simplified version of the People SPA&amp;rsquo;s &lt;code&gt;View&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight javascript&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;kr&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;View&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;nx&quot;&gt;constructor&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;lineno&quot;&gt; 3 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;table&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;querySelector&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;.people table&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;person_id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;fname&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;lname&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;p&quot;&gt;}&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;nx&quot;&gt;reset&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;lineno&quot;&gt;10 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;textContent&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;lineno&quot;&gt;11 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&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;lineno&quot;&gt;12 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&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;lineno&quot;&gt;13 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;focus&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;p&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;nx&quot;&gt;buildTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;people&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;lineno&quot;&gt;17 &lt;/span&gt;        &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tbody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;            &lt;span class=&quot;nx&quot;&gt;html&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;lineno&quot;&gt;19 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Iterate over the people and build the table&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;        &lt;span class=&quot;nx&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;            &lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;            &amp;lt;tr data-person_id=&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;quot; data-fname=&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fname&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;quot; data-lname=&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;                &amp;lt;td class=&amp;quot;timestamp&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;                &amp;lt;td class=&amp;quot;name&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fname&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;            &amp;lt;/tr&amp;gt;`&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;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Is there currently a tbody in the table?&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29 &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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tBodies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&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;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;removeChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;tbody&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;lineno&quot;&gt;31 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;// Update tbody with our new content&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33 &lt;/span&gt;        &lt;span class=&quot;nx&quot;&gt;tbody&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createTBody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;34 &lt;/span&gt;        &lt;span class=&quot;nx&quot;&gt;tbody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerHTML&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;35 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;36 &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 how this code works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 1&lt;/strong&gt; begins the class definition.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 2 to 7&lt;/strong&gt; define the class constructor, much like the &lt;code&gt;def __init__(self):&lt;/code&gt; definition in a Python class. The constructor is getting elements from the DOM and creating alias variables to use in other parts of the class. The &lt;code&gt;this.&lt;/code&gt; in front of those variable names is much like &lt;code&gt;self.&lt;/code&gt; in Python. It designates the current instance of the class when used.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 9 to 14&lt;/strong&gt; define &lt;code&gt;reset()&lt;/code&gt;, which you&amp;rsquo;ll use to set the page back to a default state.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 16 to 36&lt;/strong&gt; define &lt;code&gt;buildTable()&lt;/code&gt;, which builds the table of people based on the &lt;code&gt;people&lt;/code&gt; data passed to it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The alias variables are created to cache the DOM objects returned by calls to &lt;code&gt;document.getElementByID()&lt;/code&gt; and &lt;code&gt;document.querySelector()&lt;/code&gt;, which are relatively expensive JavaScript operations. This allows quick use of the variables in the other methods of the class.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s take a closer look at &lt;code&gt;build_table()&lt;/code&gt;, which is the second method in the &lt;code&gt;View&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;highlight javascript&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;buildTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;people&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;lineno&quot;&gt;17 &lt;/span&gt;    &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;tbody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;        &lt;span class=&quot;nx&quot;&gt;html&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;lineno&quot;&gt;19 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Iterate over the people and build the table&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;    &lt;span class=&quot;nx&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;        &lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;sb&quot;&gt;`&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;        &amp;lt;tr data-person_id=&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;quot; data-fname=&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fname&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;quot; data-lname=&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;            &amp;lt;td class=&amp;quot;timestamp&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;            &amp;lt;td class=&amp;quot;name&amp;quot;&amp;gt;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fname&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;${&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;&amp;lt;/td&amp;gt;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;&lt;span class=&quot;sb&quot;&gt;        &amp;lt;/tr&amp;gt;`&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;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Is there currently a tbody in the table?&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29 &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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;tBodies&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&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;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;removeChild&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementsByTagName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;tbody&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;lineno&quot;&gt;31 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;// Update tbody with our new content&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33 &lt;/span&gt;    &lt;span class=&quot;nx&quot;&gt;tbody&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;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;table&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createTBody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;34 &lt;/span&gt;    &lt;span class=&quot;nx&quot;&gt;tbody&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerHTML&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;html&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;35 &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 how the function works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 16&lt;/strong&gt; creates the method and passes the &lt;code&gt;people&lt;/code&gt; variable as a parameter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 21 to 27&lt;/strong&gt; iterate over the &lt;code&gt;people&lt;/code&gt; data using JavaScript &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions&quot;&gt;arrow functions&lt;/a&gt; to create a function that builds up the table rows in the &lt;code&gt;html&lt;/code&gt; variable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 29 to 31&lt;/strong&gt; remove any &lt;code&gt;&amp;lt;tbody&amp;gt;&lt;/code&gt; elements in the table if they exist.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 33&lt;/strong&gt; creates a new &lt;code&gt;tbody&lt;/code&gt; element in the table.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 34&lt;/strong&gt; inserts the &lt;code&gt;html&lt;/code&gt; string previously created into the &lt;code&gt;tbody&lt;/code&gt; element as HTML.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This function dynamically builds the table in the People SPA from the data passed to it, which is the list of people that came from the &lt;code&gt;/api/people/&lt;/code&gt; REST API call. This data is used along with JavaScript template strings to generate the table rows to insert into the table.&lt;/p&gt;
&lt;h3 id=&quot;people-controller&quot;&gt;People Controller&lt;/h3&gt;
&lt;p&gt;The &lt;strong&gt;Controller&lt;/strong&gt; is the central clearinghouse of the MVC implementation, as it coordinates the activity of both &lt;code&gt;model&lt;/code&gt; and &lt;code&gt;view&lt;/code&gt;. As such, the code to define it is a little more complicated. Here&amp;rsquo;s a simplified version:&lt;/p&gt;
&lt;div class=&quot;highlight javascript&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;kr&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Controller&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;nx&quot;&gt;constructor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;view&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;lineno&quot;&gt; 3 &lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;model&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;initialize&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;    &lt;span class=&quot;nx&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;initialize&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;lineno&quot;&gt; 9 &lt;/span&gt;        &lt;span class=&quot;nx&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;initializeTable&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;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;    &lt;span class=&quot;nx&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;initializeTable&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;lineno&quot;&gt;12 &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;13 &lt;/span&gt;            &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;urlPersonId&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;parseInt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;url_person_id&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&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;nx&quot;&gt;people&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;buildTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;people&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;// Did we navigate here with a person selected?&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &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;nx&quot;&gt;urlPersonId&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;lineno&quot;&gt;20 &lt;/span&gt;                &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;readOne&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;urlPersonId&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;updateEditor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;                &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setButtonState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;EXISTING_NOTE&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;lineno&quot;&gt;24 &lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;// Otherwise, nope, so leave the editor blank&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &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;lineno&quot;&gt;26 &lt;/span&gt;                &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;reset&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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;setButtonState&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;NEW_NOTE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &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;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;initializeTableEvents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&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;lineno&quot;&gt;31 &lt;/span&gt;            &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;errorMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;34 &lt;/span&gt;    &lt;span class=&quot;nx&quot;&gt;initializeCreateEvent&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;lineno&quot;&gt;35 &lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;create&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;addEventListener&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;evt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;36 &lt;/span&gt;            &lt;span class=&quot;kd&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;fname&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;37 &lt;/span&gt;                &lt;span class=&quot;nx&quot;&gt;lname&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;lname&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;38 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;39 &lt;/span&gt;            &lt;span class=&quot;nx&quot;&gt;evt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;40 &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;41 &lt;/span&gt;                &lt;span class=&quot;nx&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;42 &lt;/span&gt;                    &lt;span class=&quot;nx&quot;&gt;fname&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;fname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;43 &lt;/span&gt;                    &lt;span class=&quot;nx&quot;&gt;lname&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;lname&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;44 &lt;/span&gt;                &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;45 &lt;/span&gt;                &lt;span class=&quot;nx&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;initializeTable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;46 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&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;lineno&quot;&gt;47 &lt;/span&gt;                &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;errorMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;err&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;48 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;49 &lt;/span&gt;        &lt;span class=&quot;p&quot;&gt;});&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;50 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;51 &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 how it works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 1&lt;/strong&gt; begins the definition of the Controller class.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 2 to 7&lt;/strong&gt; define the class constructor and create the instance variables &lt;code&gt;this.model&lt;/code&gt; and &lt;code&gt;this.view&lt;/code&gt; with their respective parameters. It also calls &lt;code&gt;this.initialize()&lt;/code&gt; to set up the event handling and build the initial table of people.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 8 to 10&lt;/strong&gt; define &lt;code&gt;initialize()&lt;/code&gt; and mark it as an asynchronous method. It calls &lt;code&gt;this.initializeTable()&lt;/code&gt; asynchronously and waits for it to complete. This simplified version only includes this one call, but the full version of the code contains other initialization methods used for the rest of the event handling set up.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 11&lt;/strong&gt; defines &lt;code&gt;initializeTable()&lt;/code&gt; as an asynchronous method. This is necessary because it calls &lt;code&gt;model.read()&lt;/code&gt;, which is also asynchronous.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 13&lt;/strong&gt; declares and initializes the &lt;code&gt;urlPersonId&lt;/code&gt; variable with the value of the HTML hidden input &lt;code&gt;url_person_id&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 14&lt;/strong&gt; calls &lt;code&gt;this.model.read()&lt;/code&gt; and asynchronously waits for it to return with people data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 16&lt;/strong&gt; calls &lt;code&gt;this.view.buildTable(people)&lt;/code&gt; to fill the HTML table with people data.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 19 to 28&lt;/strong&gt; determine how to update the editor portion of the page.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 29&lt;/strong&gt; calls &lt;code&gt;this.initializeTableEvents()&lt;/code&gt; to install the event handling for the HTML table.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 31&lt;/strong&gt; calls &lt;code&gt;this.view.errorMessage(err)&lt;/code&gt; to display errors should they occur.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 34 to 49&lt;/strong&gt; install a click event handler on the create button. This calls &lt;code&gt;this.model.create(...)&lt;/code&gt; to create a new person using the REST API, and updates the HTML table with new data.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The bulk of the &lt;code&gt;controller&lt;/code&gt; code is like this, setting event handlers for all the expected events on the People SPA page. The controller continues creating functions in those event handlers to orchestrate calls to &lt;code&gt;this.model&lt;/code&gt; and &lt;code&gt;this.view&lt;/code&gt;, so that they perform the right actions when those events occur.&lt;/p&gt;
&lt;p&gt;When your code is complete, your People SPA page will look 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/people_page_after.007a76786496.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/people_page_after.007a76786496.png&quot; width=&quot;989&quot; height=&quot;413&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/people_page_after.007a76786496.png&amp;amp;w=247&amp;amp;sig=2ee40cebf5b2c53486a8ed5f4195d76af5188f3e 247w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/people_page_after.007a76786496.png&amp;amp;w=494&amp;amp;sig=cd7a2d8f7bcf82718331da5dda1098803924ca7e 494w, https://files.realpython.com/media/people_page_after.007a76786496.png 989w&quot; sizes=&quot;75vw&quot; alt=&quot;people page after styling and javascript&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;People HTML page after styling and JavaScript&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The content, styling, and functionality are all complete!&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ve covered a great deal of new ground and should be proud of what you&amp;rsquo;ve learned! It can be tricky to jump back and forth between Python and JavaScript to create a complete Single-Page Application.&lt;/p&gt;
&lt;p&gt;If you keep your &lt;strong&gt;content&lt;/strong&gt; (HTML), &lt;strong&gt;presentation&lt;/strong&gt; (CSS), and &lt;strong&gt;interaction&lt;/strong&gt; (JavaScript) separate, then you can substantially reduce the complexity. You can also make JavaScript coding more manageable by using the MVC pattern to further break down the complexity of user interaction.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve seen how using these tools and ideas can help you create reasonably complex Single-Page Applications. Now you&amp;rsquo;re better equipped to make decisions about whether to build an app this way, or take the plunge into a larger framework!&lt;/p&gt;
&lt;p&gt;You can get all of the code you saw in this tutorial at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/rest-api-flask-series/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-rest-api-flask-series&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to learn about Python REST APIs with Flask, Connexion, and SQLAlchemy in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;div class=&quot;container py-3 series-nav mb-3&quot;&gt;
  &lt;div class=&quot;row justify-content-between&quot;&gt;
    &lt;div class=&quot;col-12 col-md-3 text-left text-muted ml-1&quot;&gt;&lt;a href=&quot;https://realpython.com/flask-connexion-rest-api-part-3/&quot;&gt; «&amp;nbsp;Part 3: Database Relationship&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;col-12 col-md-3 text-center text-muted&quot;&gt;&lt;a href=&quot;#&quot;&gt;Part 4: Simple Web Applications&lt;/a&gt;&lt;/div&gt;
    &lt;div class=&quot;col-12 col-md-3 text-right text-muted mr-1&quot;&gt;&lt;/div&gt;
  &lt;/div&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>Python Type Checking</title>
      <id>https://realpython.com/courses/python-type-checking/</id>
      <link href="https://realpython.com/courses/python-type-checking/"/>
      <updated>2019-10-29T14:00:00+00:00</updated>
      <summary>In this course, you&#39;ll look at Python type checking. Traditionally, types have been handled by the Python interpreter in a flexible but implicit way. Recent versions of Python allow you to specify explicit type hints that can be used by different tools to help you develop your code more efficiently.</summary>
      <content type="html">
        &lt;p&gt;In this course, you&amp;rsquo;ll learn about &lt;strong&gt;Python type checking&lt;/strong&gt;. Traditionally, types have been handled by the Python interpreter in a flexible but implicit way. Recent versions of Python allow you to specify explicit type hints that can be used by different tools to help you develop your code more efficiently.&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;&lt;strong&gt;Type annotations&lt;/strong&gt; and &lt;strong&gt;type hints&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Adding &lt;strong&gt;static types&lt;/strong&gt; to code, both your code and the code of others&lt;/li&gt;
&lt;li&gt;Running a &lt;strong&gt;static type checker&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enforcing types&lt;/strong&gt; at runtime&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You&amp;rsquo;ll go on a tour of how type hints work in Python and find out if type checking is something you want to use in your code. If you want to learn more, you can check out the resources that will be linked to throughout this 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>Python Community Interview With Al Sweigart</title>
      <id>https://realpython.com/interview-al-sweigart/</id>
      <link href="https://realpython.com/interview-al-sweigart/"/>
      <updated>2019-10-28T14:00:00+00:00</updated>
      <summary>Al Sweigart is an accomplished developer, conference speaker, teacher, and origamist. But some may know him best for his numerous Python programming books, such as Automate the Boring Stuff with Python.</summary>
      <content type="html">
        &lt;p&gt;This week, I&amp;rsquo;m joined by &lt;a href=&quot;https://twitter.com/AlSweigart&quot;&gt;Al Sweigart&lt;/a&gt;, a familiar name in the Python community. Al is an accomplished developer, conference speaker, teacher, and origamist. (Yes, you read that correctly!) But some may know him best as the author of many Python programming books, including the bestselling book &lt;a href=&quot;https://realpython.com/asins/1593275994/&quot;&gt;&lt;em&gt;Automate the Boring Stuff with Python&lt;/em&gt;&lt;/a&gt; and our top pick, &lt;a href=&quot;https://realpython.com/best-python-books/#invent-your-own-computer-games-with-python-4th-edition&quot;&gt;&lt;em&gt;Invent Your Own Computer Games with Python&lt;/em&gt;&lt;/a&gt;. So, without any further ado, let&amp;rsquo;s get into it!&lt;/p&gt;
&lt;p class=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;Welcome to&lt;/em&gt; Real Python, &lt;em&gt;Al. We&amp;rsquo;re so glad you could join us for this interview. Let&amp;rsquo;s start the same way we do with all our guests. 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;img class=&quot;img-fluid w-25 float-right ml-3 rounded-circle&quot; src=&quot;https://files.realpython.com/media/me_backyard_shaved_head_cropped.aafca8eebcce.webp&quot; width=&quot;1000&quot; height=&quot;933&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/me_backyard_shaved_head_cropped.aafca8eebcce.webp&amp;amp;w=250&amp;amp;sig=feedbb09ff6fa8b521019563e2a154f06da863a6 250w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/me_backyard_shaved_head_cropped.aafca8eebcce.webp&amp;amp;w=500&amp;amp;sig=20c41603a8e4db5936fa7e701351d3d4d2dfe251 500w, https://files.realpython.com/media/me_backyard_shaved_head_cropped.aafca8eebcce.webp 1000w&quot; sizes=&quot;75vw&quot; alt=&quot;Al Sweigart&quot;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Al:&lt;/strong&gt; Thank you! Heh, I absolutely hate telling people how I got into programming because I was one of those kids who started learning BASIC around the third grade or so.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t like telling people that because I feel like it contributes to the idea that in order to become a programmer you had to have started when you were really young. Like, if you weren&amp;rsquo;t debugging subroutines as a fetus, there&amp;rsquo;s no chance you&amp;rsquo;ll make it a career. So I tell people I started when I was a kid. &lt;/p&gt;
&lt;p&gt;I also tell them that most of my programs were pretty mediocre for several years. I didn&amp;rsquo;t have Wikipedia or Google or Stack Overflow, so I kept making variations of a &amp;ldquo;guess the number&amp;rdquo; game, or began projects that I didn&amp;rsquo;t have the technical knowledge to complete. My head start didn&amp;rsquo;t amount to much. Everything I learned about programming and computers across several years as a kid and teen could be learned today in about a couple dozen weekends.&lt;/p&gt;
&lt;p&gt;I think the main benefit of starting young was that I didn&amp;rsquo;t know programming was supposed to be hard. Today, everyone thinks of AI and machine learning and video games with amazing 3D graphics. I was just messing around in my spare time in a completely unfocused way, but I was totally fine with that.&lt;/p&gt;
&lt;p&gt;I didn&amp;rsquo;t learn that much knowledge-wise, but I did pick up the idea that programming was just a thing you could learn to do like anything else. It didn&amp;rsquo;t require super smarts or Olympic-level training to do.&lt;/p&gt;
&lt;p&gt;My first programming language was BASIC and soon after Qbasic, but I also picked up a little &lt;a href=&quot;https://realpython.com/build-python-c-extension-module/&quot;&gt;C&lt;/a&gt;, Visual Basic, Perl, &lt;a href=&quot;https://realpython.com/oop-in-python-vs-java/&quot;&gt;Java&lt;/a&gt;, PHP, and JavaScript. It seems like a lot, but I never really mastered any of them. I just learned enough to complete whatever project I was working on in those languages at the time.&lt;/p&gt;
&lt;p&gt;I got into Python around 2005, and sort of stopped learning new languages after that. I keep feeling the urge to explore new ones (Kotlin, Rust, and Dart have been in my sights for a while), but Python is just so easy to use for so many areas that I haven&amp;rsquo;t had a strong enough pull away from it yet.&lt;/p&gt;
&lt;p class=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;You know, my first Python programming book was your book&lt;/em&gt; &lt;a href=&quot;https://realpython.com/asins/1593275994/&quot;&gt;Automate the Boring Stuff with Python&lt;/a&gt;. &lt;em&gt;It&amp;rsquo;s something I still reference, even today. I&amp;rsquo;d love to know what inspired you to write a book that isn&amp;rsquo;t necessarily aimed at people who want to be a professional programmer in the traditional sense?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Al:&lt;/strong&gt; Haha, I&amp;rsquo;m always amazed at how popular that book has become! I still reference the book myself: I&amp;rsquo;ll be working on something and can&amp;rsquo;t quite remember a function name and I&amp;rsquo;ll realize, &amp;ldquo;Wait, I wrote this down before.&amp;rdquo; I really hate job interviews where they forbid you from consulting books or documentation for the coding interview. When I&amp;rsquo;m programming, I consult books that &lt;em&gt;I&lt;/em&gt; wrote. &lt;/p&gt;
&lt;p&gt;I got started writing books around 2008 or 2009. My girlfriend at the time was a nanny for a 10-year-old who wanted to learn to code, but I couldn&amp;rsquo;t find any tutorials for him online that I liked. Everything was either for software engineers or the same old &amp;ldquo;let&amp;rsquo;s calculate Fibonacci numbers&amp;rdquo; stuff.&lt;/p&gt;
&lt;p&gt;I thought back to how I got into coding through those magazines and books that listed the source code for small games. I had only half-understood the explanatory text, but copying the source code and making small modifications really showed me how to put programs together. &lt;/p&gt;
&lt;p&gt;So I wrote a tutorial like that which grew in length and eventually became &lt;a href=&quot;https://realpython.com/asins/1593277954/&quot;&gt;&lt;em&gt;Invent Your Own Computer Games with Python&lt;/em&gt;&lt;/a&gt;. I put it online, then later sold it as a self-published title. I still had my day job as a software developer, and I never really considered book writing to be a career.&lt;/p&gt;
&lt;p&gt;I released the book under a Creative Commons copyright license which let people download and share it for free. That turned out to be critically important because it let people share the book and generated word-of-mouth. Without a Creative Commons license, it would have just been yet another self-published listing on Amazon and I wouldn&amp;rsquo;t have my current career. Making the book freely available resulted in far more sales.&lt;/p&gt;
&lt;p&gt;So I wrote another book and another one, and for my fourth book (which would become &lt;em&gt;Automate the Boring Stuff with Python&lt;/em&gt;), I signed a contract with No Starch Press. I&amp;rsquo;ve really enjoyed working with them: their editors are great, their books are all high-quality, and they were fine with me continuing to release titles under a Creative Commons license.&lt;/p&gt;
&lt;p&gt;Around 2012, &amp;ldquo;everyone should learn to code&amp;rdquo; was making the rounds in the news again, as it seems to have done every five or ten years for the last few decades. And I thought, &amp;ldquo;Sure, but why?&amp;rdquo; Not everyone needs to become a software engineer, and nobody needs to calculate Fibonacci numbers.&lt;/p&gt;
&lt;p&gt;I thought about what non-programmers could use coding for. Twenty years ago, if you were chatting with your friends online every day, you were probably a huge nerd. But today, you&amp;rsquo;re just the average Facebook user. Lots of people use computers for their office jobs or at home.&lt;/p&gt;
&lt;p&gt;What kinds of things would they like to automate that won&amp;rsquo;t require a computer science degree? As it turns out, there&amp;rsquo;s a lot! I have a friend who joked that if you want to become a millionaire startup founder, just find an industry that still uses fax machines and Excel spreadsheets for everything and write the web app that gets adopted by that entire field.&lt;/p&gt;
&lt;p&gt;So I had a list of stuff like &amp;ldquo;update spreadsheets&amp;rdquo; and &amp;ldquo;send notification emails,&amp;rdquo; and all of that became &lt;em&gt;Automate the Boring Stuff with Python&lt;/em&gt;. The software developer job I had at the time had gotten a bit stale, so I left it thinking I&amp;rsquo;d spend a year finishing &lt;em&gt;Automate&lt;/em&gt; and then get another software developer job. I&amp;rsquo;ve been a full-time writer and online course developer for six years now.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s been a lot of luck. I&amp;rsquo;m lucky that hundreds of people have contributed to a free, open-source language like Python that makes programming so easy. I&amp;rsquo;m lucky I had savings so I could take a chance with book writing. I&amp;rsquo;m lucky that others have created the free software culture that led to things like the Creative Commons license.&lt;/p&gt;
&lt;p&gt;So when people ask me for book-writing advice, it&amp;rsquo;s kind of like asking a lottery winner what numbers to pick. I still think there&amp;rsquo;s a lot of needless barriers in our society that need to be torn down to let people reach their full potential, so that aim has been my guiding star.&lt;/p&gt;
&lt;p class=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;Anyone who has followed you for any amount of time on Twitter will know you have a passion for teaching Python to people learning to code. You particularly seem to like using video games as the entry point. Have you found that focusing more on the &amp;ldquo;fun&amp;rdquo; topics has helped you reach more people, and helped them get into Python? And was it intentional, or were you scratching your own itch?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Al:&lt;/strong&gt; Just the other day I found a slide from &lt;a href=&quot;https://twitter.com/mhashemi&quot;&gt;Mahmoud Hashemi&amp;rsquo;s&lt;/a&gt; 2019 PyBay talk that was titled &amp;ldquo;There are two reasons to start wanting to code&amp;rdquo; and it had a Venn diagram with &amp;ldquo;I want to make a video game&amp;rdquo; and &amp;ldquo;I want to be free of Excel.&amp;rdquo; Never have I seen my entire teaching and writing career summed up like that before. Video games are an excellent gateway into programming, especially with a tool like &lt;a href=&quot;https://scratch.mit.edu&quot;&gt;MIT&amp;rsquo;s Scratch&lt;/a&gt;. But it&amp;rsquo;s kind of hard to use video games sometimes. &lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll be standing in front of a classroom of 9-year-olds and say, &amp;ldquo;We&amp;rsquo;re going to make a game,&amp;rdquo; and they&amp;rsquo;re thinking of &lt;em&gt;Minecraft&lt;/em&gt; or &lt;em&gt;Breath of the Wild&lt;/em&gt; or some other title that had a professional development team with a hundred-million-dollar budget, and instead I say, &amp;ldquo;How about we make a maze or Simon Says game?&amp;rdquo; It&amp;rsquo;s all about managing expectations. There&amp;rsquo;s still the basic fun of creating something, of telling the computer what to do and seeing it do that.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve been working on creating a collection of small, easy to understand, text-based games in Python, which I&amp;rsquo;ve put &lt;a href=&quot;https://github.com/asweigart/pythonstdiogames&quot;&gt;online&lt;/a&gt;. The idea is that once you know about programming concepts like loops and variables, you can see these used in actual programs with these games. &lt;/p&gt;
&lt;p&gt;I shudder when people tell new programmers to get better by reading the code of open source projects because those projects are often massive and poorly documented. Very few of them have onboarding guides to get new volunteers up to speed with the code base, so it&amp;rsquo;s hard to wrap your head around that code.&lt;/p&gt;
&lt;p&gt;New coders just come away from it feeling intimidated. So my simple games are like training wheels on a bike, and the constraints I follow to enforce simplicity are actually pretty good at making me come up with creative but simple programs.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m not a game designer by any means. All the games I&amp;rsquo;ve made are, at most, a few hundred lines of code, and they&amp;rsquo;ve always been things that are mechanic-heavy like &lt;em&gt;Tetris&lt;/em&gt; or that &lt;a href=&quot;https://playsnake.org/&quot;&gt;growing worm game&lt;/a&gt; everyone had on their Nokia cell phone. These games don&amp;rsquo;t require a lot in the way of graphics or level design.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m in awe of folks like Toby Fox or Eric Barone who spent years on their own creating &lt;em&gt;Undertale&lt;/em&gt; and &lt;em&gt;Stardew Valley&lt;/em&gt;, respectively. But even those games stand on the shoulders of giants. &lt;em&gt;Undertale&lt;/em&gt; and &lt;em&gt;Stardew Valley&lt;/em&gt; were inspired by &lt;em&gt;Earthbound&lt;/em&gt; and &lt;em&gt;Harvest Moon&lt;/em&gt;, but have the benefit of modern game design insights (and overwhelming talent on the part of Fox and Barone).&lt;/p&gt;
&lt;p&gt;Likewise, all of my text-based games are similar to the ones you&amp;rsquo;d find in David Ahl&amp;rsquo;s &lt;em&gt;BASIC Computer Games&lt;/em&gt; book or &lt;em&gt;BYTE&lt;/em&gt; Magazine from the 70s and 80s, but with the benefit of a few decades of game design theory. All of this was intentional on my part (I wouldn&amp;rsquo;t be creating these small games if not for getting a programming tutorial out of them), but I don&amp;rsquo;t think I could do it any other way; nothing is as good of a hook to get kids and adults into programming as these fun little video games.&lt;/p&gt;
&lt;p&gt;Also, anyone who has followed me for any amount of time on Twitter will also know that I have a passion for political rants. I try to stay on the constructive side for those, at least.&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 few programmers (and definitely one of only a handful of Python programmers that I know of) that live codes on &lt;a href=&quot;https://www.twitch.tv/AlSweigart&quot;&gt;Twitch&lt;/a&gt;. How has that experience been, and what have you learned through the process? Do we need to be encouraging more Python Twitch streamers?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Al:&lt;/strong&gt; I&amp;rsquo;ve been streaming off and on over the last couple of years, sometimes with weeks or months in between streams. It&amp;rsquo;s an unfortunate truth that you essentially have to do it as a full-time job for about a year before you can grow an audience to a size that can sustain a career, and I don&amp;rsquo;t have that kind of time. But it&amp;rsquo;s nice as a hobby. &lt;/p&gt;
&lt;p&gt;I can stream myself as I work on my small games or as I record myself creating online courses. It lets me practice being on camera while coding and narrating, which is useful for my online video course work. And it puts me in touch with beginners, so I can understand what parts they have trouble with or what questions they have. &lt;/p&gt;
&lt;p&gt;Twitch deletes my streams about a week after I stream them and some folks have asked that I archive them somewhere permanent, but I really don&amp;rsquo;t think of it as much more than something to have on in the background. I&amp;rsquo;d much prefer creating polished, 10-minute videos than a four-hour stream of me rambling and trying to look up documentation.&lt;/p&gt;
&lt;p class=&quot;mt-5&quot;&gt;&lt;strong&gt;Ricky:&lt;/strong&gt; &lt;em&gt;Now for our last few questions. What else do you get up to in your spare time? What other hobbies and interests do you have, aside from Python and coding?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Al:&lt;/strong&gt; Spare time, eh? I&amp;rsquo;m afraid I don&amp;rsquo;t understand the question&amp;hellip;&lt;/p&gt;
&lt;p&gt;A nice thing about my current career is that it certainly keeps me busy. Writing programming tutorials pretty much was my side hobby, and now I get to do it full time, with all the benefits and disadvantages that brings. I have enough projects to last me well into 2021, but at the same time, I want them all done now.&lt;/p&gt;
&lt;p&gt;The biggest motivation for finishing my current books and videos is that I&amp;rsquo;ll be able to start on my next book and video. I jokingly asked a friend if starting a cocaine habit would improve my productivity and she said, &amp;ldquo;Sure, at first.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;But aside from writing programs and writing books about programs, I like doing origami. It&amp;rsquo;s something I was interested in as a kid, but I&amp;rsquo;d always get halfway through the folding diagrams in books before reaching a step I couldn&amp;rsquo;t figure out, and I&amp;rsquo;d have to abandon it.&lt;/p&gt;
&lt;p&gt;This is another thing from my childhood that the internet has improved tremendously: these days, there&amp;rsquo;s a million origami folding videos online, so I&amp;rsquo;m able to put together models that are far more impressive than anything I could have done as a kid.&lt;/p&gt;
&lt;p&gt;Another friend pointed out that writing software, writing books, folding origami, and essentially all my hobbies have one thing in common: they&amp;rsquo;re all cheap! Give me an old laptop and a stack of paper, and I&amp;rsquo;ll be fairly content.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If you want to see what Al is up to, you can reach out to him on &lt;a href=&quot;https://twitter.com/AlSweigart&quot;&gt;Twitter&lt;/a&gt; and say hi. His blog and his plethora of books can be found on his website, &lt;a href=&quot;https://inventwithpython.com/&quot;&gt;Invent With Python&lt;/a&gt;. Thank you, Al, for talking to me!&lt;/p&gt;
&lt;p&gt;If you have someone you&amp;rsquo;d like me to reach out to for an interview, leave a comment below and let me know.&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 and PyQt: Building a GUI Desktop Calculator</title>
      <id>https://realpython.com/python-pyqt-gui-calculator/</id>
      <link href="https://realpython.com/python-pyqt-gui-calculator/"/>
      <updated>2019-10-23T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn how to create Graphical User Interface (GUI) applications with Python and PyQt. Once you&#39;ve covered the basics, you&#39;ll build a fully-functional desktop calculator that can respond to user events with concrete actions.</summary>
      <content type="html">
        &lt;p&gt;Even as web and mobile applications appear to overtake the software development market, there&amp;rsquo;s still a demand for traditional &lt;strong&gt;Graphical User Interface (GUI)&lt;/strong&gt; desktop applications. For developers who are interested in building these kinds of applications in Python, there are a wide variety of libraries to choose from, including &lt;a href=&quot;https://docs.python.org/3/library/tkinter.html&quot;&gt;Tkinter&lt;/a&gt;, &lt;a href=&quot;https://realpython.com/python-gui-with-wxpython/&quot;&gt;wxPython&lt;/a&gt;, &lt;a href=&quot;https://www.riverbankcomputing.com/software/pyqt/intro&quot;&gt;PyQt&lt;/a&gt;, &lt;a href=&quot;https://wiki.qt.io/Qt_for_Python&quot;&gt;PySide2&lt;/a&gt;, and others. In this tutorial, you&amp;rsquo;ll develop GUI desktop applications with Python and &lt;strong&gt;PyQt&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&amp;rsquo;ll learn how to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create Graphical User Interfaces with Python and PyQt&lt;/li&gt;
&lt;li&gt;Give life to your applications by connecting user events to concrete actions&lt;/li&gt;
&lt;li&gt;Create fully-functional GUI applications to solve real-world problems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this tutorial, you&amp;rsquo;ll create a calculator application with Python and PyQt. This will help you grasp the fundamentals and get you up and running with the library. You can download the source code for the project and all examples in this tutorial by clicking on the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/pyqt-calculator/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-pyqt-calculator&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to build a calculator in Python with PyQt in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;understanding-pyqt&quot;&gt;Understanding PyQt&lt;/h2&gt;
&lt;p&gt;PyQt is a Python binding for &lt;strong&gt;&lt;a href=&quot;https://wiki.qt.io/About_Qt&quot;&gt;Qt&lt;/a&gt;&lt;/strong&gt;, which is a set of &lt;a href=&quot;https://realpython.com/python-vs-cpp/&quot;&gt;C++&lt;/a&gt; libraries and development tools that include platform-independent abstractions for Graphical User Interfaces (GUI), as well as networking, threads, regular expressions, SQL databases, SVG, OpenGL, XML, and many other powerful features. Developed by &lt;a href=&quot;https://riverbankcomputing.com&quot;&gt;RiverBank Computing Ltd&lt;/a&gt;, PyQt is available in two editions:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt4/introduction.html&quot;&gt;PyQt4&lt;/a&gt;:&lt;/strong&gt; an edition that&amp;rsquo;s built against Qt 4.x and 5.x&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/introduction.html&quot;&gt;PyQt5&lt;/a&gt;:&lt;/strong&gt; an edition that&amp;rsquo;s only built against Qt 5.x&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Even though PyQt4 can be built against Qt 5.x, only a small subset that is also compatible with Qt 4.x will be supported. This means that if you decide to use PyQt4, then you&amp;rsquo;ll probably miss out on some of the new features and improvements in PyQt5. See the &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt4/qt_v5.html&quot;&gt;PyQt4 documentation&lt;/a&gt; for more information on this topic.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll be covering PyQt5 in this tutorial, as it seems to be the future of the library. From now on, be sure to consider any mention of PyQt as a reference to PyQt5.&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 want to dive deeper into the differences between the two versions of the library, then you can take a look at the related page on the &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/&quot;&gt;PyQt5 documentation&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;PyQt5 is based on &lt;a href=&quot;https://doc.qt.io&quot;&gt;Qt v5&lt;/a&gt; and includes classes that cover Graphical User Interfaces as well as XML handling, network communication, regular expressions, threads, SQL databases, multimedia, web browsing, and other technologies available in Qt. PyQt5 implements over one thousand of these Qt classes in a set of &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/module_index.html#ref-module-index&quot;&gt;Python modules&lt;/a&gt;, all of which are contained within a top-level Python package called &lt;code&gt;PyQt5&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;PyQt5 is compatible with Windows, Unix, Linux, macOS, iOS, and Android. This can be an attractive feature if you&amp;rsquo;re looking for a library or framework to develop multi-platform applications with a native look and feel on each platform.&lt;/p&gt;
&lt;p&gt;PyQt5 is available under two licenses:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://riverbankcomputing.com/commercial/buy&quot;&gt;The Riverbank Commercial License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.gnu.org/licenses/gpl-3.0.en.html&quot;&gt;The General Public License (GPL), version 3&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Your PyQt5 license must be compatible with your Qt license. If you use the GPL version, then your code must also use a GPL-compatible license. If you want to use PyQt5 to create commercial applications, then you&amp;rsquo;ll need a commercial license for your installation.&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 &lt;a href=&quot;https://www.qt.io/&quot;&gt;Qt Company&lt;/a&gt; has developed and currently maintains its own Python binding for the Qt library. The Python library is called &lt;a href=&quot;https://wiki.qt.io/Qt_for_Python&quot;&gt;Qt for Python&lt;/a&gt; and is considered to be the official Qt for Python. In this case, the Python package is called PySide2.&lt;/p&gt;
&lt;p&gt;As PyQt5 and PySide2 are both built on top of Qt, their APIs are quite similar, even almost identical. That&amp;rsquo;s why porting PyQt5 code to PySide2 can be as simple as updating some imports. If you learn one of them, then you&amp;rsquo;ll be able to work with the other with minimal effort. If you want to dive deeper into the differences between these two libraries, then you can check out the following resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://machinekoder.com/pyqt-vs-qt-for-python-pyside2-pyside/&quot;&gt;PyQt vs Qt for Python (PySide2)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.learnpyqt.com/blog/pyqt5-vs-pyside2/&quot;&gt;What&amp;rsquo;s the difference between PyQt5 and PySide2?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&quot;installing-pyqt&quot;&gt;Installing PyQt&lt;/h2&gt;
&lt;p&gt;You have several options to choose from when you install PyQt on your system or development environment. The first option is to build from source. This can be a bit complicated, so you might want to avoid it if possible. If you really need to build from source, then you can take a look at what the library&amp;rsquo;s &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/installation.html#building-and-installing-from-source&quot;&gt;documentation&lt;/a&gt; recommends in those cases.&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; Most of the installation options you&amp;rsquo;ll cover here require that you have a working Python installation. If you need to dive deeper into how to install Python, then check out &lt;a href=&quot;https://realpython.com/courses/installing-python-windows-macos-linux/&quot;&gt;Installing Python on Windows, macOS, and Linux&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Another option would be to use binary wheels. Wheels are a very popular way to manage the installation of Python packages. However, you need to consider that wheels for PyQt5 are only available for Python 3.5 and later. There are wheels for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux (64-bit)&lt;/li&gt;
&lt;li&gt;macOS&lt;/li&gt;
&lt;li&gt;Windows (32-bit and 64-bit)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All of these wheels include copies of the corresponding Qt libraries, so you won&amp;rsquo;t need to install them separately.&lt;/p&gt;
&lt;p&gt;Your third option is to use package managers on Linux distributions and macOS. For Windows, you can use a binary &lt;code&gt;.exe&lt;/code&gt; file. Your fourth and final option is to use the Anaconda distribution to install PyQt on your system. The next few sections will walk you through some of the options you have to properly install PyQt5 from different sources and on different platforms.&lt;/p&gt;
&lt;h3 id=&quot;system-wide-installation-with-pip&quot;&gt;System-Wide Installation With &lt;code&gt;pip&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;If you&amp;rsquo;re using Python 3.5 or later, then you can install PyQt5 from &lt;a href=&quot;https://pypi.org/project/PyQt5/&quot;&gt;PyPI&lt;/a&gt; by running 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; pip3 install pyqt5
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this command, you&amp;rsquo;ll install PyQt5 in your base system. You can start using the library immediately after the installation finishes. Depending on your operating system, you may need root or administrator privileges for this installation to work.&lt;/p&gt;
&lt;h3 id=&quot;virtual-environment-installation-with-pip&quot;&gt;Virtual Environment Installation With &lt;code&gt;pip&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;You may decide not to install PyQt directly on your base system to avoid messing up your configuration. In this case, you can use a Python &lt;a href=&quot;https://realpython.com/courses/working-python-virtual-environments/&quot;&gt;virtual environment&lt;/a&gt;. Use the following commands to create one and install PyQt5:&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 -m venv pyqtvenv
&lt;span class=&quot;gp&quot;&gt;$&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;source&lt;/span&gt; pyqtvenv/bin/activate
&lt;span class=&quot;gp&quot;&gt;(pyqtvenv) $&lt;/span&gt; pip install pyqt5
&lt;span class=&quot;go&quot;&gt;Collecting pyqt5&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Successfully installed PyQt5-sip-4.19.17 pyqt5-5.12.2&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you create a virtual environment with &lt;code&gt;venv&lt;/code&gt;. Once you activate it, you install &lt;code&gt;pyqt5&lt;/code&gt; in that environment with &lt;code&gt;pip install pyqt5&lt;/code&gt;. This installation alternative is the most recommended option if you want to keep your base system clean.&lt;/p&gt;
&lt;h3 id=&quot;platform-specific-installation&quot;&gt;Platform-Specific Installation&lt;/h3&gt;
&lt;p&gt;In the Linux ecosystem, several distributions include binary packages for PyQt in their repositories. If this is true for your distribution, then you can install the library using the distribution&amp;rsquo;s package manager. On Ubuntu 18.04 for example, you can use 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; sudo apt install python3-pyqt5
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With this command, you&amp;rsquo;ll install PyQt5 and all its dependencies in your base system, so you can use the library in any of your GUI projects. Note that root privileges are needed, which you invoke here with &lt;code&gt;sudo&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re a Mac user, then you can install PyQt5 using the &lt;a href=&quot;https://brew.sh&quot;&gt;Homebrew&lt;/a&gt; package manager. To do that, open a terminal and type in 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; brew install pyqt5
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If all goes well, then you&amp;rsquo;ll have PyQt5 installed on your base system, ready for you to use.&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 use a package manager on Linux or macOS, then there&amp;rsquo;s a chance you won&amp;rsquo;t get the latest version of PyQt5. A &lt;code&gt;pip&lt;/code&gt; installation would be better if you want to ensure that you have the latest release.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If you prefer to use Windows, but you decide not to use the binary wheels, then your path through PyQt installation can be painful. That&amp;rsquo;s because the PyQt5 &lt;a href=&quot;https://www.riverbankcomputing.com/software/pyqt/download5&quot;&gt;download page&lt;/a&gt; appears to no longer provide Windows binaries (&lt;code&gt;.exe&lt;/code&gt; files) for later versions. Still, you can find some Windows binary packages for older versions of the library at the &lt;a href=&quot;https://sourceforge.net/projects/pyqt/files/PyQt5/&quot;&gt;project page&lt;/a&gt;. The latest binary file was built for &lt;a href=&quot;https://sourceforge.net/projects/pyqt/files/PyQt5/PyQt-5.6/&quot;&gt;PyQt v5.6&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;If you really need to install PyQt this way, then you&amp;rsquo;ll need to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Determine what version of Python you&amp;rsquo;re running and whether you have 32-bit or 64-bit Python&lt;/li&gt;
&lt;li&gt;Download the right version for your Python installation&lt;/li&gt;
&lt;li&gt;Install PyQt by running the &lt;code&gt;.exe&lt;/code&gt; file and following the on-screen instructions&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;anaconda-installation&quot;&gt;Anaconda Installation&lt;/h3&gt;
&lt;p&gt;Another alternative you can use to install PyQt is &lt;a href=&quot;https://docs.anaconda.com/anaconda/&quot;&gt;Anaconda&lt;/a&gt;, a Python distribution for data science. Anaconda is a free and multi-platform package and environment manager that includes a collection of over 1,500 open source &lt;a href=&quot;https://docs.anaconda.com/anaconda/packages/pkg-docs/&quot;&gt;packages&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Anaconda provides a user-friendly installation wizard that you can use to install PyQt on your system. You can &lt;a href=&quot;https://www.anaconda.com/distribution/#download-section&quot;&gt;download&lt;/a&gt; the appropriate version for your current platform and follow the on-screen instructions. If you install the latest version of Anaconda, then you&amp;rsquo;ll have the following packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://www.riverbankcomputing.co.uk/software/pyqt&quot;&gt;&lt;code&gt;pyqt&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; a Python binding for the cross-platform GUI toolkit Qt (Commercial, GPL-2.0, GPL-3.0 licenses)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/ales-erjavec/anyqt/&quot;&gt;&lt;code&gt;anyqt&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; a compatibility layer for PyQt4/PyQt5 (GPL-3.0 license)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/spyder-ide/qtpy&quot;&gt;&lt;code&gt;qtpy&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; an abstraction layer PyQt5/PyQt4/PySide (MIT license)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;http://www.pyqtgraph.org&quot;&gt;&lt;code&gt;pyqtgraph&lt;/code&gt;&lt;/a&gt;:&lt;/strong&gt; a Python library for Scientific Graphics (MIT license)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With this set of packages, you&amp;rsquo;ll have all that you need to develop GUI desktop applications with Python and PyQt.&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; Note that the Anaconda installation will occupy a large amount of disk space. If you install Anaconda only to use the PyQt packages, then you&amp;rsquo;ll have a serious amount of unused packages and libraries on your system. Keep this in mind when you consider using the Anaconda distribution.&lt;/p&gt;
&lt;/div&gt;
&lt;h2 id=&quot;creating-your-first-pyqt-application&quot;&gt;Creating Your First PyQt Application&lt;/h2&gt;
&lt;p&gt;Now that you have a working PyQt installation, you&amp;rsquo;re ready to start coding. You&amp;rsquo;re going to create a &amp;ldquo;Hello, World!&amp;rdquo; application with Python and PyQt. Here are the steps you&amp;rsquo;ll follow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Import &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qapplication.html&quot;&gt;&lt;code&gt;QApplication&lt;/code&gt;&lt;/a&gt; and all the required widgets from &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qtwidgets-module.html&quot;&gt;&lt;code&gt;PyQt5.QtWidgets&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Create an instance of &lt;code&gt;QApplication&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create an instance of your application&amp;rsquo;s GUI.&lt;/li&gt;
&lt;li&gt;Show your application&amp;rsquo;s GUI.&lt;/li&gt;
&lt;li&gt;Run your application&amp;rsquo;s event loop (or main loop).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can download the source code for the examples you&amp;rsquo;ll cover in this section at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/pyqt-calculator/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-pyqt-calculator&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to build a calculator in Python with PyQt in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;ll start with a file called &lt;code&gt;hello.py&lt;/code&gt; in your current working directory:&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;# Filename: hello.py&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Simple Hello World example with PyQt5.&amp;quot;&amp;quot;&amp;quot;&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;hll&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# 1. Import `QApplication` and all the required widgets&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLabel&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;First, you import &lt;code&gt;sys&lt;/code&gt;, which will allow you to handle the exit status of the application. Then, you import &lt;code&gt;QApplication&lt;/code&gt;,  &lt;code&gt;QWidget&lt;/code&gt;, and &lt;code&gt;QLabel&lt;/code&gt; from &lt;code&gt;QtWidgets&lt;/code&gt;, which is part of the package called &lt;code&gt;PyQt5&lt;/code&gt;. You&amp;rsquo;ll be using these imports later on, but for now, you&amp;rsquo;re done with step one.&lt;/p&gt;
&lt;p&gt;For step two, you need to create an instance of &lt;code&gt;QApplication&lt;/code&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;hll&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# 2. Create an instance of QApplication&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you create the instance of &lt;code&gt;QApplication&lt;/code&gt;. Since the &lt;code&gt;QApplication&lt;/code&gt; object (&lt;code&gt;app&lt;/code&gt;) does so much initialization, you should create it before you create any other object related to the GUI. The &lt;code&gt;QApplication&lt;/code&gt; object also deals with common command line arguments, so you also need to pass in &lt;code&gt;sys.argv&lt;/code&gt; as an argument when you create &lt;code&gt;app&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;sys.argv&lt;/code&gt; contains the &lt;code&gt;list&lt;/code&gt; of command-line arguments passed into a Python script. If your application is not going to accept command line arguments, then you can use an empty &lt;code&gt;list&lt;/code&gt; instead of &lt;code&gt;sys.argv&lt;/code&gt;. That is, you can do something like &lt;code&gt;app = QApplication([])&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Step three is to create the application&amp;rsquo;s GUI. For this example, your GUI will be based on &lt;code&gt;QWidget&lt;/code&gt;, which is the base class of all user interface objects in PyQt. Let&amp;rsquo;s create the GUI:&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;c1&quot;&gt;# 3. Create an instance of your application&amp;#39;s GUI&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setWindowTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;PyQt5 App&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setGeometry&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;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;280&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&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;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;helloMsg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;lt;h1&amp;gt;Hello World!&amp;lt;/h1&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;helloMsg&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;move&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;15&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, &lt;code&gt;window&lt;/code&gt; is an instance of &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qwidget.html&quot;&gt;&lt;code&gt;QWidget&lt;/code&gt;&lt;/a&gt;, which provides all the features you&amp;rsquo;ll need to create the application&amp;rsquo;s window (or form). With &lt;code&gt;.setWindowTitle()&lt;/code&gt;, you can add a title to your application&amp;rsquo;s window. In this case, the title to show is &lt;code&gt;PyQt5 App&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can use &lt;code&gt;.setGeometry()&lt;/code&gt; to define the size of the window and where to place it on your screen. The first two parameters are the &lt;code&gt;x&lt;/code&gt; and &lt;code&gt;y&lt;/code&gt; coordinates at which the window will be placed on the screen. The third and fourth parameters are the &lt;code&gt;width&lt;/code&gt; and &lt;code&gt;height&lt;/code&gt; of the window.&lt;/p&gt;
&lt;p&gt;Every functional GUI application needs widgets! Here, you use a &lt;code&gt;QLabel&lt;/code&gt; object (&lt;code&gt;helloMsg&lt;/code&gt;) to show the message &lt;code&gt;Hello World!&lt;/code&gt; on your application&amp;rsquo;s window. &lt;code&gt;QLabel&lt;/code&gt; objects can accept HTML text, so you can use the HTML element &lt;code&gt;&#39;&amp;lt;h1&amp;gt;Hello World!&amp;lt;/h1&amp;gt;&#39;&lt;/code&gt; to format the text as an &lt;code&gt;h1&lt;/code&gt; header. Finally, you use &lt;code&gt;.move()&lt;/code&gt; to place &lt;code&gt;helloMsg&lt;/code&gt; at the coordinates &lt;code&gt;(60, 15)&lt;/code&gt; on your application&amp;rsquo;s window.&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 PyQt5, you can use any widget (a subclass of &lt;code&gt;QWidget&lt;/code&gt;) as a top-level window, or even a button or a label. The only condition is that you pass no &lt;code&gt;parent&lt;/code&gt; to it. When you use a widget like this, PyQt5 automatically gives it a title bar and turns it into a normal window.&lt;/p&gt;
&lt;p&gt;The parent-child relationship is used for two complementary purposes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A widget that doesn&amp;rsquo;t have a &lt;code&gt;parent&lt;/code&gt; is a &lt;strong&gt;main window&lt;/strong&gt; or a &lt;strong&gt;top-level window&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;A widget that has a &lt;code&gt;parent&lt;/code&gt; (which is always another widget) is contained (or shown) within its &lt;code&gt;parent&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This relationship also defines &lt;strong&gt;ownership&lt;/strong&gt;, with parents owning their children. The PyQt5 ownership model ensures that if you delete a &lt;code&gt;parent&lt;/code&gt; (for example, a top-level window), then all of its children (widgets) are automatically deleted as well.&lt;/p&gt;
&lt;p&gt;To avoid memory leaks, you should always make sure that any &lt;code&gt;QWidget&lt;/code&gt; object has a &lt;code&gt;parent&lt;/code&gt;, with the sole exception of top-level windows.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You&amp;rsquo;re done with step three, so let&amp;rsquo;s code the last two steps and get your first PyQt GUI application ready to go live:&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;c1&quot;&gt;# 4. Show your application&amp;#39;s GUI&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&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;hll&quot;&gt;&lt;span class=&quot;c1&quot;&gt;# 5. Run your application&amp;#39;s event loop (or main loop)&lt;/span&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;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you call &lt;code&gt;.show()&lt;/code&gt; on &lt;code&gt;window&lt;/code&gt;. The call to &lt;code&gt;.show()&lt;/code&gt; schedules a paint event. In other words, it adds a new event to the application&amp;rsquo;s event queue. You cover the event loop in a later section.&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; A &lt;strong&gt;paint event&lt;/strong&gt; is a request for painting the widgets that compose a GUI.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Finally, you start the application&amp;rsquo;s event loop by calling &lt;code&gt;app.exec_()&lt;/code&gt;. The call to &lt;code&gt;.exec_()&lt;/code&gt; is wrapped in a call to &lt;code&gt;sys.exit()&lt;/code&gt;, which allows you to cleanly exit Python and release memory resources when the application terminates. You can run &lt;code&gt;hello.py&lt;/code&gt; with 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; python3 hello.py
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you &lt;a href=&quot;https://realpython.com/run-python-scripts/&quot;&gt;run this script&lt;/a&gt;, you should see a window like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/hello.066635a13824.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/hello.066635a13824.png&quot; width=&quot;306&quot; height=&quot;137&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/hello.066635a13824.png&amp;amp;w=76&amp;amp;sig=99b6c5140209d05cbfe9f4618e0cf99281b198a9 76w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/hello.066635a13824.png&amp;amp;w=153&amp;amp;sig=ae857aa6fa0a884d808ab2a6d7aa5111c85a2f0e 153w, https://files.realpython.com/media/hello.066635a13824.png 306w&quot; sizes=&quot;75vw&quot; alt=&quot;Hello World PyQt GUI application&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Here, your application shows a window (based on &lt;code&gt;QWidget&lt;/code&gt;) with the message &lt;code&gt;Hello World!&lt;/code&gt; on it. To show the message, you use a &lt;code&gt;QLabel&lt;/code&gt; that contains the message in HTML format.&lt;/p&gt;
&lt;p&gt;Congrats! You&amp;rsquo;ve created your first PyQt GUI desktop application!&lt;/p&gt;
&lt;h2 id=&quot;considering-code-styles&quot;&gt;Considering Code Styles&lt;/h2&gt;
&lt;p&gt;If you take a closer look at the code for your first application, then you&amp;rsquo;ll notice that PyQt doesn&amp;rsquo;t follow &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008&quot;&gt;PEP 8&lt;/a&gt; coding style and naming conventions. PyQt is built on top of Qt, which is written in C++ and uses a camelCase naming style for functions, methods, and variables. That said, you&amp;rsquo;ll need to decide what naming style you&amp;rsquo;re going to use for your own PyQt GUI applications.&lt;/p&gt;
&lt;p&gt;With regard to this issue, PEP 8 states that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;New modules and packages (including third party frameworks) should be written to these standards, but where an existing library has a different style, internal consistency is preferred. (&lt;a href=&quot;https://www.python.org/dev/peps/pep-0008&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In addition, the &lt;a href=&quot;https://www.python.org/dev/peps/pep-0020/&quot;&gt;Zen of Python&lt;/a&gt; says:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&amp;hellip;practicality beats purity. (&lt;a href=&quot;https://www.python.org/dev/peps/pep-0020/&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you want to write consistent code, then you might want to disregard PEP 8 naming style and stick to the PyQt naming style. This is a decision that you need to make. In this tutorial, you&amp;rsquo;ll follow the PyQt naming style for consistency.&lt;/p&gt;
&lt;h2 id=&quot;learning-the-basics-of-pyqt&quot;&gt;Learning the Basics of PyQt&lt;/h2&gt;
&lt;p&gt;You&amp;rsquo;ll need to master the basic concepts of PyQt logic in order to efficiently use the library to develop GUI applications. Some of these concepts include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Widgets&lt;/li&gt;
&lt;li&gt;Layout managers&lt;/li&gt;
&lt;li&gt;Dialogs&lt;/li&gt;
&lt;li&gt;Main windows&lt;/li&gt;
&lt;li&gt;Applications&lt;/li&gt;
&lt;li&gt;Event loops&lt;/li&gt;
&lt;li&gt;Signals and slots&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These elements will be the building blocks of your PyQt GUI applications. Most of them are represented as Python classes. &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qtwidgets-module.html#&quot;&gt;&lt;code&gt;PyQt5.QtWidgets&lt;/code&gt;&lt;/a&gt; is the module that provides all these classes. These elements are extremely important, so you&amp;rsquo;ll cover them in the next few sections.&lt;/p&gt;
&lt;h3 id=&quot;widgets&quot;&gt;Widgets&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;QWidget&lt;/code&gt; is the base class for all user interface objects, or &lt;strong&gt;widgets&lt;/strong&gt;. These are rectangular-shaped graphical components that you can place on your application&amp;rsquo;s windows to build the GUI. Widgets contain a series of attributes and methods that allow you to model their appearance and behavior. They can also paint a representation of themselves on the screen.&lt;/p&gt;
&lt;p&gt;Widgets also receive mouse clicks, keypresses, and other events from the user, the window system, and many other sources. Each time a widget catches an event, it emits a signal to announce its state change. PyQt5 has a rich and modern collection of widgets that serve several purposes. Some of the most common and useful widgets are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Buttons&lt;/li&gt;
&lt;li&gt;Labels&lt;/li&gt;
&lt;li&gt;Line edits&lt;/li&gt;
&lt;li&gt;Combo boxes&lt;/li&gt;
&lt;li&gt;Radio buttons&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s take a closer look at each of these widgets. First up is the &lt;strong&gt;button&lt;/strong&gt;. You can create a button by instantiating &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qpushbutton.html&quot;&gt;&lt;code&gt;QPushButton&lt;/code&gt;&lt;/a&gt;, a class that provides a classical command button. Typical buttons are &lt;code&gt;OK&lt;/code&gt;, &lt;code&gt;Cancel&lt;/code&gt;, &lt;code&gt;Apply&lt;/code&gt;, &lt;code&gt;Yes&lt;/code&gt;, &lt;code&gt;No&lt;/code&gt;, and &lt;code&gt;Close&lt;/code&gt;. Here&amp;rsquo;s how they look on a Linux system:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/buttons.40e5948189f6.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/buttons.40e5948189f6.png&quot; width=&quot;274&quot; height=&quot;72&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/buttons.40e5948189f6.png&amp;amp;w=68&amp;amp;sig=af9426157c0dd9ddc606109bbcf9276bd4c1a8c7 68w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/buttons.40e5948189f6.png&amp;amp;w=137&amp;amp;sig=b1feaec7432716517fe652ca476bfca39350c1aa 137w, https://files.realpython.com/media/buttons.40e5948189f6.png 274w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QPushButton example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Buttons like these are perhaps the most commonly used widget in any GUI. When you click them, you can command the computer to perform actions. You can even perform actions in response to a user clicking a button.&lt;/p&gt;
&lt;p&gt;Up next are &lt;strong&gt;labels&lt;/strong&gt;, which you can create with &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qlabel.html&quot;&gt;&lt;code&gt;QLabel&lt;/code&gt;&lt;/a&gt;. Labels give you a way to display useful information in the form of text or images:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/labels.f7818e2fa725.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/labels.f7818e2fa725.png&quot; width=&quot;71&quot; height=&quot;94&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/labels.f7818e2fa725.png&amp;amp;w=17&amp;amp;sig=74da439210e34c9ccf15df8309a8c0d6ce86fabf 17w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/labels.f7818e2fa725.png&amp;amp;w=35&amp;amp;sig=4010c3a869e3b17f1e93c31cbb63315c8d89c2d2 35w, https://files.realpython.com/media/labels.f7818e2fa725.png 71w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QLabel example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can use labels like these to better explain the purpose or usage of your GUI. You can tweak their appearance in several ways, and they can even accept HTML text, as you saw earlier. Labels can also be used to specify a focus mnemonic key for another widget.&lt;/p&gt;
&lt;p&gt;Another common widget is the &lt;strong&gt;line edit&lt;/strong&gt;, a single-line text box that you can create with &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qlineedit.html&quot;&gt;&lt;code&gt;QLineEdit&lt;/code&gt;&lt;/a&gt;. Line edits are useful when you need the user to enter or edit data in plain text format. Here&amp;rsquo;s how they look on a Linux system:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/line-edits.41e67fc77d2b.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/line-edits.41e67fc77d2b.png&quot; width=&quot;353&quot; height=&quot;72&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/line-edits.41e67fc77d2b.png&amp;amp;w=88&amp;amp;sig=eb46fa8a34b237df8ca6e5af91c74be80a44616d 88w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/line-edits.41e67fc77d2b.png&amp;amp;w=176&amp;amp;sig=b73370cd7c1edf441e75775b5c7ea9d7007170ef 176w, https://files.realpython.com/media/line-edits.41e67fc77d2b.png 353w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QLineEdit example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Line edits like these provide basic editing operations like &lt;code&gt;copy&lt;/code&gt;, &lt;code&gt;paste&lt;/code&gt;, &lt;code&gt;undo&lt;/code&gt;, &lt;code&gt;redo&lt;/code&gt;, drag, drop, and so on. In the above figure, you can also see that the objects on the first row show placeholder text to inform the user what kind of input is required.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Combo boxes&lt;/strong&gt; are another useful widget that you can create with &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qcombobox.html&quot;&gt;&lt;code&gt;QComboBox&lt;/code&gt;&lt;/a&gt;. A combo box will present your user with a list of options in a way that takes up a minimal amount of screen space. Here&amp;rsquo;s an example of a dropdown list on a Linux system:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/combo-box.442ec954da54.gif&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/combo-box.442ec954da54.gif&quot; width=&quot;242&quot; height=&quot;202&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/combo-box.442ec954da54.gif&amp;amp;w=60&amp;amp;sig=4f8c472c749e37cbc6326b5086c226ada5443e4a 60w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/combo-box.442ec954da54.gif&amp;amp;w=121&amp;amp;sig=5a24d0337ee3b7f9eca2eeb516f8e080290e0a88 121w, https://files.realpython.com/media/combo-box.442ec954da54.gif 242w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QComboBox example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This combo box is &lt;strong&gt;read-only&lt;/strong&gt;, which means the user can select one of several options but can&amp;rsquo;t add their own. Combo boxes can also be &lt;strong&gt;editable&lt;/strong&gt;, allowing the user to add new options. They can contain pixmaps, strings, or both.&lt;/p&gt;
&lt;p&gt;The last widget you&amp;rsquo;ll cover here is the &lt;strong&gt;radio button&lt;/strong&gt;, which you can create with &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qradiobutton.html&quot;&gt;&lt;code&gt;QRadioButton&lt;/code&gt;&lt;/a&gt;. A &lt;code&gt;QRadioButton&lt;/code&gt; object is an option button that can be switched on (checked) or off (unchecked). Radio buttons are useful when you need the user to select one of many options. In this case, all options are visible on the screen at the same time:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/radio-buttons.dc2424d696dc.gif&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/radio-buttons.dc2424d696dc.gif&quot; width=&quot;198&quot; height=&quot;186&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/radio-buttons.dc2424d696dc.gif&amp;amp;w=49&amp;amp;sig=278718e127d3d0f8ce05d21a60a790b6b45bdb88 49w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/radio-buttons.dc2424d696dc.gif&amp;amp;w=99&amp;amp;sig=7746edaf898b6d6d1ae0d00c1640b31696573949 99w, https://files.realpython.com/media/radio-buttons.dc2424d696dc.gif 198w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QRadioButton example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this group of radio buttons, only one button can be checked at a given time. If the user selects another radio button, then the previously selected button will switch off automatically.&lt;/p&gt;
&lt;p&gt;PyQt5 has a large collection of widgets. At the time of this writing, there are over forty available for you to use to create your application&amp;rsquo;s GUI. Those you&amp;rsquo;ve covered so far are only a small sample, but they show you the power and flexibility of PyQt5. In the next section, you&amp;rsquo;ll cover how to lay out different widgets to create modern and functional GUIs for your applications.&lt;/p&gt;
&lt;h3 id=&quot;layout-managers&quot;&gt;Layout Managers&lt;/h3&gt;
&lt;p&gt;Now you know what widgets are and how to use them to build GUIs. But how can you arrange a set of widgets to create a GUI that is both coherent and functional? There are a variety of techniques that you can use to lay out the widgets on a form or window. For instance, you can use &lt;code&gt;.resize()&lt;/code&gt; and &lt;code&gt;.move()&lt;/code&gt; to give widgets absolute sizes and positions. However, this can have some drawbacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You&amp;rsquo;ll have to do a lot of manual calculations to determine the correct size and position of every single widget in your forms.&lt;/li&gt;
&lt;li&gt;You&amp;rsquo;ll have to do some extra calculations to correctly respond to changes in form size (&lt;strong&gt;resize event&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;You&amp;rsquo;ll have to redo all the calculations whenever you change the layout of your forms or add or remove widgets.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One alternative is to use &lt;code&gt;.resizeEvent()&lt;/code&gt; to calculate widget size and position dynamically.  However, the most effective alternative is might be to use &lt;strong&gt;layout managers&lt;/strong&gt;, which will both increase your productivity and improve your code&amp;rsquo;s maintainability.&lt;/p&gt;
&lt;p&gt;Layout managers are classes that allow you to size and position your widgets at the places you want them to be on the application&amp;rsquo;s form. Layout managers automatically adapt to resize events and content changes. They also control the size of the widgets within them. This means that the widgets in a layout are automatically resized whenever the form is resized.&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 develop international applications, then you may have seen how translated labels can be cut short. This is particularly likely when the target language is more verbose than the original language. Layout managers can help you avoid this common pitfall. However, this feature can be a bit tricky and can sometimes fail with particularly wordy languages.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;PyQt provides four basic layout manager classes:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qhboxlayout.html&quot;&gt;&lt;code&gt;QHBoxLayout&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qvboxlayout.html&quot;&gt;&lt;code&gt;QVBoxLayout&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qgridlayout.html&quot;&gt;&lt;code&gt;QGridLayout&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qformlayout.html&quot;&gt;&lt;code&gt;QFormLayout&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The first layout manager class is &lt;strong&gt;&lt;code&gt;QHBoxLayout&lt;/code&gt;&lt;/strong&gt;, which arranges widgets horizontally from left to right:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/horizontal-layout.39d78929812f.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/horizontal-layout.39d78929812f.png&quot; width=&quot;382&quot; height=&quot;81&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/horizontal-layout.39d78929812f.png&amp;amp;w=95&amp;amp;sig=85053330005c355475ec2dccdf44f992c1fd692c 95w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/horizontal-layout.39d78929812f.png&amp;amp;w=191&amp;amp;sig=6532566ed56a006380f7185f6593c57809244fcb 191w, https://files.realpython.com/media/horizontal-layout.39d78929812f.png 382w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QHBoxLayout schema&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The widgets will appear one next to the other, starting from the left.&lt;/p&gt;
&lt;p&gt;This code example shows you how to use &lt;code&gt;QHBoxLayout&lt;/code&gt; to arrange buttons horizontally:&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;# Filename: h_layout.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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Horizontal layout example.&amp;quot;&amp;quot;&amp;quot;&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QHBoxLayout&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&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;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;lineno&quot;&gt;13 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setWindowTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;QHBoxLayout&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QHBoxLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&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 class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Left&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&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;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Center&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&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;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Right&amp;#39;&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;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layout&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;n&quot;&gt;window&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;lineno&quot;&gt;21 &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;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The highlighted lines do the magic here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 15&lt;/strong&gt; creates a &lt;code&gt;QHBoxLayout&lt;/code&gt; object called &lt;code&gt;layout&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 16 to 18&lt;/strong&gt; add three buttons to &lt;code&gt;layout&lt;/code&gt; with &lt;code&gt;.addWidget()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 19&lt;/strong&gt; sets &lt;code&gt;layout&lt;/code&gt; as your window&amp;rsquo;s layout with &lt;code&gt;.setLayout()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you run &lt;code&gt;python3 h_layout.py&lt;/code&gt; from your command line,  you&amp;rsquo;ll get the following output:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/h-layout.3471b0b63bc8.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/h-layout.3471b0b63bc8.png&quot; width=&quot;299&quot; height=&quot;98&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/h-layout.3471b0b63bc8.png&amp;amp;w=74&amp;amp;sig=1ef1f79bad53bfcece9da73f5c0de12f147b6f67 74w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/h-layout.3471b0b63bc8.png&amp;amp;w=149&amp;amp;sig=3c9cb154bec27728fa58b80055d2b8d3d90f6c1d 149w, https://files.realpython.com/media/h-layout.3471b0b63bc8.png 299w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QHBoxLayout example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In the above figure, you added three buttons in a horizontal arrangement. Notice that the buttons are shown from left to right in the same order as you added them in your code.&lt;/p&gt;
&lt;p&gt;The next layout manager class is &lt;strong&gt;&lt;code&gt;QVBoxLayout&lt;/code&gt;&lt;/strong&gt;, which arranges widgets vertically, from top to bottom:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/vertical-layout.c173d779b79d.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/vertical-layout.c173d779b79d.png&quot; width=&quot;141&quot; height=&quot;201&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/vertical-layout.c173d779b79d.png&amp;amp;w=35&amp;amp;sig=6438e915b088bceab4f47475f4f0e34809cd9b0f 35w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/vertical-layout.c173d779b79d.png&amp;amp;w=70&amp;amp;sig=0c0db5ffc64df15a43800a084b107be5fe1d25a2 70w, https://files.realpython.com/media/vertical-layout.c173d779b79d.png 141w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QVBoxLayout schema&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Each new widget will appear beneath the previous one. You can use this class to construct vertical box layout objects and organize your widget from top to bottom.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how you can create and use a &lt;code&gt;QVBoxLayout&lt;/code&gt; 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;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Filename: v_layout.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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Vertical layout example.&amp;quot;&amp;quot;&amp;quot;&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QVBoxLayout&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&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;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;lineno&quot;&gt;13 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setWindowTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;QVBoxLayout&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QVBoxLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&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 class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Top&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&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;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Center&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&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;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Bottom&amp;#39;&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;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layout&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;n&quot;&gt;window&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;lineno&quot;&gt;21 &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;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In line 15, you create an instance of &lt;code&gt;QVBoxLayout&lt;/code&gt;. In the next three lines, you add three buttons to &lt;code&gt;layout&lt;/code&gt;. Finally, you use &lt;code&gt;layout&lt;/code&gt; to arrange the widget in a vertical layout.&lt;/p&gt;
&lt;p&gt;When you run this application, you&amp;rsquo;ll get an output like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/v-layout.366271060ab3.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/v-layout.366271060ab3.png&quot; width=&quot;208&quot; height=&quot;175&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/v-layout.366271060ab3.png&amp;amp;w=52&amp;amp;sig=5751db8f01672d577a7fcaf34cbd4bfcdf76c594 52w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/v-layout.366271060ab3.png&amp;amp;w=104&amp;amp;sig=2b98b9dbd01a59321fd5a550dde3dea744ac36db 104w, https://files.realpython.com/media/v-layout.366271060ab3.png 208w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QVBoxLayout example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This application shows three buttons in a vertical layout, one below the other. The buttons appear in the same order as you added them in your code, from top to bottom.&lt;/p&gt;
&lt;p&gt;The third layout manager class is &lt;strong&gt;&lt;code&gt;QGridLayout&lt;/code&gt;&lt;/strong&gt;, which arranges widgets into a grid of rows and columns. Every widget will have a relative position on the grid. You can define a widget&amp;rsquo;s position by passing it a pair of coordinates in the form of &lt;code&gt;(row, column)&lt;/code&gt;. These coordinates should be valid &lt;code&gt;int&lt;/code&gt; numbers. They define which cell of the grid you&amp;rsquo;re going to place the widget on. The grid layout works as follows:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/grid-layout.3bbf850cab1e.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/grid-layout.3bbf850cab1e.png&quot; width=&quot;381&quot; height=&quot;201&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/grid-layout.3bbf850cab1e.png&amp;amp;w=95&amp;amp;sig=7d8751f379bdb13bcb6adc6214b3046da2c57126 95w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/grid-layout.3bbf850cab1e.png&amp;amp;w=190&amp;amp;sig=c9eeaf8e578d824082785fdabddd2283ab2b3127 190w, https://files.realpython.com/media/grid-layout.3bbf850cab1e.png 381w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QGridLayout schema&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;QGridLayout&lt;/code&gt; takes the space made available to it by its &lt;code&gt;parent&lt;/code&gt;, divides it up into &lt;code&gt;rows&lt;/code&gt; and &lt;code&gt;columns&lt;/code&gt;, and puts each widget into its own cell.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how to use &lt;code&gt;QGridLayout&lt;/code&gt; in your GUI:&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;# Filename: g_layout.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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Grid layout example.&amp;quot;&amp;quot;&amp;quot;&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QGridLayout&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&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;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;lineno&quot;&gt;13 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setWindowTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;QGridLayout&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QGridLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&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 class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Button (0, 0)&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Button (0, 1)&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Button (0, 2)&amp;#39;&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;2&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;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Button (1, 0)&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;mi&quot;&gt;0&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;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Button (1, 1)&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Button (1, 2)&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;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Button (2, 0)&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Button (2, 1) + 2 Columns Span&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;mi&quot;&gt;1&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&gt;&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&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;lineno&quot;&gt;26 &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;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you create an application that uses a &lt;code&gt;QGridLayout&lt;/code&gt; object to organize its widgets. Notice that, in this case, the second and third arguments you pass to &lt;code&gt;.addWidget()&lt;/code&gt; are &lt;code&gt;int&lt;/code&gt; arguments that define the position of each widget.&lt;/p&gt;
&lt;p&gt;In line 23, you add two more arguments to &lt;code&gt;.addWidget()&lt;/code&gt;. These arguments are called &lt;code&gt;rowSpan&lt;/code&gt; and &lt;code&gt;columnSpan&lt;/code&gt;, and they&amp;rsquo;re the fourth and fifth arguments passed to the function. You can use them to make a widget occupy more than one row or column like you did with &lt;code&gt;QPushButton(&#39;Button (2, 1) + 2 Columns Span&#39;)&lt;/code&gt; here.&lt;/p&gt;
&lt;p&gt;If you run this code from your command line, then you&amp;rsquo;ll get a window like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/g-layout.d3784adad447.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/g-layout.d3784adad447.png&quot; width=&quot;331&quot; height=&quot;176&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/g-layout.d3784adad447.png&amp;amp;w=82&amp;amp;sig=223d70c127f518c64c41bc83880e724af7419d86 82w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/g-layout.d3784adad447.png&amp;amp;w=165&amp;amp;sig=4a7e1c2abd3c7b5f1d1be395c7299aa392a6b1a0 165w, https://files.realpython.com/media/g-layout.d3784adad447.png 331w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QGridLayout example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see your widgets arranged in a grid of rows and columns. The last widget occupies more than one cell, as you specified in line 23.&lt;/p&gt;
&lt;p&gt;The last layout manager class is &lt;strong&gt;&lt;code&gt;QFormLayout&lt;/code&gt;&lt;/strong&gt;, which arranges widgets in a two-column layout. The first column usually displays messages in labels. The second column generally contains widgets like &lt;code&gt;QLineEdit&lt;/code&gt;, &lt;code&gt;QComboBox&lt;/code&gt;, &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qspinbox.html&quot;&gt;&lt;code&gt;QSpinBox&lt;/code&gt;&lt;/a&gt;, and so on. These allow the user to enter or edit data regarding the information in the first column. The following diagram shows how form layouts work in practice:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/form-layout.6e168f74cdcd.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/form-layout.6e168f74cdcd.png&quot; width=&quot;261&quot; height=&quot;201&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/form-layout.6e168f74cdcd.png&amp;amp;w=65&amp;amp;sig=ba1d754221337392eb55489a9b5f2fa90ab7ab1e 65w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/form-layout.6e168f74cdcd.png&amp;amp;w=130&amp;amp;sig=3d0ab7f837ba8f285ef25375cd865ef55b021947 130w, https://files.realpython.com/media/form-layout.6e168f74cdcd.png 261w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QFormLayout schema&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The left column consists of labels, and the right column consists of field widgets. If you&amp;rsquo;re dealing with a database application, then this kind of layout can be an attractive option for increased productivity when you&amp;rsquo;re creating your forms.&lt;/p&gt;
&lt;p&gt;The following example shows you how to create an application that uses a &lt;code&gt;QFormLayout&lt;/code&gt; object to arrange its widgets:&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;# Filename: f_layout.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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Form layout example.&amp;quot;&amp;quot;&amp;quot;&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QFormLayout&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&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;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;lineno&quot;&gt;13 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setWindowTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;QFormLayout&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QFormLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&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 class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Name:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&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;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Age:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&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;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Job:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&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;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hobbies:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&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;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&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;lineno&quot;&gt;22 &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;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Lines 15 to 20 do the hard work in this example. Notice that &lt;code&gt;QFormLayout&lt;/code&gt; has a convenient method called &lt;code&gt;.addRow()&lt;/code&gt;. You can use this method to add a two-widget row to the layout. The first argument of &lt;code&gt;.addRow()&lt;/code&gt; should be a label, and the second argument should be any other widget that allows the user to enter or edit data.&lt;/p&gt;
&lt;p&gt;If you run this code, then you&amp;rsquo;ll get the following output:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/f-layout.5bc3a560d54c.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/f-layout.5bc3a560d54c.png&quot; width=&quot;247&quot; height=&quot;200&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/f-layout.5bc3a560d54c.png&amp;amp;w=61&amp;amp;sig=7839cde3726beff3bd5c3ee98041fa06fe7d5c12 61w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/f-layout.5bc3a560d54c.png&amp;amp;w=123&amp;amp;sig=4f1123e921f2180dcb9fcc0caa23cda9b2ca859b 123w, https://files.realpython.com/media/f-layout.5bc3a560d54c.png 247w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt QFormLayout example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The above figure shows a GUI that uses a form layout. The first column contains labels to ask the user for some information. The second column shows widgets that allow the user to enter or edit the information you asked from them.&lt;/p&gt;
&lt;h3 id=&quot;dialogs&quot;&gt;Dialogs&lt;/h3&gt;
&lt;p&gt;With PyQt, you can develop two types of GUI desktop applications. Depending on the class you use to create the main form or window, you&amp;rsquo;ll have one of the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;A Main Window-Style application:&lt;/strong&gt; The application&amp;rsquo;s main window inherits from &lt;code&gt;QMainWindow&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A Dialog-Style application:&lt;/strong&gt; The application&amp;rsquo;s main window inherits from &lt;code&gt;QDialog&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You&amp;rsquo;ll start with Dialog-Style applications first. In the next section, you&amp;rsquo;ll cover Main Window-Style applications.&lt;/p&gt;
&lt;p&gt;To develop a Dialog-Style application, you need to create a GUI class that inherits from &lt;code&gt;QDialog&lt;/code&gt;, which is the base class of all dialog windows. A &lt;strong&gt;dialog window&lt;/strong&gt; is always a top-level window that you can use as the main window for your Dialog-Style application.&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; Dialog windows are also commonly used in Main Window-Style applications for brief communication and interaction with the user.&lt;/p&gt;
&lt;p&gt;When dialog windows are used to communicate with the user, they may be:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Modal dialogs:&lt;/strong&gt; block input to any other visible windows in the same application. You can display a modal dialog by calling &lt;code&gt;.exec_()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Modeless dialogs:&lt;/strong&gt; operate independently of other windows in the same application. You can display a modeless dialog by using &lt;code&gt;.show()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dialog windows can also provide a return value and have default buttons (for example, &lt;code&gt;OK&lt;/code&gt; and &lt;code&gt;Cancel&lt;/code&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;A dialog is always a top-level widget. If it has a &lt;code&gt;parent&lt;/code&gt;, then its default location is centered on top of the parent&amp;rsquo;s top-level widget. This kind of dialog will also share the parent&amp;rsquo;s taskbar entry. If you don&amp;rsquo;t set a &lt;code&gt;parent&lt;/code&gt; for a given dialog, then the dialog will get its own entry in the system&amp;rsquo;s taskbar.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of how you&amp;rsquo;d use &lt;code&gt;QDialog&lt;/code&gt; to develop a Dialog-Style application:&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;# Filename: dialog.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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Dialog-Style application.&amp;quot;&amp;quot;&amp;quot;&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QDialog&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QDialogButtonBox&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QFormLayout&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QVBoxLayout&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Dialog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QDialog&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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Dialog.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &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;parent&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;lineno&quot;&gt;17 &lt;/span&gt;        &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Initializer.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &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;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;parent&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setWindowTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;QDialog&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;dlgLayout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QVBoxLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;formLayout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QFormLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;formLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Name:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&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;formLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Age:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;formLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Job:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&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;n&quot;&gt;formLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addRow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hobbies:&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;dlgLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;formLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;btns&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QDialogButtonBox&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;btns&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setStandardButtons&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;29 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;            &lt;span class=&quot;n&quot;&gt;QDialogButtonBox&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Cancel&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QDialogButtonBox&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Ok&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;dlgLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;btns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31 &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;setLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dlgLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33 &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;vm&quot;&gt;__name__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;34 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;lineno&quot;&gt;35 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;dlg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dialog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;36 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;dlg&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;lineno&quot;&gt;37 &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;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This application is a bit more elaborate. Here&amp;rsquo;s what&amp;rsquo;s going on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 14&lt;/strong&gt; creates a full class &lt;code&gt;Dialog&lt;/code&gt; for the GUI, which inherits from &lt;code&gt;QDialog&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 20&lt;/strong&gt; assigns a &lt;code&gt;QVBoxLayout&lt;/code&gt; object to &lt;code&gt;dlgLaout&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 21&lt;/strong&gt; assigns a &lt;code&gt;QVFormLayout&lt;/code&gt; object to &lt;code&gt;formLayout&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 22 to 25&lt;/strong&gt; add widgets to &lt;code&gt;formLayout&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 26&lt;/strong&gt; uses &lt;code&gt;dlgLayout&lt;/code&gt; to arrange all the widgets on the form.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 27&lt;/strong&gt; provides a convenient object to place the dialog buttons.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 28 and 29&lt;/strong&gt; add two standard buttons: &lt;code&gt;Ok&lt;/code&gt; and &lt;code&gt;Cancel&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 33 to 37&lt;/strong&gt; wrap the boilerplate code in an &lt;a href=&quot;https://realpython.com/python-main-function/#use-if-__name__-main-to-control-the-execution-of-your-code&quot;&gt;&lt;code&gt;if __name__ == &#39;__main__&#39;:&lt;/code&gt; idiom&lt;/a&gt;. This is considered a best practice for Pythonistas.&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; If you look at line 26 in the code block above, then you&amp;rsquo;ll notice that layout managers can be nested inside one another. You can nest layouts by calling &lt;code&gt;.addLayout()&lt;/code&gt; on the container layout and passing in the nested layout as an argument to this method.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The code block above displays the following window:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/dialog-style-app.d453259dee67.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/dialog-style-app.d453259dee67.png&quot; width=&quot;253&quot; height=&quot;229&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/dialog-style-app.d453259dee67.png&amp;amp;w=63&amp;amp;sig=5c91a84cc85b4c89da5319fac0161cadbf278861 63w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/dialog-style-app.d453259dee67.png&amp;amp;w=126&amp;amp;sig=815468f89c9b2391e5aa18c7037a537389eab714 126w, https://files.realpython.com/media/dialog-style-app.d453259dee67.png 253w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt Dialog-Style application example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is the GUI that you created using &lt;code&gt;QFormLayout&lt;/code&gt; for the widgets and &lt;code&gt;QVBoxLayout&lt;/code&gt; for the general application&amp;rsquo;s layout (&lt;code&gt;dlgLayout&lt;/code&gt; in line 20).&lt;/p&gt;
&lt;h3 id=&quot;main-windows&quot;&gt;Main Windows&lt;/h3&gt;
&lt;p&gt;Most of the time, your GUI applications will be &lt;strong&gt;Main Window-Style&lt;/strong&gt;. This means that they&amp;rsquo;ll have a menu bar, some toolbars, a status bar, and a central widget that will be the GUI&amp;rsquo;s main element. It&amp;rsquo;s also common that your apps will have several dialog windows to accomplish secondary actions that depend on user input.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll use the class &lt;code&gt;QMainWindow&lt;/code&gt; to develop Main Window-Style applications. You need to inherit from &lt;code&gt;QMainWindow&lt;/code&gt; to create your main GUI class. An instance of a class that derives from &lt;code&gt;QMainWindow&lt;/code&gt; is considered to be a &lt;strong&gt;main window&lt;/strong&gt;. &lt;code&gt;QMainWindow&lt;/code&gt; provides a framework for building your application&amp;rsquo;s GUI. The class has its own built-in layout, which you can use to place the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;One menu bar&lt;/strong&gt; is at the top of the window. The &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qmenubar.html&quot;&gt;menu bar&lt;/a&gt; holds the application&amp;rsquo;s main menu.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Several toolbars&lt;/strong&gt; are on the sides of the window. &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qtoolbar.html&quot;&gt;Toolbars&lt;/a&gt; are suitable for holding &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qtoolbutton.html&quot;&gt;tool buttons&lt;/a&gt; and other kinds of widgets such as &lt;code&gt;QComboBox&lt;/code&gt;, &lt;code&gt;QSpinBox&lt;/code&gt;, and more.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;One central widget&lt;/strong&gt; is in the center of the window. The central widget can be of any type, or it can be a composite widget.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Several dock widgets&lt;/strong&gt; are around the central widget. &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qdockwidget.html&quot;&gt;Dock widgets&lt;/a&gt; are small, movable windows.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;One status bar&lt;/strong&gt; is at the bottom of the window. The &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/qtwidgets/qstatusbar.html&quot;&gt;status bar&lt;/a&gt; shows information on the application&amp;rsquo;s general status.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can&amp;rsquo;t create a main window without first setting a central widget. You &lt;em&gt;must&lt;/em&gt; have a central widget, even if it&amp;rsquo;s just a placeholder. When this is the case, you can use a &lt;code&gt;QWidget&lt;/code&gt; object as your central widget.  You can set the main window&amp;rsquo;s central widget with &lt;code&gt;.setCentralWidget()&lt;/code&gt;. The main window&amp;rsquo;s layout will allow you to have only one central widget, but it can be a single or a composite widget.&lt;/p&gt;
&lt;p&gt;The following code example shows you how to use &lt;code&gt;QMainWindow&lt;/code&gt; to create a Main Window-Style application:&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;# Filename: main_window.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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Main Window-Style application.&amp;quot;&amp;quot;&amp;quot;&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLabel&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QMainWindow&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QStatusBar&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QToolBar&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QMainWindow&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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Main Window.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &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;parent&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;lineno&quot;&gt;16 &lt;/span&gt;        &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Initializer.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &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;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;parent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;        &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setWindowTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;QMainWindow&amp;#39;&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setCentralWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QLabel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;I&amp;#39;m the Central Widget&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;&lt;span class=&quot;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;_createMenu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;21 &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;_createToolBar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;22 &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;_createStatusBar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;23 &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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_createMenu&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;25 &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;menu&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;menuBar&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;addMenu&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;amp;Menu&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &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;menu&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;&amp;amp;Exit&amp;#39;&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;close&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;lineno&quot;&gt;28 &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;_createToolBar&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;29 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QToolBar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30 &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;addToolBar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;tools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addAction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Exit&amp;#39;&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;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33 &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;_createStatusBar&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;34 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QStatusBar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;35 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;showMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;I&amp;#39;m the Status Bar&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;36 &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;setStatusBar&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;lineno&quot;&gt;37 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;38 &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;s1&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;39 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;lineno&quot;&gt;40 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;win&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Window&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;41 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;win&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;lineno&quot;&gt;42 &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;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&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 how this code works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 13&lt;/strong&gt; creates a class &lt;code&gt;Window&lt;/code&gt; that inherits from &lt;code&gt;QMainWindow&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 18&lt;/strong&gt; sets the window&amp;rsquo;s title.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 19&lt;/strong&gt; sets a &lt;code&gt;QLabel&lt;/code&gt; as the central widget.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 20 to 22&lt;/strong&gt; call private methods in the lines that follow in order to create different GUI elements:&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lines 24 to 26&lt;/strong&gt; create the main menu.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 28 to 31&lt;/strong&gt; create the toolbar.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 33 to 36&lt;/strong&gt; create the status bar.&lt;/li&gt;
&lt;/ul&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; When you implement different GUI components in their own method, you&amp;rsquo;re making your code more readable and more maintainable. This is not a requirement, however, so you&amp;rsquo;re free to organize your code in the way you like best.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;When you run the above code, you&amp;rsquo;ll see a window like the following:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/main-window-app.53142a356307.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/main-window-app.53142a356307.png&quot; width=&quot;258&quot; height=&quot;191&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/main-window-app.53142a356307.png&amp;amp;w=64&amp;amp;sig=f5a8d8005257dc123aa6b5e50f0485870538c546 64w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/main-window-app.53142a356307.png&amp;amp;w=129&amp;amp;sig=ccb49fb28646212d7249cda9b0437a6a7d0147fb 129w, https://files.realpython.com/media/main-window-app.53142a356307.png 258w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt Main Window-Style application example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see that your Main Window-Style application has the following components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One main menu called &lt;code&gt;Menu&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;One toolbar with a functional &lt;code&gt;Exit&lt;/code&gt; tool button&lt;/li&gt;
&lt;li&gt;One central widget (a &lt;code&gt;QLabel&lt;/code&gt; object)&lt;/li&gt;
&lt;li&gt;One status bar at the bottom of the window&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So far, you&amp;rsquo;ve covered some of the more important graphical components of PyQt5&amp;rsquo;s set of widgets. In the next two sections, you&amp;rsquo;ll cover some other important concepts related to PyQt GUI applications.&lt;/p&gt;
&lt;h3 id=&quot;applications&quot;&gt;Applications&lt;/h3&gt;
&lt;p&gt;The most basic class you&amp;rsquo;ll use when developing PyQt GUI applications is &lt;code&gt;QApplication&lt;/code&gt;. This class is at the core of any PyQt application. It manages the application&amp;rsquo;s control flow as well as its main settings. In PyQt, any instance of &lt;code&gt;QApplication&lt;/code&gt; is considered to be an &lt;strong&gt;application&lt;/strong&gt;. Every PyQt GUI application must have one &lt;code&gt;QApplication&lt;/code&gt; object. Some of the application&amp;rsquo;s responsibilities include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Handling initialization and finalization&lt;/li&gt;
&lt;li&gt;Providing the event loop and event handling&lt;/li&gt;
&lt;li&gt;Handling most of the system-wide and application-wide settings&lt;/li&gt;
&lt;li&gt;Providing access to global information, such as the application&amp;rsquo;s directory, screen size, and so on&lt;/li&gt;
&lt;li&gt;Parsing common command-line arguments&lt;/li&gt;
&lt;li&gt;Defining the application&amp;rsquo;s look and feel&lt;/li&gt;
&lt;li&gt;Providing localization capabilities&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are just some of the core responsibilities of &lt;code&gt;QApplication&lt;/code&gt;. As you can see, this is a fundamental class when it comes to developing PyQt GUI applications!&lt;/p&gt;
&lt;p&gt;One of the most important responsibilities of &lt;code&gt;QApplication&lt;/code&gt; is to provide the event loop and the entire event handling mechanism. Let&amp;rsquo;s take a closer look at the event loop now.&lt;/p&gt;
&lt;h3 id=&quot;event-loops&quot;&gt;Event Loops&lt;/h3&gt;
&lt;p&gt;GUI applications are &lt;strong&gt;event-driven&lt;/strong&gt;. This means that functions and methods are executed in response to user actions like clicking on a button, selecting an item from a combo box, entering or updating the text in a text edit, pressing a key on the keyboard, and so on. These user actions are generally called &lt;strong&gt;events&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Events are commonly handled by an &lt;strong&gt;event loop&lt;/strong&gt; (also called the &lt;strong&gt;main loop&lt;/strong&gt;). An event loop is an infinite loop in which all events from the user, the window system, and any other sources are processed and dispatched. The event loop waits for an event to occur and then dispatches it to perform some task. The event loop continues to work until the application is terminated.&lt;/p&gt;
&lt;p&gt;Event loops are used by all GUI applications. The event loop is kind of an infinite loop that waits for the occurrence of events. If an event happens, then the loop checks if the event is a &lt;code&gt;Terminate&lt;/code&gt; event. In that case, the loop is terminated and the application exits. Otherwise, the event is sent to the application&amp;rsquo;s event queue for further processing, and the loop starts again.&lt;/p&gt;
&lt;p&gt;In PyQt, you can run the application&amp;rsquo;s event loop by calling &lt;code&gt;.exec_()&lt;/code&gt; on the &lt;code&gt;QApplication&lt;/code&gt; object.&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; PyQt was first developed to target Python 2, which already has an &lt;code&gt;exec&lt;/code&gt; keyword. In earlier versions, an underscore was added to the end &lt;code&gt;.exec_()&lt;/code&gt; to help avoid name conflicts.&lt;/p&gt;
&lt;p&gt;PyQt5 targets Python 3, which doesn&amp;rsquo;t have an &lt;code&gt;exec&lt;/code&gt; keyword. Still, the library provides two methods that start the event loop:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;.exec_()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.exec()&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This means that you can remove &lt;code&gt;.exec_()&lt;/code&gt; from your code, and you can safely use &lt;code&gt;.exec()&lt;/code&gt; instead.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;For an event to trigger a response action, you need to connect the event with the action you want to be executed. In PyQt5, you can establish that connection by using the signals and slots mechanism. You&amp;rsquo;ll cover these in the next section.&lt;/p&gt;
&lt;h3 id=&quot;signals-and-slots&quot;&gt;Signals and Slots&lt;/h3&gt;
&lt;p&gt;PyQt widgets act as &lt;strong&gt;event-catchers&lt;/strong&gt;. This means that every widget can catch a specific number of events, like mouse clicks, keypresses, and so on. In response to these events, widgets always emit a &lt;strong&gt;signal&lt;/strong&gt;, which is a kind of message that announces a change in its state.&lt;/p&gt;
&lt;p&gt;The signal on its own doesn&amp;rsquo;t perform any action. If you want a signal to trigger an action, then you need to connect it to a &lt;strong&gt;slot&lt;/strong&gt;. This is the function or method that will perform an action whenever the connecting signal is emitted. You can use any Python callable (or &lt;strong&gt;callback&lt;/strong&gt;) as a slot.&lt;/p&gt;
&lt;p&gt;If a signal is connected to a slot, then the slot is called whenever the signal is emitted. If a signal isn&amp;rsquo;t connected to any slot, then nothing happens and the signal is ignored. Here are some of the most useful features of this mechanism:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A signal can be connected to one or many slots.&lt;/li&gt;
&lt;li&gt;A signal may also be connected to another signal.&lt;/li&gt;
&lt;li&gt;A slot may be connected to one or many signals.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can use the following syntax to connect a signal to a slot:&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;widget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;signal&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slot_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will connect &lt;code&gt;slot_function&lt;/code&gt; to &lt;code&gt;widget.signal&lt;/code&gt;. Whenever &lt;code&gt;signal&lt;/code&gt; is emitted, &lt;code&gt;slot_function()&lt;/code&gt; will be called.&lt;/p&gt;
&lt;p&gt;This code shows you how to use the signals and slots mechanism:&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;# Filename: signals_slots.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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Signals and slots example.&amp;quot;&amp;quot;&amp;quot;&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;sys&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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLabel&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QVBoxLayout&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;greeting&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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Slot function.&amp;quot;&amp;quot;&amp;quot;&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;n&quot;&gt;msg&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;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &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;setText&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;lineno&quot;&gt;17 &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;lineno&quot;&gt;18 &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;setText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello World!&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;lineno&quot;&gt;21 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setWindowTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Signals and slots&amp;#39;&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;layout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QVBoxLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;btn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Greet&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;btn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicked&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Connect clicked to greeting()&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;btn&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;n&quot;&gt;msg&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLabel&lt;/span&gt;&lt;span class=&quot;p&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;lineno&quot;&gt;30 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&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;lineno&quot;&gt;31 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;layout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;window&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;lineno&quot;&gt;33 &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;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In line 13, you create &lt;code&gt;greeting()&lt;/code&gt;, which you&amp;rsquo;ll use as a slot. Then in line 26, you connect the button&amp;rsquo;s &lt;code&gt;clicked&lt;/code&gt; signal to &lt;code&gt;greeting()&lt;/code&gt;. This way, whenever the user clicks on the button, &lt;code&gt;greeting()&lt;/code&gt; is called and &lt;code&gt;msg&lt;/code&gt; will alternate between the message &lt;code&gt;Hello World!&lt;/code&gt; and an empty string:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/signals-slots.5c631f0ce2cc.gif&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/signals-slots.5c631f0ce2cc.gif&quot; width=&quot;257&quot; height=&quot;132&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/signals-slots.5c631f0ce2cc.gif&amp;amp;w=64&amp;amp;sig=43edb0cf2899930b4eae394be89aa4cb685c336b 64w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/signals-slots.5c631f0ce2cc.gif&amp;amp;w=128&amp;amp;sig=9c728c1af4da469ab24ef857b6790640417728f7 128w, https://files.realpython.com/media/signals-slots.5c631f0ce2cc.gif 257w&quot; sizes=&quot;75vw&quot; alt=&quot;PyQt signals and slots example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you click on &lt;code&gt;Greet&lt;/code&gt;, the &lt;code&gt;Hello World!&lt;/code&gt; message will appear and disappear on your screen.&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; Every widget has its own set of predefined signals. You can check them out on the widget&amp;rsquo;s documentation page.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;If your slot function needs to receive extra arguments, then you can pass them in by using &lt;code&gt;functools.partial&lt;/code&gt;. For example, you can modify &lt;code&gt;greeting()&lt;/code&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;who&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;Slot function.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&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;text&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;n&quot;&gt;setText&lt;/span&gt;&lt;span class=&quot;p&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;k&quot;&gt;else&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;n&quot;&gt;setText&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;Hello &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{who}&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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, &lt;code&gt;greeting()&lt;/code&gt; needs to receive an argument called &lt;code&gt;who&lt;/code&gt;. If you want to connect this new version of &lt;code&gt;greeting()&lt;/code&gt; to the &lt;code&gt;btn.clicked&lt;/code&gt; signal, then you can do something 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;btn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicked&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;functools&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;World!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For this code to work, you need to import &lt;code&gt;functools&lt;/code&gt; first. The call to &lt;code&gt;functools.partial()&lt;/code&gt; returns an object that behaves similarly to calling &lt;code&gt;greeting()&lt;/code&gt; with &lt;code&gt;who=&#39;World!&#39;&lt;/code&gt;. Now, when the user clicks on the button, the message &lt;code&gt;&#39;Hello World!&#39;&lt;/code&gt; will be shown in the label as well as before.&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 also use &lt;code&gt;lambda&lt;/code&gt; to connect a signal to a slot that requires extra arguments. For a practice exercise, try to code the above example using &lt;code&gt;lambda&lt;/code&gt; instead of &lt;code&gt;functools.partial()&lt;/code&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;The signals and slots mechanism is what you&amp;rsquo;ll use to give life to your PyQt5 GUI applications. This mechanism will allow you to turn user events into concrete actions. You can dive deeper into the signals and slots mechanism by taking a look at the &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/signals_slots.html&quot;&gt;PyQt5 documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now you&amp;rsquo;ve finished covering the most important concepts of PyQt5. With this knowledge and the library&amp;rsquo;s documentation at hand, you&amp;rsquo;re ready to start developing your own GUI applications. In the next section, you&amp;rsquo;ll build your first fully-functional GUI application.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s go for it!&lt;/p&gt;
&lt;h2 id=&quot;creating-a-calculator-with-python-and-pyqt&quot;&gt;Creating a Calculator With Python and PyQt&lt;/h2&gt;
&lt;p&gt;In this section, you&amp;rsquo;re going to develop a calculator using the &lt;a href=&quot;https://realpython.com/the-model-view-controller-mvc-paradigm-summarized-with-legos&quot;&gt;Model-View-Controller (MVC)&lt;/a&gt; design pattern. This pattern has three layers of code, each with different roles:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The model&lt;/strong&gt; takes care of your app&amp;rsquo;s &lt;a href=&quot;https://en.wikipedia.org/wiki/Business_logic&quot;&gt;business logic&lt;/a&gt;. It contains the core functionality and data. For your calculator, the model will handle the calculations.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The view&lt;/strong&gt; implements your app&amp;rsquo;s GUI. It hosts all the widgets the end-user would need to interact with the application. The view also receives user actions and events. For your calculator, the view will be the window you&amp;rsquo;ll see on your screen.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;The controller&lt;/strong&gt; connects the model and the view to make the application work. User events (or requests) are sent to the controller, which puts the model to work. When the model delivers the requested result (or data) in the right format, the controller forwards it to the view. For your calculator, the controller will receive user events from the GUI, ask the model to perform calculations, and update the GUI with the result.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;rsquo;s a step-by-step MVC pattern for a GUI desktop application:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The user performs an action or request (event) on the view (GUI).&lt;/li&gt;
&lt;li&gt;The view notifies the controller about the user&amp;rsquo;s action.&lt;/li&gt;
&lt;li&gt;The controller gets the user&amp;rsquo;s request and queries the model for a response.&lt;/li&gt;
&lt;li&gt;The model processes the controller query, performs the required operations, and returns an answer or result.&lt;/li&gt;
&lt;li&gt;The controller receives the model&amp;rsquo;s answer and updates the view accordingly.&lt;/li&gt;
&lt;li&gt;The user finally sees the requested result on the view.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You&amp;rsquo;ll use this MVC design pattern to build your calculator.&lt;/p&gt;
&lt;h3 id=&quot;creating-the-skeleton&quot;&gt;Creating the Skeleton&lt;/h3&gt;
&lt;p&gt;You&amp;rsquo;ll start by implementing a basic skeleton for your application, called &lt;code&gt;pycalc.py&lt;/code&gt;. You can find this script and the rest of the source code at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/pyqt-calculator/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-pyqt-calculator&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to build a calculator in Python with PyQt in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;If you&amp;rsquo;d prefer to code the project on your own, then go ahead and create &lt;code&gt;pycalc.py&lt;/code&gt; in your current working directory. Then, open the file in your code editor and type the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;ch&quot;&gt;#!/usr/bin/env python3&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Filename: pycalc.py&lt;/span&gt;

&lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;PyCalc is a simple calculator built using Python and PyQt5.&amp;quot;&amp;quot;&amp;quot;&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;# Import QApplication and the required widgets from PyQt5.QtWidgets&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QMainWindow&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&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;0.1&amp;#39;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;__author__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;Leodanis Pozo Ramos&amp;#39;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create a subclass of QMainWindow to setup the calculator&amp;#39;s GUI&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PyCalcUi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QMainWindow&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;PyCalc&amp;#39;s View (GUI).&amp;quot;&amp;quot;&amp;quot;&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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;View initializer.&amp;quot;&amp;quot;&amp;quot;&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;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;c1&quot;&gt;# Set some main window&amp;#39;s properties&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;setWindowTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;PyCalc&amp;#39;&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;setFixedSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;235&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;235&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Set the central widget&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;_centralWidget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&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;setCentralWidget&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;_centralWidget&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Client code&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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Main function.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Create an instance of QApplication&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pycalc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;c1&quot;&gt;# Show the calculator&amp;#39;s GUI&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCalcUi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&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;# Execute the calculator&amp;#39;s main loop&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;pycalc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&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;s1&quot;&gt;&amp;#39;__main__&amp;#39;&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;This script implements all the code you&amp;rsquo;ll need to run a basic GUI application. You&amp;rsquo;ll use this skeleton to build your calculator. Here&amp;rsquo;s how it works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lines 10 to 12&lt;/strong&gt; import the required modules and classes from &lt;code&gt;PyQt5.QtWidgets&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 18&lt;/strong&gt; creates the GUI with the class &lt;code&gt;PyCalcUi&lt;/code&gt;. Note that this class inherits from &lt;code&gt;QMainWindow&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 24&lt;/strong&gt; sets the window&amp;rsquo;s title to &lt;code&gt;PyCalc&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 25&lt;/strong&gt; uses &lt;code&gt;.setFixedSize()&lt;/code&gt; to give the window a fixed size. This ensures that the user won&amp;rsquo;t be able to resize the window.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 27&lt;/strong&gt; creates a &lt;code&gt;QWidget&lt;/code&gt; object to play the role of a central widget. Remember that since your GUI class inherits from &lt;code&gt;QMainWindow&lt;/code&gt;, you need a central widget. This object will be the &lt;code&gt;parent&lt;/code&gt; for the rest of the GUI component.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Line 31&lt;/strong&gt; defines your calculator&amp;rsquo;s &lt;a href=&quot;https://realpython.com/python-main-function/&quot;&gt;main function&lt;/a&gt;, which is considered a best practice. This function will be the entry point to the application. Inside &lt;code&gt;main()&lt;/code&gt;, your program does the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 34&lt;/strong&gt; creates a &lt;code&gt;QApplication&lt;/code&gt; object &lt;code&gt;pycalc&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 37&lt;/strong&gt; shows the GUI with &lt;code&gt;view.show()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 39&lt;/strong&gt; runs the application&amp;rsquo;s event loop with &lt;code&gt;pycalc.exec_()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you run the script, the following window will appear on your screen:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/calculator-skeleton.37acefd3eee2.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/calculator-skeleton.37acefd3eee2.png&quot; width=&quot;263&quot; height=&quot;288&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/calculator-skeleton.37acefd3eee2.png&amp;amp;w=65&amp;amp;sig=aa64486cd636040f39ac41675a857b45838c92f4 65w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/calculator-skeleton.37acefd3eee2.png&amp;amp;w=131&amp;amp;sig=edb403f89328f888fedcc43093968b65cd9344d6 131w, https://files.realpython.com/media/calculator-skeleton.37acefd3eee2.png 263w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCalc&amp;#39;s skeleton&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This is your GUI application skeleton.&lt;/p&gt;
&lt;h3 id=&quot;completing-the-view&quot;&gt;Completing the View&lt;/h3&gt;
&lt;p&gt;The GUI you have at this point doesn&amp;rsquo;t really look like a calculator. Let&amp;rsquo;s finish the GUI by adding the display and buttons for the numbers. You&amp;rsquo;ll also add buttons for basic math operations and for clearing the display.&lt;/p&gt;
&lt;p&gt;First, you&amp;rsquo;ll need to add the following imports to the top of your 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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtCore&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Qt&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QGridLayout&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QPushButton&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;PyQt5.QtWidgets&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QVBoxLayout&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You&amp;rsquo;re going to use a &lt;code&gt;QVBoxLayout&lt;/code&gt; for the calculator&amp;rsquo;s general layout. You&amp;rsquo;ll also use a &lt;code&gt;QGridLayout&lt;/code&gt; object to arrange the buttons. Finally, you import &lt;code&gt;QLineEdit&lt;/code&gt; for the display and &lt;code&gt;QPushButton&lt;/code&gt; for the buttons. There should now be eight import statements at the top of your file.&lt;/p&gt;
&lt;p&gt;Now you can update the initializer for &lt;code&gt;PyCalcUi&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;# Create a subclass of QMainWindow to setup the calculator&amp;#39;s GUI&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PyCalcUi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QMainWindow&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;PyCalc&amp;#39;s View (GUI).&amp;quot;&amp;quot;&amp;quot;&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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;View initializer.&amp;quot;&amp;quot;&amp;quot;&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;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;c1&quot;&gt;# Set some main window&amp;#39;s properties&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;setWindowTitle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;PyCalc&amp;#39;&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;setFixedSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;235&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;235&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Set the central widget and the general layout&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;generalLayout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QVBoxLayout&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;_centralWidget&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QWidget&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;setCentralWidget&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;_centralWidget&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;_centralWidget&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setLayout&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;generalLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Create the display and the buttons&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;_createDisplay&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;_createButtons&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;Here, you&amp;rsquo;ve added the highlighted lines of code. You&amp;rsquo;ll use a &lt;code&gt;QVBoxLayout&lt;/code&gt; to place the display at the top and the buttons in a grid layout at the bottom.&lt;/p&gt;
&lt;p&gt;The calls to &lt;code&gt;._createDisplay()&lt;/code&gt; and &lt;code&gt;._createButtons()&lt;/code&gt; won&amp;rsquo;t work, because you haven&amp;rsquo;t yet implemented those methods. Let&amp;rsquo;s fix that by coding &lt;code&gt;._createDisplay()&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;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PyCalcUi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QMainWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Snip&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_createDisplay&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;Create the display.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Create the display widget&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;display&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QLineEdit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;c1&quot;&gt;# Set some display&amp;#39;s properties&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;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setFixedHeight&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;35&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;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setAlignment&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Qt&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AlignRight&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;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setReadOnly&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&gt;        &lt;span class=&quot;c1&quot;&gt;# Add the display to the general layout&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;generalLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&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;display&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;To create the display widget, you use a &lt;code&gt;QLineEdit&lt;/code&gt; object. Then you set the following display properties:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The display has a fixed height of 35 pixels.&lt;/li&gt;
&lt;li&gt;The display shows the text as left-aligned.&lt;/li&gt;
&lt;li&gt;The display is set to read-only to avoid direct editing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The last line adds the display to the calculator&amp;rsquo;s general layout with &lt;code&gt;generalLayout.addWidget()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Next, you&amp;rsquo;ll implement &lt;code&gt;._createButtons()&lt;/code&gt; to create buttons for your calculator. You&amp;rsquo;ll use a dictionary to hold each button&amp;rsquo;s text and position on the grid. You&amp;rsquo;ll also use &lt;code&gt;QGridLayout&lt;/code&gt; to arrange the buttons on the calculator&amp;rsquo;s window. The final code will 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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PyCalcUi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QMainWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Snip&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_createButtons&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;Create the buttons.&amp;quot;&amp;quot;&amp;quot;&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;buttons&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;buttonsLayout&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QGridLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Button text | position on the QGridLayout&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;buttons&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;7&amp;#39;&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                   &lt;span class=&quot;s1&quot;&gt;&amp;#39;8&amp;#39;&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                   &lt;span class=&quot;s1&quot;&gt;&amp;#39;9&amp;#39;&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;mi&quot;&gt;0&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;/&amp;#39;&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;mi&quot;&gt;0&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;C&amp;#39;&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;mi&quot;&gt;0&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;s1&quot;&gt;&amp;#39;4&amp;#39;&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                   &lt;span class=&quot;s1&quot;&gt;&amp;#39;5&amp;#39;&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;mi&quot;&gt;1&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;6&amp;#39;&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;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;s1&quot;&gt;&amp;#39;*&amp;#39;&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                   &lt;span class=&quot;s1&quot;&gt;&amp;#39;(&amp;#39;&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;mi&quot;&gt;1&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;s1&quot;&gt;&amp;#39;1&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;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;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                   &lt;span class=&quot;s1&quot;&gt;&amp;#39;2&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                   &lt;span class=&quot;s1&quot;&gt;&amp;#39;3&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;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;2&lt;/span&gt;&lt;span class=&quot;p&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;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;s1&quot;&gt;&amp;#39;)&amp;#39;&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;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;s1&quot;&gt;&amp;#39;0&amp;#39;&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;mi&quot;&gt;3&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;s1&quot;&gt;&amp;#39;00&amp;#39;&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;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
                   &lt;span class=&quot;s1&quot;&gt;&amp;#39;.&amp;#39;&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;mi&quot;&gt;3&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;+&amp;#39;&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;mi&quot;&gt;3&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;=&amp;#39;&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;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;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Create the buttons and add them to the grid layout&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;btnText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buttons&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttons&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;btnText&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;QPushButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;btnText&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;buttons&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;btnText&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;setFixedSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;buttonsLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addWidget&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;buttons&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;btnText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&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;c1&quot;&gt;# Add buttonsLayout to the general layout&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;generalLayout&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;addLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttonsLayout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You first create an empty dictionary &lt;code&gt;self.buttons&lt;/code&gt; to hold the calculator buttons. Then, you create a temporary dictionary to store their labels and relative positions on the grid layout (&lt;code&gt;buttonsLayout&lt;/code&gt;). Inside the &lt;code&gt;for&lt;/code&gt; loop, you create the buttons and add them to both &lt;code&gt;self.buttons&lt;/code&gt; and &lt;code&gt;buttonsLayout&lt;/code&gt;. Every button will have a fixed size of &lt;code&gt;40x40&lt;/code&gt; pixels, which you set with &lt;code&gt;.setFixedSize(40, 40)&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; When it comes to widget size, you&amp;rsquo;ll rarely find measurement units in the PyQt documentation. It&amp;rsquo;s assumed that the measurement unit is &lt;strong&gt;pixels&lt;/strong&gt; (except for &lt;code&gt;QPrinter&lt;/code&gt;, which uses &lt;strong&gt;points&lt;/strong&gt;).&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now, the calculator&amp;rsquo;s GUI (or view) can show the display and the buttons. But there&amp;rsquo;s still no way to update the information shown in the display. You can fix this by adding a few extra methods:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;.setDisplayText()&lt;/code&gt;&lt;/strong&gt; to set and update the display&amp;rsquo;s text&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;.displayText()&lt;/code&gt;&lt;/strong&gt; to get the current display&amp;rsquo;s text&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;.clearDisplay()&lt;/code&gt;&lt;/strong&gt; to clear the display&amp;rsquo;s text&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;These methods will form the GUI public interface and complete the view class for your Python calculator. Here&amp;rsquo;s a possible implementation:&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;PyCalcUi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QMainWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Snip&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;setDisplayText&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;text&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;Set display&amp;#39;s text.&amp;quot;&amp;quot;&amp;quot;&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;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setText&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;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;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setFocus&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;displayText&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;Get display&amp;#39;s text.&amp;quot;&amp;quot;&amp;quot;&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;display&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;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;clearDisplay&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;Clear the display.&amp;quot;&amp;quot;&amp;quot;&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;setDisplayText&lt;/span&gt;&lt;span class=&quot;p&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;Here&amp;rsquo;s what each function does:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;.setDisplayText()&lt;/code&gt;&lt;/strong&gt; uses &lt;code&gt;.setText()&lt;/code&gt; to set and update the display&amp;rsquo;s text, and &lt;code&gt;.setFocus()&lt;/code&gt; to set the cursor&amp;rsquo;s focus on the display.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;.displayText()&lt;/code&gt;&lt;/strong&gt; is a getter method that returns the display&amp;rsquo;s current text. When the user clicks on the equals sign (&lt;code&gt;=&lt;/code&gt;), the program will use the return value of &lt;code&gt;.displayText()&lt;/code&gt; as the math expression to be evaluated. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;.clearDisplay()&lt;/code&gt;&lt;/strong&gt; sets the display&amp;rsquo;s text to an empty string (&lt;code&gt;&#39;&#39;&lt;/code&gt;) so the user can introduce a new math expression.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now your calculator&amp;rsquo;s GUI is ready! When you run the application, you&amp;rsquo;ll see a window like this one:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/calculator-gui.f7d08c6a29b8.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/calculator-gui.f7d08c6a29b8.png&quot; width=&quot;270&quot; height=&quot;287&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/calculator-gui.f7d08c6a29b8.png&amp;amp;w=67&amp;amp;sig=a54cb239663436bcad7de00e7834f1975a33bda9 67w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/calculator-gui.f7d08c6a29b8.png&amp;amp;w=135&amp;amp;sig=ae41c3b69ec800dd2a12e88f4dc4c44464e209d8 135w, https://files.realpython.com/media/calculator-gui.f7d08c6a29b8.png 270w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCalc&amp;#39;s Graphical User Interface&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ve completed the calculator&amp;rsquo;s GUI interface. However, if you try to do some calculations, then you&amp;rsquo;ll notice that the calculator doesn&amp;rsquo;t do anything just yet. That&amp;rsquo;s because you haven&amp;rsquo;t implemented the model or the controller. Next, you&amp;rsquo;ll add a basic controller class to start giving life to your calculator.&lt;/p&gt;
&lt;h3 id=&quot;creating-a-basic-controller&quot;&gt;Creating a Basic Controller&lt;/h3&gt;
&lt;p&gt;In this section, you&amp;rsquo;re going to code the calculator&amp;rsquo;s controller class. This class will connect the view to the model. You&amp;rsquo;ll use the controller class to make the calculator perform actions in response to user events. You&amp;rsquo;ll start with the following import:&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;functools&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;partial&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At the top of &lt;code&gt;pycalc.py&lt;/code&gt;, you import &lt;code&gt;partial()&lt;/code&gt; to connect signals with methods that need to take extra arguments.&lt;/p&gt;
&lt;p&gt;Your controller class needs to perform three main tasks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Access the GUI&amp;rsquo;s public interface&lt;/li&gt;
&lt;li&gt;Handle the creation of math expressions&lt;/li&gt;
&lt;li&gt;Connect button &lt;code&gt;clicked&lt;/code&gt; signals with the appropriate slots&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This will ensure that your calculator is working correctly. Here&amp;rsquo;s how you code the controller 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;c1&quot;&gt;# Create a Controller class to connect the GUI and the model&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PyCalcCtrl&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;PyCalc Controller class.&amp;quot;&amp;quot;&amp;quot;&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;view&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;Controller initializer.&amp;quot;&amp;quot;&amp;quot;&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;_view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Connect signals and slots&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;_connectSignals&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;_buildExpression&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;sub_exp&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;Build expression.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;expression&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayText&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;sub_exp&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setDisplayText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expression&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;_connectSignals&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;Connect signals and slots.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;btnText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;btn&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttons&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;btnText&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;p&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;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;btn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicked&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;partial&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;_buildExpression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;btnText&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttons&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicked&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clearDisplay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first thing you do is give &lt;code&gt;PyCalcCtrl&lt;/code&gt; an instance of the view &lt;code&gt;PyCalcUi&lt;/code&gt;. You&amp;rsquo;ll use this instance to gain full access to the view&amp;rsquo;s public interface. Next, you create &lt;code&gt;._buildExpression()&lt;/code&gt; to handle the creation of math expressions. This method also updates the calculator&amp;rsquo;s display in response to user input.&lt;/p&gt;
&lt;p&gt;Finally, you use &lt;code&gt;._connectSignals()&lt;/code&gt; to connect the &lt;strong&gt;printable&lt;/strong&gt; buttons with &lt;code&gt;._buildExpression()&lt;/code&gt;. This allows your users to create math expressions by clicking on the calculator&amp;rsquo;s buttons. In the last line, you connect the clear button (&lt;code&gt;C&lt;/code&gt;) to &lt;code&gt;._view.clearDisplay()&lt;/code&gt;.  This method will clear up the text on the display.&lt;/p&gt;
&lt;p&gt;For this new controller class to work, you need to update &lt;code&gt;main()&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;# Client code&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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Main function.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Create an instance of QApplication&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pycalc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;c1&quot;&gt;# Show the calculator&amp;#39;s GUI&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCalcUi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&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;hll&quot;&gt;    &lt;span class=&quot;c1&quot;&gt;# Create instances of the model and the controller&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;PyCalcCtrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Execute calculator&amp;#39;s main loop&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;pycalc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&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 an instance of &lt;code&gt;PyCalcCtrl(view=view)&lt;/code&gt; with the &lt;code&gt;view&lt;/code&gt; passed in as an argument. This will initialize the controller and connect the signals and slots to give your calculator some functionality.&lt;/p&gt;
&lt;p&gt;If you run the application, then you&amp;rsquo;ll see something like the following:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/calculator-basic-ctrl.d979c7b56b59.gif&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/calculator-basic-ctrl.d979c7b56b59.gif&quot; width=&quot;276&quot; height=&quot;302&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/calculator-basic-ctrl.d979c7b56b59.gif&amp;amp;w=69&amp;amp;sig=dc360f0101153d75dba05f6fb7e7c57eee1925cc 69w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/calculator-basic-ctrl.d979c7b56b59.gif&amp;amp;w=138&amp;amp;sig=42ae1404e639c6295afed430bd0f60d6643382eb 138w, https://files.realpython.com/media/calculator-basic-ctrl.d979c7b56b59.gif 276w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCalc&amp;#39;s basic controller&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As you can see, the calculator already has some useful functionalities! Now, you can build math expressions by clicking on the buttons. Notice that the equals sign (&lt;code&gt;=&lt;/code&gt;) doesn&amp;rsquo;t work yet. To fix this, you need to implement the calculator&amp;rsquo;s model.&lt;/p&gt;
&lt;h3 id=&quot;implementing-the-model&quot;&gt;Implementing the Model&lt;/h3&gt;
&lt;p&gt;The model is the layer of code that takes care of the business logic. In this case, the business logic is all about basic math calculations. Your model will evaluate the math expressions introduced by your users. Since the model needs to handle errors, you&amp;rsquo;re going to define the following global constant:&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;ERROR_MSG&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;ERROR&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is the message the user will see if they introduce an invalid math expression.&lt;/p&gt;
&lt;p&gt;Your model will be a single 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;c1&quot;&gt;# Create a Model to handle the calculator&amp;#39;s operation&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;evaluateExpression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expression&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;Evaluate an expression.&amp;quot;&amp;quot;&amp;quot;&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;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eval&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expression&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;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;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ERROR_MSG&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you use &lt;code&gt;eval()&lt;/code&gt; to evaluate a string as an expression. If this is successful, then you&amp;rsquo;ll return the result. Otherwise, you&amp;rsquo;ll return the error message. Note that this function isn&amp;rsquo;t perfect. It has a couple of important issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;try...except&lt;/code&gt; block doesn&amp;rsquo;t catch any specific exception, which is not a best practice in Python.&lt;/li&gt;
&lt;li&gt;The function is based on the use of &lt;code&gt;eval()&lt;/code&gt;, which can lead to some serious &lt;a href=&quot;http://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html&quot;&gt;security issues&lt;/a&gt;. The general advice is to only use &lt;code&gt;eval()&lt;/code&gt; on trusted input.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You&amp;rsquo;re free to rework the function to make it more reliable and secure. For this tutorial, you&amp;rsquo;ll use the function as-is.&lt;/p&gt;
&lt;h3 id=&quot;completing-the-controller&quot;&gt;Completing the Controller&lt;/h3&gt;
&lt;p&gt;Once you&amp;rsquo;ve completed the calculator&amp;rsquo;s model, you can finish the controller. The final version of &lt;code&gt;PyCalcCtrl&lt;/code&gt; will include logic to process the calculations and to make sure the equals sign (&lt;code&gt;=&lt;/code&gt;) works correctly:&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 a Controller class to connect the GUI and the model&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PyCalcCtrl&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;PyCalc&amp;#39;s Controller.&amp;quot;&amp;quot;&amp;quot;&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;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;/span&gt;        &lt;span class=&quot;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Controller initializer.&amp;quot;&amp;quot;&amp;quot;&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;_evaluate&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Connect signals and slots&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;_connectSignals&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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_calculateResult&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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Evaluate expressions.&amp;quot;&amp;quot;&amp;quot;&lt;/span&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_evaluate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expression&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayText&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setDisplayText&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;p&quot;&gt;)&lt;/span&gt;
&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;_buildExpression&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;sub_exp&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;Build expression.&amp;quot;&amp;quot;&amp;quot;&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayText&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;ERROR_MSG&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clearDisplay&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&gt;        &lt;span class=&quot;n&quot;&gt;expression&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;displayText&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;sub_exp&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;setDisplayText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;expression&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;_connectSignals&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;Connect signals and slots.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;btnText&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;btn&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttons&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;btnText&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;p&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;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;btn&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicked&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;partial&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;_buildExpression&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;btnText&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttons&lt;/span&gt;&lt;span class=&quot;p&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicked&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&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;_calculateResult&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;returnPressed&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&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;_calculateResult&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buttons&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clicked&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;connect&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;_view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;clearDisplay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The new lines of code are highlighted. First, you add a new parameter to the init function. Now the class receives instances from both the model and the view. Then in &lt;code&gt;._calculateResult()&lt;/code&gt;, you take the display&amp;rsquo;s content, evaluate it as a math expression, and finally show the result in the display.&lt;/p&gt;
&lt;p&gt;You also add an &lt;code&gt;if&lt;/code&gt; statement to &lt;code&gt;._buildExpression()&lt;/code&gt; to check if an error has occurred. If so, then you clear the display and start over with a new expression. Finally, you add two more connections inside &lt;code&gt;._connectSignals()&lt;/code&gt;. The first enables the equals sign (&lt;code&gt;=&lt;/code&gt;). The second ensures that when the user hits &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt;, the calculator will process the expression as expected.&lt;/p&gt;
&lt;p&gt;For all this code to work, you need to update &lt;code&gt;main()&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;# Client code&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;sd&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Main function.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Create an instance of `QApplication`&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;pycalc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;QApplication&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;c1&quot;&gt;# Show the calculator&amp;#39;s GUI&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCalcUi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;view&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;# Create instances of the model and the controller&lt;/span&gt;
&lt;span class=&quot;hll&quot;&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;evaluateExpression&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;PyCalcCtrl&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;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 class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;# Execute calculator&amp;#39;s main loop&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;pycalc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;exec_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, your &lt;code&gt;model&lt;/code&gt; holds a reference to &lt;code&gt;evaluateExpression()&lt;/code&gt;. In addition, &lt;code&gt;PyCalcCtrl()&lt;/code&gt; now receives two arguments: the &lt;code&gt;model&lt;/code&gt; and the &lt;code&gt;view&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;running-the-calculator&quot;&gt;Running the Calculator&lt;/h3&gt;
&lt;p&gt;Now that you&amp;rsquo;ve finished the code, it&amp;rsquo;s time for a test! If you run the application, then you&amp;rsquo;ll see something like this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/pycalc.9572fb3104cb.gif&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/pycalc.9572fb3104cb.gif&quot; width=&quot;376&quot; height=&quot;326&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycalc.9572fb3104cb.gif&amp;amp;w=94&amp;amp;sig=6cc9758f8a9ce3af68b6b1b7e27a49668aebf5c1 94w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/pycalc.9572fb3104cb.gif&amp;amp;w=188&amp;amp;sig=1211ce2ddf630d182763c4aa1b03c0244cc7dd22 188w, https://files.realpython.com/media/pycalc.9572fb3104cb.gif 376w&quot; sizes=&quot;75vw&quot; alt=&quot;PyCalc, a calculator with Python and PyQt&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To use PyCalc, enter a valid math expression with your mouse. Then, press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt; or click on the equals sign (&lt;code&gt;=&lt;/code&gt;) to see the result on the calculator&amp;rsquo;s display.&lt;/p&gt;
&lt;p&gt;Congrats! You&amp;rsquo;ve developed your first fully-functional GUI desktop application with Python and PyQt!&lt;/p&gt;
&lt;h2 id=&quot;additional-tools&quot;&gt;Additional Tools&lt;/h2&gt;
&lt;p&gt;PyQt5 offers quite a useful set of additional tools to help you build solid, modern, and full-featured GUI applications. Here are some of the most remarkable tools you can use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/designer.html&quot;&gt;Qt Designer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The set of &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/i18n.html&quot;&gt;internationalization tools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;The PyQt5 &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/resources.html&quot;&gt;resource system&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Qt Designer&lt;/strong&gt; is the Qt tool for designing and building graphical user interfaces. You can use it to design widgets, dialogs, or complete main windows by using on-screen forms and a drag-and-drop mechanism. The following figure shows some of the Qt Designer&amp;rsquo;s features:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/qt-designer.bd1e2f5392c8.gif&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/qt-designer.bd1e2f5392c8.gif&quot; width=&quot;903&quot; height=&quot;580&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/qt-designer.bd1e2f5392c8.gif&amp;amp;w=225&amp;amp;sig=96dee4c6353f78fc2ebd6ba32158e70fd6413c61 225w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/qt-designer.bd1e2f5392c8.gif&amp;amp;w=451&amp;amp;sig=8fa24d41bb670190f20a6e253dc6be9299b46223 451w, https://files.realpython.com/media/qt-designer.bd1e2f5392c8.gif 903w&quot; sizes=&quot;75vw&quot; alt=&quot;Qt-Designer example&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Qt Designer uses XML &lt;code&gt;.ui&lt;/code&gt; files to store your GUI designs. You can load them with &lt;code&gt;QUiLoader&lt;/code&gt;. PyQt includes a module called &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/api/uic/uic-module.html&quot;&gt;uic&lt;/a&gt; to help with this. You can also convert the &lt;code&gt;.ui&lt;/code&gt; file content into Python code with a command-line tool called &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/designer.html#pyuic5&quot;&gt;&lt;code&gt;pyuic5&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;PyQt5 also provides a comprehensive set of tools for the &lt;strong&gt;internationalization&lt;/strong&gt; of apps into local languages. &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/i18n.html#pylupdate5&quot;&gt;&lt;strong&gt;&lt;code&gt;pylupdate5&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; creates and updates translation (&lt;code&gt;.ts&lt;/code&gt;) files. Then, &lt;a href=&quot;https://doc.qt.io/qt-5/qtlinguist-index.html&quot;&gt;&lt;strong&gt;Qt Linguist&lt;/strong&gt;&lt;/a&gt; updates the generated &lt;code&gt;.ts&lt;/code&gt; files with translations of the strings. It also releases the &lt;code&gt;.ts&lt;/code&gt; files as &lt;code&gt;.qm&lt;/code&gt; files. These &lt;code&gt;.qm&lt;/code&gt; files are compact binary equivalents that can be used directly by the application.&lt;/p&gt;
&lt;p&gt;Finally, you can use the PyQt5 &lt;strong&gt;resource system&lt;/strong&gt;, which is a facility for embedding resources such as icons and translation files. To use this tool, you need to generate a &lt;code&gt;.qrc&lt;/code&gt; file. This is an XML file that&amp;rsquo;s used to specify which resource files are to be embedded. Once you have this file ready, you can use &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/resources.html#pyrcc5&quot;&gt;&lt;code&gt;pyrcc5&lt;/code&gt;&lt;/a&gt; to generate a Python module that contains the embedded resources.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Graphical User Interface (GUI) desktop applications still hold a substantial share of the software development market. Python offers a handful of frameworks and libraries that can help you develop modern and robust GUI applications.&lt;/p&gt;
&lt;p&gt;In this tutorial, you learned how to use &lt;a href=&quot;https://www.riverbankcomputing.com/software/pyqt/intro&quot;&gt;PyQt&lt;/a&gt;, which is arguably one of the most popular and solid libraries for GUI desktop application development in Python. Now you know how to effectively use both Python and PyQt to build modern GUI desktop applications.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&amp;rsquo;re now able to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create Graphical User Interfaces with Python and PyQt&lt;/li&gt;
&lt;li&gt;Connect user events to concrete actions in your application&lt;/li&gt;
&lt;li&gt;Create fully-functional GUI desktop applications to solve real-world problems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you can use Python and PyQt to give life to your desktop GUI applications! You can get the source code for the calculator project and all code examples at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/pyqt-calculator/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-pyqt-calculator&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to build a calculator in Python with PyQt in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;If you want to dive deeper into PyQt and its related tools, then you can take a look at some of these resources:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt5/index.html&quot;&gt;PyQt5 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt4/&quot;&gt;PyQt4 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doc.qt.io/&quot;&gt;Qt v5 Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://wiki.python.org/moin/PyQt&quot;&gt;PyQt Wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.qtrac.eu/pyqtbook.html&quot;&gt;Rapid GUI Programming with Python and Qt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doc.qt.io/qt-5/qtdesigner-manual.html&quot;&gt;Qt Designer Manual&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://doc.qt.io/qtforpython/index.html&quot;&gt;Qt for Python (&lt;code&gt;PySide2&lt;/code&gt;) documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Although the PyQt5 Documentation is the first resource listed here, some important parts are still missing or incomplete. Fortunately, you can use the &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt4/&quot;&gt;PyQt4 Documentation&lt;/a&gt; to fill in the blanks. The &lt;a href=&quot;https://www.riverbankcomputing.com/static/Docs/PyQt4/classes.html&quot;&gt;Class Reference&lt;/a&gt; is particularly useful for gaining a complete understanding of widgets and classes.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using the PyQt4 documentation as a reference for PyQt5 classes, then bear in mind that the classes will be slightly different and may behave differently, too. Another option would be to use the original &lt;a href=&quot;https://doc.qt.io/&quot;&gt;Qt v5 Documentation&lt;/a&gt; and its &lt;a href=&quot;https://doc.qt.io/qt-5/classes.html&quot;&gt;Class Reference&lt;/a&gt; instead. In this case, you may need some background in C++ to properly understand the code samples.&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 Plotting With Matplotlib</title>
      <id>https://realpython.com/courses/python-plotting-matplotlib/</id>
      <link href="https://realpython.com/courses/python-plotting-matplotlib/"/>
      <updated>2019-10-22T14:00:00+00:00</updated>
      <summary>In this beginner-friendly course, you&#39;ll learn about plotting in Python with matplotlib by looking at the theory and following along with practical examples.</summary>
      <content type="html">
        &lt;p&gt;A picture is worth a thousand words, and with Python&amp;rsquo;s &lt;strong&gt;&lt;code&gt;matplotlib&lt;/code&gt;&lt;/strong&gt; library, it fortunately takes far less than a thousand words of code to create a production-quality graphic.&lt;/p&gt;
&lt;p&gt;However, &lt;code&gt;matplotlib&lt;/code&gt; is also a massive library, and getting a plot to look just right is often achieved through trial and error.  Using one-liners to generate basic plots in &lt;code&gt;matplotlib&lt;/code&gt; is relatively simple, but skillfully commanding the remaining 98% of the library can be daunting.&lt;/p&gt;
&lt;p&gt;In this &lt;strong&gt;beginner-friendly&lt;/strong&gt; course, you&amp;rsquo;ll learn about plotting in Python with &lt;code&gt;matplotlib&lt;/code&gt; by looking at the theory and following along with practical examples.  While learning by example can be tremendously insightful, it helps to have even just a surface-level understanding of the library&amp;rsquo;s inner workings and layout as well.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this course, you&amp;rsquo;ll:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Know the differences between PyLab and Pyplot&lt;/li&gt;
&lt;li&gt;Grasp the key concepts in the design of &lt;code&gt;matplotlib&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Understand &lt;code&gt;plt.subplots()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Visualize arrays with &lt;code&gt;matplotlib&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Plot by combining &lt;code&gt;pandas&lt;/code&gt; and &lt;code&gt;matplotlib&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This course assumes you know a tiny bit of NumPy. You&amp;rsquo;ll mainly use the &lt;a href=&quot;https://docs.scipy.org/doc/numpy/reference/routines.random.html&quot;&gt;&lt;code&gt;numpy.random&lt;/code&gt;&lt;/a&gt; module to generate &amp;ldquo;toy&amp;rdquo; data, drawing samples from different statistical distributions. If you don&amp;rsquo;t already have &lt;code&gt;matplotlib&lt;/code&gt; installed, see the &lt;a href=&quot;https://matplotlib.org/users/installing.html&quot;&gt;documentation&lt;/a&gt; for a walkthrough before proceeding.&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>Arduino With Python: How to Get Started</title>
      <id>https://realpython.com/arduino-python/</id>
      <link href="https://realpython.com/arduino-python/"/>
      <updated>2019-10-21T14:00:00+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll discover how to use Arduino with Python to develop your own electronic projects. You&#39;ll learn how to set up circuits and write applications with the Firmata protocol. You&#39;ll control Arduino inputs and outputs and integrate the board with higher-level apps.</summary>
      <content type="html">
        &lt;p&gt;&lt;a href=&quot;http://www.circuitstoday.com/microcontroller-invention-history&quot;&gt;Microcontrollers&lt;/a&gt; have been around for a long time, and they&amp;rsquo;re used in everything from complex machinery to common household appliances. However, working with them has traditionally been reserved for those with formal technical training, such as technicians and electrical engineers. The emergence of &lt;strong&gt;Arduino&lt;/strong&gt; has made electronic application design much more accessible to all developers. In this tutorial, you&amp;rsquo;ll discover how to use Arduino with Python to develop your own electronic projects.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You&amp;rsquo;ll cover the basics of Arduino with Python and learn how to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Set up electronic circuits&lt;/li&gt;
&lt;li&gt;Set up the Firmata protocol on Arduino&lt;/li&gt;
&lt;li&gt;Write basic applications for Arduino in Python&lt;/li&gt;
&lt;li&gt;Control analog and digital inputs and outputs&lt;/li&gt;
&lt;li&gt;Integrate Arduino sensors and switches with higher-level apps&lt;/li&gt;
&lt;li&gt;Trigger notifications on your PC and send emails using Arduino&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;the-arduino-platform&quot;&gt;The Arduino Platform&lt;/h2&gt;
&lt;p&gt;Arduino is an open-source platform composed of hardware and software that allows for the rapid development of interactive electronics projects. The &lt;a href=&quot;https://vimeo.com/18539129&quot;&gt;emergence of Arduino&lt;/a&gt; drew the attention of professionals from many different industries, &lt;a href=&quot;https://readwrite.com/2014/05/12/arduino-massimo-banzi-diy-electronics-hardware-hacking-builders/&quot;&gt;contributing&lt;/a&gt; to the start of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Maker_culture&quot;&gt;Maker Movement&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;With the growing popularity of the Maker Movement and the concept of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Internet_of_things&quot;&gt;Internet of Things&lt;/a&gt;, Arduino has become one of the main platforms for electronic prototyping and the development of MVPs.&lt;/p&gt;
&lt;p&gt;Arduino uses its own programming language, which is similar to C++. However, it&amp;rsquo;s possible to use Arduino with Python or another high-level programming language. In fact, platforms like Arduino work well with Python, especially for applications that require integration with sensors and other physical devices.&lt;/p&gt;
&lt;p&gt;All in all, Arduino and Python can facilitate an effective learning environment that encourages developers to get into electronics design. If you already know &lt;a href=&quot;https://realpython.com/learning-paths/python3-introduction/&quot;&gt;the basics of Python&lt;/a&gt;, then you&amp;rsquo;ll be able to get started with Arduino by using Python to control it.&lt;/p&gt;
&lt;p&gt;The Arduino platform includes both &lt;a href=&quot;https://www.arduino.cc/en/Main/Products&quot;&gt;hardware&lt;/a&gt; and software products. In this tutorial, you&amp;rsquo;ll use Arduino hardware and Python software to learn about basic circuits, as well as digital and analog inputs and outputs.&lt;/p&gt;
&lt;h3 id=&quot;arduino-hardware&quot;&gt;Arduino Hardware&lt;/h3&gt;
&lt;p&gt;To run the examples, you&amp;rsquo;ll need to assemble the circuits by hooking up &lt;strong&gt;electronic components&lt;/strong&gt;. You can generally find these items at electronic component stores or in good Arduino starter kits. You&amp;rsquo;ll need:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;An &lt;a href=&quot;https://store.arduino.cc/usa/arduino-uno-rev3&quot;&gt;Arduino Uno&lt;/a&gt; or other compatible board&lt;/li&gt;
&lt;li&gt;A standard LED of any color&lt;/li&gt;
&lt;li&gt;A push button&lt;/li&gt;
&lt;li&gt;A 10 KOhm potentiometer&lt;/li&gt;
&lt;li&gt;A 470 Ohm resistor&lt;/li&gt;
&lt;li&gt;A 10 KOhm resistor&lt;/li&gt;
&lt;li&gt;A breadboard&lt;/li&gt;
&lt;li&gt;Jumper wires of various colors and sizes&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s take a closer look at a few of these components.&lt;/p&gt;
&lt;p&gt;Component 1 is an &lt;a href=&quot;https://store.arduino.cc/usa/arduino-uno-rev3&quot;&gt;&lt;strong&gt;Arduino Uno&lt;/strong&gt;&lt;/a&gt; or other compatible board. Arduino is a project that includes many &lt;a href=&quot;https://www.arduino.cc/en/main/boards&quot;&gt;boards&lt;/a&gt; and modules for different purposes, and Arduino Uno is the most basic among these. It&amp;rsquo;s also the most used and most documented board of the whole Arduino family, so it&amp;rsquo;s a great choice for developers who are just getting started with electronics.&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; Arduino is an open hardware platform, so there are many other vendors who sell compatible boards that could be used to run the examples you see here. In this tutorial, you&amp;rsquo;ll learn how to use the Arduino Uno.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Components 5 and 6 are &lt;strong&gt;resistors.&lt;/strong&gt; Most resistors are identified by colored stripes according to a &lt;a href=&quot;https://en.wikipedia.org/wiki/Electronic_color_code#Resistor_color-coding&quot;&gt;color code&lt;/a&gt;. In general, the first three colors represent the &lt;strong&gt;value&lt;/strong&gt; of a resistor, while the fourth color represents its &lt;strong&gt;tolerance&lt;/strong&gt;. For a 470 Ohm resistor, the first three colors are yellow, violet, and brown. For a 10 KOhm resistor, the first three colors are brown, black, and orange.&lt;/p&gt;
&lt;p&gt;Component 7 is a &lt;strong&gt;breadboard&lt;/strong&gt;, which you use to hook up all the other components and assemble the circuits. While a breadboard is not required, it&amp;rsquo;s recommended that you get one if you intend to begin working with Arduino.&lt;/p&gt;
&lt;h3 id=&quot;arduino-software&quot;&gt;Arduino Software&lt;/h3&gt;
&lt;p&gt;In addition to these hardware components, you&amp;rsquo;ll need to install some software. The platform includes the &lt;a href=&quot;https://www.arduino.cc/en/Main/Software&quot;&gt;Arduino IDE&lt;/a&gt;, an Integrated Development Environment for programming Arduino devices, among other online tools.&lt;/p&gt;
&lt;p&gt;Arduino was designed to allow you to program the boards with little difficulty. In general, you&amp;rsquo;ll follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Connect the board to your PC&lt;/li&gt;
&lt;li&gt;Install and open the Arduino IDE&lt;/li&gt;
&lt;li&gt;Configure the board settings&lt;/li&gt;
&lt;li&gt;Write the code&lt;/li&gt;
&lt;li&gt;Press a button on the IDE to upload the program to the board&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To install the Arduino IDE on your computer, download the appropriate version for your operating system from the &lt;a href=&quot;https://www.arduino.cc/en/Main/Software&quot;&gt;Arduino website&lt;/a&gt;. Check the documentation for installation instructions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;If you&amp;rsquo;re using Windows&lt;/strong&gt;, then use the Windows installer to ensure you download the necessary drivers for using Arduino on Windows. Check the &lt;a href=&quot;https://www.arduino.cc/en/guide/windows&quot;&gt;Arduino documentation&lt;/a&gt; for more details.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If you&amp;rsquo;re using Linux&lt;/strong&gt;, then you may have to add your user to some groups in order to use the serial port to program Arduino. This process is described in the &lt;a href=&quot;https://www.arduino.cc/en/Guide/Linux&quot;&gt;Arduino install guide for Linux&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;If you&amp;rsquo;re using macOS&lt;/strong&gt;, then you can install Arduino IDE by following the &lt;a href=&quot;https://www.arduino.cc/en/Guide/MacOSX&quot;&gt;Arduino install guide for OS X&lt;/a&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; You&amp;rsquo;ll be using the Arduino IDE in this tutorial, but Arduino also provides a &lt;a href=&quot;https://create.arduino.cc/getting-started/plugin&quot;&gt;web editor&lt;/a&gt; that will let you program Arduino boards using the browser.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Now that you&amp;rsquo;ve installed the Arduino IDE and gathered all the necessary components, you&amp;rsquo;re ready to get started with Arduino! Next, you&amp;rsquo;ll upload a &amp;ldquo;Hello, World!&amp;rdquo; program to your board.&lt;/p&gt;
&lt;h2 id=&quot;hello-world-with-arduino&quot;&gt;&amp;ldquo;Hello, World!&amp;rdquo; With Arduino&lt;/h2&gt;
&lt;p&gt;The Arduino IDE comes with several example &lt;strong&gt;sketches&lt;/strong&gt; you can use to learn the basics of Arduino. A &lt;strong&gt;sketch&lt;/strong&gt; is the term you use for a program that you can upload to a board. Since the Arduino Uno doesn&amp;rsquo;t have an attached display, you&amp;rsquo;ll need a way to see the physical output from your program. You&amp;rsquo;ll use the &lt;strong&gt;Blink&lt;/strong&gt; example sketch to make a built-in LED on the Arduino board blink.&lt;/p&gt;
&lt;h3 id=&quot;uploading-the-blink-example-sketch&quot;&gt;Uploading the Blink Example Sketch&lt;/h3&gt;
&lt;p&gt;To get started, connect the Arduino board to your PC using a USB cable and start the Arduino IDE. To open the Blink example sketch, access the &lt;em&gt;File&lt;/em&gt; menu and select &lt;em&gt;Examples&lt;/em&gt;, then &lt;em&gt;01.Basics&lt;/em&gt; and, finally, &lt;em&gt;Blink&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/arduino_ide_open_blink.800adb25f6da.jpg&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/arduino_ide_open_blink.800adb25f6da.jpg&quot; width=&quot;1125&quot; height=&quot;929&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ide_open_blink.800adb25f6da.jpg&amp;amp;w=281&amp;amp;sig=055019bbe706464963f06f481af729849c02343b 281w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ide_open_blink.800adb25f6da.jpg&amp;amp;w=562&amp;amp;sig=69d488cbc74d6a13b73dcd40dba9fae3a66f1b98 562w, https://files.realpython.com/media/arduino_ide_open_blink.800adb25f6da.jpg 1125w&quot; sizes=&quot;75vw&quot; alt=&quot;Blink example sketch on Arduino IDE&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The Blink example code will be loaded into a new IDE window. But before you can upload the sketch to the board, you&amp;rsquo;ll need to configure the IDE by selecting your board and its connected port.&lt;/p&gt;
&lt;p&gt;To configure the board, access the &lt;em&gt;Tools&lt;/em&gt; menu and then &lt;em&gt;Board&lt;/em&gt;. For Arduino Uno, you should select &lt;em&gt;Arduino/Genuino Uno&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/arduino_ide_select_board.ab3e17d0f3e6.jpg&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/arduino_ide_select_board.ab3e17d0f3e6.jpg&quot; width=&quot;1127&quot; height=&quot;931&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ide_select_board.ab3e17d0f3e6.jpg&amp;amp;w=281&amp;amp;sig=84ed08b265f10c131d2726898db79b8e3b3ddd7b 281w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ide_select_board.ab3e17d0f3e6.jpg&amp;amp;w=563&amp;amp;sig=738da7d319ee154f1c470d1c2b0290768472d2e1 563w, https://files.realpython.com/media/arduino_ide_select_board.ab3e17d0f3e6.jpg 1127w&quot; sizes=&quot;75vw&quot; alt=&quot;Selecting board on Arduino IDE&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After you select the board, you have to set the appropriate port. Access the &lt;em&gt;Tools&lt;/em&gt; menu again, and this time select &lt;em&gt;Port&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/arduino_ide_select_port.7eef188bba81.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/arduino_ide_select_port.7eef188bba81.jpg&quot; width=&quot;1127&quot; height=&quot;931&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ide_select_port.7eef188bba81.jpg&amp;amp;w=281&amp;amp;sig=467112afaac65d92c2732d5b555c0e58ad11eba5 281w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ide_select_port.7eef188bba81.jpg&amp;amp;w=563&amp;amp;sig=c2f8d2b3df2ce3b461bbc63cb83fd819fe674112 563w, https://files.realpython.com/media/arduino_ide_select_port.7eef188bba81.jpg 1127w&quot; sizes=&quot;75vw&quot; alt=&quot;Selecting port on Arduino IDE&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The names of the ports may be different, depending on your operating system. In Windows, the ports will be named &lt;code&gt;COM4&lt;/code&gt;, &lt;code&gt;COM5&lt;/code&gt;, or something similar. In macOS or Linux, you may see something like &lt;code&gt;/dev/ttyACM0&lt;/code&gt; or &lt;code&gt;/dev/ttyUSB0&lt;/code&gt;. If you have any problems setting the port, then take a look at the &lt;a href=&quot;https://www.arduino.cc/en/Guide/Troubleshooting&quot;&gt;Arduino Troubleshooting Page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After you&amp;rsquo;ve configured the board and port, you&amp;rsquo;re all set to upload the sketch to your Arduino. To do that, you just have to press the &lt;em&gt;Upload&lt;/em&gt; button in the IDE toolbar:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/arduino_ide_buttons.fee61246ed0f.jpg&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/arduino_ide_buttons.fee61246ed0f.jpg&quot; width=&quot;1122&quot; height=&quot;194&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ide_buttons.fee61246ed0f.jpg&amp;amp;w=280&amp;amp;sig=ded323cc472d206a47180f70757fc057cb56e3b2 280w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ide_buttons.fee61246ed0f.jpg&amp;amp;w=561&amp;amp;sig=b65f0e145a74314dd7c30109ee70b772f428761c 561w, https://files.realpython.com/media/arduino_ide_buttons.fee61246ed0f.jpg 1122w&quot; sizes=&quot;75vw&quot; alt=&quot;Buttons for verify and upload on Arduino IDE&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you press &lt;em&gt;Upload&lt;/em&gt;, the IDE compiles the sketch and uploads it to your board. If you want to check for errors, then you can press &lt;em&gt;Verify&lt;/em&gt; before &lt;em&gt;Upload&lt;/em&gt;, which will only compile your sketch.&lt;/p&gt;
&lt;p&gt;The USB cable provides a serial connection to both upload the program and power the Arduino board. During the upload, you&amp;rsquo;ll see LEDs flashing on the board. After a few seconds, the uploaded program will run, and you&amp;rsquo;ll see an LED light blink once every second:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/blinking.ad6c84c75f27.gif&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/blinking.ad6c84c75f27.gif&quot; width=&quot;795&quot; height=&quot;596&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/blinking.ad6c84c75f27.gif&amp;amp;w=198&amp;amp;sig=2d33394a53c4aee9dd34646413a06fa0d77b0064 198w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/blinking.ad6c84c75f27.gif&amp;amp;w=397&amp;amp;sig=b2eca4275f83bd3340134acaa53eb47b82fc95c7 397w, https://files.realpython.com/media/blinking.ad6c84c75f27.gif 795w&quot; sizes=&quot;75vw&quot; alt=&quot;Arduino buit-in LED blinking&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After the upload is finished, the USB cable will continue to power the Arduino board. The program is stored in flash memory on the Arduino microcontroller. You can also use a battery or other external &lt;a href=&quot;https://www.technobyte.org/2016/07/power-up-the-arduino-uno/&quot;&gt;power supply&lt;/a&gt; to run the application without a USB cable.&lt;/p&gt;
&lt;h3 id=&quot;connecting-external-components&quot;&gt;Connecting External Components&lt;/h3&gt;
&lt;p&gt;In the previous section, you used an LED that was already present on the Arduino board. However, in most practical projects you&amp;rsquo;ll need to connect external components to the board. To make these connections, Arduino has several &lt;strong&gt;pins&lt;/strong&gt; of different types:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/arduino_ports.ccba6e743d26.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/arduino_ports.ccba6e743d26.png&quot; width=&quot;795&quot; height=&quot;596&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ports.ccba6e743d26.png&amp;amp;w=198&amp;amp;sig=7239440cbf40edfe77eab3f148eb59ebfcd6f099 198w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ports.ccba6e743d26.png&amp;amp;w=397&amp;amp;sig=d78bea13d341b32ab0c2b6445ac057a6ab253976 397w, https://files.realpython.com/media/arduino_ports.ccba6e743d26.png 795w&quot; sizes=&quot;75vw&quot; alt=&quot;Arduino Uno Ports&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Although these connections are commonly called &lt;strong&gt;pins&lt;/strong&gt;, you can see that they&amp;rsquo;re not exactly physical pins. Rather, the pins are holes in a socket to which you can connect jumper wires. In the  figure above, you can see different groups of pins:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Orange rectangle:&lt;/strong&gt; These are 13 &lt;strong&gt;digital pins&lt;/strong&gt; that you can use as inputs or outputs. They&amp;rsquo;re only meant to work with digital signals, which have 2 different levels:&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Level 0:&lt;/strong&gt; represented by the voltage 0V&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Level 1:&lt;/strong&gt; represented by the voltage 5V    &lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Green rectangle:&lt;/strong&gt; These are 6 &lt;strong&gt;analog pins&lt;/strong&gt; that you can use as analog inputs. They&amp;rsquo;re meant to work with an arbitrary voltage between 0V and 5V.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Blue rectangle:&lt;/strong&gt; These are 5 &lt;strong&gt;power pins&lt;/strong&gt;. They&amp;rsquo;re mainly used for powering external components.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To get started using external components, you&amp;rsquo;ll connect an external LED to run the Blink example sketch. The built-in LED is connected to &lt;strong&gt;digital pin #13&lt;/strong&gt;. So, let&amp;rsquo;s connect an external LED to that pin and check if it blinks. (A standard LED is one of the components you saw listed &lt;a href=&quot;https://realpython.com/arduino-python/#arduino-hardware&quot;&gt;earlier&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;Before you connect anything to the Arduino board, it&amp;rsquo;s good practice to disconnect it from the computer. With the USB cable unplugged, you&amp;rsquo;ll be able to connect the LED to your board:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/blink.18009615ed53.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/blink.18009615ed53.png&quot; width=&quot;795&quot; height=&quot;893&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/blink.18009615ed53.png&amp;amp;w=198&amp;amp;sig=bb031e1f8413ea2a523bb63e67c2b8d89993bf06 198w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/blink.18009615ed53.png&amp;amp;w=397&amp;amp;sig=bca292ef306989d9188c9f0befcb702dbf06fc1c 397w, https://files.realpython.com/media/blink.18009615ed53.png 795w&quot; sizes=&quot;75vw&quot; alt=&quot;Circuit for blink sketch&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Note that the figure shows the board with the digital pins now facing you.&lt;/p&gt;
&lt;h3 id=&quot;using-a-breadboard&quot;&gt;Using a Breadboard&lt;/h3&gt;
&lt;p&gt;Electronic circuit projects usually involve testing several ideas, with you adding new components and making adjustments as you go. However, it can be tricky to connect components directly, especially if the circuit is large.&lt;/p&gt;
&lt;p&gt;To facilitate prototyping, you can use a &lt;a href=&quot;https://en.wikipedia.org/wiki/Breadboard&quot;&gt;&lt;strong&gt;breadboard&lt;/strong&gt;&lt;/a&gt; to connect the components. This is a device with several holes that are connected in a particular way so that you can easily connect components using jumper wires:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/breadboard.1429308d8fa9.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-66&quot; src=&quot;https://files.realpython.com/media/breadboard.1429308d8fa9.jpg&quot; width=&quot;592&quot; height=&quot;479&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/breadboard.1429308d8fa9.jpg&amp;amp;w=148&amp;amp;sig=cf584b8df0ef0302a39d38097484508eb99efa97 148w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/breadboard.1429308d8fa9.jpg&amp;amp;w=296&amp;amp;sig=302f4bc44358ecc19c5e0812690f3218311c4d19 296w, https://files.realpython.com/media/breadboard.1429308d8fa9.jpg 592w&quot; sizes=&quot;75vw&quot; alt=&quot;Breadboard&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see which holes are interconnected by looking at the colored lines. You&amp;rsquo;ll use the holes on the sides of the breadboard to power the circuit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Connect one hole on the &lt;strong&gt;red line&lt;/strong&gt; to the power source.&lt;/li&gt;
&lt;li&gt;Connect one hole on the &lt;strong&gt;blue line&lt;/strong&gt; to the ground.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then, you can easily connect components to the power source or the ground by simply using the other holes on the red and blue lines. The holes in the middle of the breadboard are connected as indicated by the colors. You&amp;rsquo;ll use these to make connections between the components of the circuit. These two internal sections are separated by a small depression, over which you can connect integrated circuits (ICs).&lt;/p&gt;
&lt;p&gt;You can use a breadboard to assemble the circuit used in the Blink example sketch:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/blink_2.0a1b1975b7da.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/blink_2.0a1b1975b7da.png&quot; width=&quot;812&quot; height=&quot;1172&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/blink_2.0a1b1975b7da.png&amp;amp;w=203&amp;amp;sig=e3294c9162eb801c1a0f945d6b6bf0a0ac4f6b78 203w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/blink_2.0a1b1975b7da.png&amp;amp;w=406&amp;amp;sig=2f488cdaecaf5337ee52f0ed24639ad3f0b00423 406w, https://files.realpython.com/media/blink_2.0a1b1975b7da.png 812w&quot; sizes=&quot;75vw&quot; alt=&quot;Circuit for blink sketch on breadboard&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For this circuit, it&amp;rsquo;s important to note that the LED must be connected according to its polarity or it won&amp;rsquo;t work. The positive terminal of the LED is called the &lt;strong&gt;anode&lt;/strong&gt; and is generally the longer one. The negative terminal is called the &lt;strong&gt;cathode&lt;/strong&gt; and is shorter. If you&amp;rsquo;re using a recovered component, then you can also identify the terminals by looking for a flat side on the LED itself. This will indicate the position of the negative terminal.&lt;/p&gt;
&lt;p&gt;When you connect an LED to an Arduino pin, you&amp;rsquo;ll always need a resistor to limit its current and avoid burning out the LED prematurely. Here, you use a 470 Ohm resistor to do this. You can follow the connections and check that the circuit is the same:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The resistor is connected to digital pin 13 on the Arduino board.&lt;/li&gt;
&lt;li&gt;The LED anode is connected to the other terminal of the resistor.&lt;/li&gt;
&lt;li&gt;The LED cathode is connected to the ground (GND) via the blue line of holes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a more detailed explanation, check out &lt;a href=&quot;https://www.youtube.com/watch?v=6WReFkfrUIk&quot;&gt;How to Use a Breadboard&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After you finish the connection, plug the Arduino back into the PC and re-run the Blink sketch:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/blinking_2.ff9a0bc7491d.gif&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/blinking_2.ff9a0bc7491d.gif&quot; width=&quot;812&quot; height=&quot;1172&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/blinking_2.ff9a0bc7491d.gif&amp;amp;w=203&amp;amp;sig=45edad93091f6e7520e4af74999c371c36ff91fa 203w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/blinking_2.ff9a0bc7491d.gif&amp;amp;w=406&amp;amp;sig=1f2d541d85669d137524e3a25af644475dfc82b0 406w, https://files.realpython.com/media/blinking_2.ff9a0bc7491d.gif 812w&quot; sizes=&quot;75vw&quot; alt=&quot;Arduino built-in and external LEDs blinking&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As both LEDs are connected to digital pin 13, they blink together when the sketch is running.&lt;/p&gt;
&lt;h2 id=&quot;hello-world-with-arduino-and-python&quot;&gt;&amp;ldquo;Hello, World!&amp;rdquo; With Arduino and Python&lt;/h2&gt;
&lt;p&gt;In the previous section, you uploaded the Blink sketch to your Arduino board. Arduino sketches are written in a language similar to C++ and are compiled and recorded on the flash memory of the microcontroller when you press &lt;em&gt;Upload&lt;/em&gt;. While you can use &lt;a href=&quot;https://www.makeuseof.com/tag/programming-languages-can-use-arduino/&quot;&gt;another language&lt;/a&gt; to directly program the Arduino microcontroller, it&amp;rsquo;s not a trivial task!&lt;/p&gt;
&lt;p&gt;However, there are some approaches you can take to use Arduino with Python or other languages. One idea is to run the main program on a PC and use the serial connection to communicate with Arduino through the USB cable. The sketch would be responsible for reading the inputs, sending the information to the PC, and getting updates from the PC to update the Arduino outputs.&lt;/p&gt;
&lt;p&gt;To control Arduino from the PC, you&amp;rsquo;d have to design a protocol for the communication between the PC and Arduino. For example, you could consider a protocol with messages like the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;VALUE OF PIN 13 IS HIGH:&lt;/strong&gt; used to tell the PC about the status of digital input pins&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SET PIN 11 LOW:&lt;/strong&gt; used to tell Arduino to set the states of the output pins&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With the protocol defined, you could write an Arduino sketch to send messages to the PC and update the states of the pins according to the protocol. On the PC, you could write a program to control the Arduino through a serial connection, based on the protocol you&amp;rsquo;ve designed. For this, you can use whatever language and libraries you prefer, such as Python and the &lt;a href=&quot;https://pythonhosted.org/pyserial/&quot;&gt;PySerial&lt;/a&gt; library.&lt;/p&gt;
&lt;p&gt;Fortunately, there are standard protocols to do all this! &lt;a href=&quot;https://github.com/firmata/protocol&quot;&gt;&lt;strong&gt;Firmata&lt;/strong&gt;&lt;/a&gt; is one of them. This protocol establishes a serial communication format that allows you to read digital and analog inputs, as well as send information to digital and analog outputs.&lt;/p&gt;
&lt;p&gt;The Arduino IDE includes ready-made sketches that will drive Arduino through Python with the Firmata protocol. On the PC side, there are implementations of the protocol in several languages, including Python. To get started with Firmata, let&amp;rsquo;s use it to implement a &amp;ldquo;Hello, World!&amp;rdquo; program.&lt;/p&gt;
&lt;h3 id=&quot;uploading-the-firmata-sketch&quot;&gt;Uploading the Firmata Sketch&lt;/h3&gt;
&lt;p&gt;Before you write your Python program to drive Arduino, you have to upload the Firmata sketch so that you can use that protocol to control the board. The sketch is available in the Arduino IDE&amp;rsquo;s built-in examples. To open it, access the &lt;em&gt;File&lt;/em&gt; menu, then &lt;em&gt;Examples&lt;/em&gt;, followed by &lt;em&gt;Firmata&lt;/em&gt;, and finally &lt;em&gt;StandardFirmata&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/arduino_ide_firmata.35e3f089e6cd.jpg&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/arduino_ide_firmata.35e3f089e6cd.jpg&quot; width=&quot;1123&quot; height=&quot;921&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ide_firmata.35e3f089e6cd.jpg&amp;amp;w=280&amp;amp;sig=4773b28d28fdd8d2555747ca17ca786d1b17b1ff 280w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_ide_firmata.35e3f089e6cd.jpg&amp;amp;w=561&amp;amp;sig=ca5c514c4ef4983566262bbdcc3beeae4112d8fd 561w, https://files.realpython.com/media/arduino_ide_firmata.35e3f089e6cd.jpg 1123w&quot; sizes=&quot;75vw&quot; alt=&quot;Firmata example sketch on Arduino IDE&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The sketch will be loaded into a new IDE window. To upload it to the Arduino, you can follow the same steps you did before:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Plug the USB cable into the PC.&lt;/li&gt;
&lt;li&gt;Select the appropriate board and port on the IDE.&lt;/li&gt;
&lt;li&gt;Press &lt;em&gt;Upload&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After the upload is finished, you won&amp;rsquo;t notice any activity on the Arduino. To control it, you still need a program that can communicate with the board through the serial connection. To work with the Firmata protocol in Python, you&amp;rsquo;ll need the &lt;a href=&quot;https://github.com/tino/pyFirmata&quot;&gt;pyFirmata&lt;/a&gt; package, which you can install with &lt;a href=&quot;https://realpython.com/what-is-pip/&quot;&gt;&lt;code&gt;pip&lt;/code&gt;&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; pip install pyfirmata
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After the installation finishes, you can run an equivalent Blink application using Python and Firmata:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyfirmata&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &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;lineno&quot;&gt; 3 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Arduino&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/dev/ttyACM0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;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; 7 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digital&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;13&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;write&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;lineno&quot;&gt; 8 &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;1&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;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digital&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;13&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;write&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;lineno&quot;&gt;10 &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;1&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 how this program &lt;a href=&quot;https://github.com/tino/pyFirmata#usage&quot;&gt;works&lt;/a&gt;. You import &lt;code&gt;pyfirmata&lt;/code&gt; and use it to establish a serial connection with the Arduino board, which is represented by the &lt;code&gt;board&lt;/code&gt; object in line 4. You also configure the port in this line by passing an argument to &lt;code&gt;pyfirmata.Arduino()&lt;/code&gt;. You can use the Arduino IDE to find the port.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;board.digital&lt;/code&gt; is a list whose elements represent the digital pins of the Arduino. These elements have the methods &lt;code&gt;read()&lt;/code&gt; and &lt;code&gt;write()&lt;/code&gt;, which will read and write the state of the pins. Like most embedded device programs, this program mainly consists of an infinite loop:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;In line 7,&lt;/strong&gt; digital pin 13 is turned on, which turns the LED on for one second.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In line 9,&lt;/strong&gt; this pin is turned off, which turns the LED off for one second.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that you know the basics of how to control an Arduino with Python, let&amp;rsquo;s go through some applications to interact with its inputs and outputs.&lt;/p&gt;
&lt;h3 id=&quot;reading-digital-inputs&quot;&gt;Reading Digital Inputs&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Digital inputs&lt;/strong&gt; can have only two possible values. In a circuit, each of these values is represented by a different voltage. The table below shows the digital input representation for a standard Arduino Uno board:&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;Value&lt;/th&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Voltage&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;Low&lt;/td&gt;
&lt;td&gt;0V&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;5V&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p&gt;To control the LED, you&amp;rsquo;ll use a &lt;strong&gt;push button&lt;/strong&gt; to send digital input values to the Arduino. The button should send 0V to the board when it&amp;rsquo;s released and 5V to the board when it&amp;rsquo;s pressed. The figure below shows how to connect the button to the Arduino board:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/digital_input.5691a8f1d4fe.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/digital_input.5691a8f1d4fe.png&quot; width=&quot;1131&quot; height=&quot;1001&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/digital_input.5691a8f1d4fe.png&amp;amp;w=282&amp;amp;sig=d5aaf38db8d228fafaa6e58657080798504de61c 282w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/digital_input.5691a8f1d4fe.png&amp;amp;w=565&amp;amp;sig=3258209e9fc5b483c2cd48c43f3ddda830aa67ce 565w, https://files.realpython.com/media/digital_input.5691a8f1d4fe.png 1131w&quot; sizes=&quot;75vw&quot; alt=&quot;Circuit for digital input&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You may notice that the LED is connected to the Arduino on digital pin 13, just like before. Digital pin 10 is used as a digital input. To connect the push button, you have to use the 10 KOhm resistor, which acts as a &lt;a href=&quot;https://playground.arduino.cc/CommonTopics/PullUpDownResistor/&quot;&gt;pull down&lt;/a&gt; in this circuit. A &lt;strong&gt;pull down&lt;/strong&gt; resistor ensures that the digital input gets 0V when the button is released.&lt;/p&gt;
&lt;p&gt;When you release the button, you open the connection between the two wires on the button. Since there&amp;rsquo;s no current flowing through the resistor, pin 10 just connects to the ground (GND). The digital input gets 0V, which represents the &lt;strong&gt;0&lt;/strong&gt; (or &lt;strong&gt;low&lt;/strong&gt;) state. When you press the button, you apply 5V to both the resistor and the digital input. A current flows through the resistor and the digital input gets 5V, which represents the &lt;strong&gt;1&lt;/strong&gt; (or &lt;strong&gt;high&lt;/strong&gt;) state.&lt;/p&gt;
&lt;p&gt;You can use a breadboard to assemble the above circuit as well:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/digital_input_2.a46059238b65.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/digital_input_2.a46059238b65.png&quot; width=&quot;852&quot; height=&quot;1268&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/digital_input_2.a46059238b65.png&amp;amp;w=213&amp;amp;sig=0b85a665d5dde81c7572c09f3011e3156f8772bf 213w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/digital_input_2.a46059238b65.png&amp;amp;w=426&amp;amp;sig=92567a71da9c4e70440223f66979ef063e4a9f48 426w, https://files.realpython.com/media/digital_input_2.a46059238b65.png 852w&quot; sizes=&quot;75vw&quot; alt=&quot;Circuit for digital input on breadboard&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Now that you&amp;rsquo;ve assembled the circuit, you have to run a program on the PC to control it using Firmata. This program will turn on the LED, based on the state of the push button:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyfirmata&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &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;lineno&quot;&gt; 3 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Arduino&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/dev/ttyACM0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&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;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digital&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&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;lineno&quot;&gt;10 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &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;12 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digital&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sw&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&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;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digital&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;13&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;write&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;lineno&quot;&gt;15 &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;lineno&quot;&gt;16 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digital&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;13&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;write&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;lineno&quot;&gt;17 &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;mf&quot;&gt;0.1&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 walk through this program:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lines 1 and 2&lt;/strong&gt; import &lt;code&gt;pyfirmata&lt;/code&gt; and &lt;code&gt;time&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 4&lt;/strong&gt; uses &lt;code&gt;pyfirmata.Arduino()&lt;/code&gt; to set the connection with the Arduino board.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 6&lt;/strong&gt; assigns an iterator that will be used to read the status of the inputs of the circuit.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 7&lt;/strong&gt; starts the iterator, which keeps a loop running in parallel with your main code. The loop executes &lt;code&gt;board.iterate()&lt;/code&gt; to update the input values obtained from the Arduino board.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 9&lt;/strong&gt; sets pin 10 as a digital input with &lt;code&gt;pyfirmata.INPUT&lt;/code&gt;. This is necessary since the default configuration is to use digital pins as outputs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 11&lt;/strong&gt; starts an infinite &lt;code&gt;while&lt;/code&gt; loop. This loop reads the status of the input pin, stores it in &lt;code&gt;sw&lt;/code&gt;, and uses this value to turn the LED on or off by changing the value of pin 13.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 17&lt;/strong&gt; waits 0.1 seconds between iterations of the &lt;code&gt;while&lt;/code&gt; loop. This isn&amp;rsquo;t strictly necessary, but it&amp;rsquo;s a nice trick to avoid overloading the CPU, which reaches 100% load when there isn&amp;rsquo;t a wait command in the loop.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;pyfirmata&lt;/code&gt; also offers a more compact syntax to work with input and output pins. This may be a good option for when you&amp;rsquo;re working with several pins. You can rewrite the previous program to have more compact syntax:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyfirmata&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &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;lineno&quot;&gt; 3 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Arduino&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/dev/ttyACM0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&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;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;digital_input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;d:10:i&amp;#39;&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;n&quot;&gt;led&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;d:13:o&amp;#39;&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;lineno&quot;&gt;12 &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;13 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digital_input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sw&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&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;15 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;led&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;16 &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;lineno&quot;&gt;17 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;led&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;18 &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;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this version, you use &lt;code&gt;board.get_pin()&lt;/code&gt; to create two objects. &lt;code&gt;digital_input&lt;/code&gt; represents the digital input state, and &lt;code&gt;led&lt;/code&gt; represents the LED state. When you run this method, you have to pass a string argument composed of three elements separated by colons:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;The type&lt;/strong&gt; of the pin (&lt;code&gt;a&lt;/code&gt; for analog or &lt;code&gt;d&lt;/code&gt; for digital)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The number&lt;/strong&gt; of the pin&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The mode&lt;/strong&gt; of the pin (&lt;code&gt;i&lt;/code&gt; for input or &lt;code&gt;o&lt;/code&gt; for output)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Since &lt;code&gt;digital_input&lt;/code&gt; is a digital input using pin 10, you pass the argument &lt;code&gt;&#39;d:10:i&#39;&lt;/code&gt;. The LED state is set to a digital output using pin 13, so the &lt;code&gt;led&lt;/code&gt; argument is &lt;code&gt;&#39;d:13:o&#39;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;When you use &lt;code&gt;board.get_pin()&lt;/code&gt;, there&amp;rsquo;s no need to explicitly set up pin 10 as an input like you did before with &lt;code&gt;pyfirmata.INPUT&lt;/code&gt;. After the pins are set, you can access the status of a digital input pin using &lt;code&gt;read()&lt;/code&gt;, and set the status of a digital output pin with &lt;code&gt;write()&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Digital inputs are widely used in electronics projects. Several sensors provide digital signals, like presence or door sensors, that can be used as inputs to your circuits. However, there are some cases where you&amp;rsquo;ll need to measure analog values, such as distance or physical quantities. In the next section, you&amp;rsquo;ll see how to read analog inputs using Arduino with Python.&lt;/p&gt;
&lt;h3 id=&quot;reading-analog-inputs&quot;&gt;Reading Analog Inputs&lt;/h3&gt;
&lt;p&gt;In contrast to digital inputs, which can only be on or off, &lt;strong&gt;analog inputs&lt;/strong&gt; are used to read values in some range. On the Arduino Uno, the voltage to an analog input ranges from 0V to 5V. Appropriate sensors are used to measure physical quantities, such as distances. These sensors are responsible for encoding these physical quantities in the proper voltage range so they can be read by the Arduino.&lt;/p&gt;
&lt;p&gt;To read an analog voltage, the Arduino uses an &lt;a href=&quot;https://en.wikipedia.org/wiki/Analog-to-digital_converter&quot;&gt;&lt;strong&gt;analog-to-digital converter (ADC)&lt;/strong&gt;&lt;/a&gt;, which converts the input voltage to a digital number with a fixed number of bits. This determines the resolution of the conversion. The Arduino Uno uses a 10-bit ADC and can determine 1024 different voltage levels.&lt;/p&gt;
&lt;p&gt;The voltage range for an analog input is encoded to numbers ranging from 0 to 1023. When 0V is applied, the Arduino encodes it to the number &lt;strong&gt;0&lt;/strong&gt;. When 5V is applied, the encoded number is &lt;strong&gt;1023&lt;/strong&gt;. All intermediate voltage values are proportionally encoded.&lt;/p&gt;
&lt;p&gt;A &lt;a href=&quot;https://en.wikipedia.org/wiki/Potentiometer&quot;&gt;potentiometer&lt;/a&gt; is a variable resistor that you can use to set the voltage applied to an Arduino analog input. You&amp;rsquo;ll connect it to an analog input to control the frequency of a blinking LED:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/analog_input.b5c94511d649.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/analog_input.b5c94511d649.png&quot; width=&quot;969&quot; height=&quot;1007&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_input.b5c94511d649.png&amp;amp;w=242&amp;amp;sig=9c33b1f97a09b38e8b87368e7919a0d19a56559f 242w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_input.b5c94511d649.png&amp;amp;w=484&amp;amp;sig=59889ec322f095717b72d3a52b468c7904df252f 484w, https://files.realpython.com/media/analog_input.b5c94511d649.png 969w&quot; sizes=&quot;75vw&quot; alt=&quot;Circuit for analog input&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this circuit, the LED is set up just as before. The end terminals of the potentiometer are connected to ground (GND) and 5V pins. This way, the central terminal (the cursor) can have any voltage in the 0V to 5V range depending on its position, which is connected to the Arduino on analog pin A0.&lt;/p&gt;
&lt;p&gt;Using a breadboard, you can assemble this circuit as follows:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/analog_input_2.1d0464a94dd5.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/analog_input_2.1d0464a94dd5.png&quot; width=&quot;878&quot; height=&quot;1316&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_input_2.1d0464a94dd5.png&amp;amp;w=219&amp;amp;sig=158d411f7a77c9476a40d8063ded671ace28ac79 219w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_input_2.1d0464a94dd5.png&amp;amp;w=439&amp;amp;sig=82638b4bccfdf8b8e5523883a9fbbf354deaab58 439w, https://files.realpython.com/media/analog_input_2.1d0464a94dd5.png 878w&quot; sizes=&quot;75vw&quot; alt=&quot;Circuit for analog input on breadboard&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Before you control the LED, you can use the circuit to check the different values the Arduino reads, based on the position of the potentiometer. To do this, run the following program on your PC:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyfirmata&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &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;lineno&quot;&gt; 3 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Arduino&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/dev/ttyACM0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&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;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&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;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;analog_input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a:0:i&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&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;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;11 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;analog_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;analog_input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;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;n&quot;&gt;analog_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;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;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In line 8, you set up &lt;code&gt;analog_input&lt;/code&gt; as the analog A0 input pin with the argument &lt;code&gt;&#39;a:0:i&#39;&lt;/code&gt;. Inside the infinite &lt;code&gt;while&lt;/code&gt; loop, you read this value, store it in &lt;code&gt;analog_value&lt;/code&gt;, and display the output to the console with &lt;code&gt;print()&lt;/code&gt;. When you move the potentiometer while the program runs, you should output similar to 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;go&quot;&gt;0.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.0293&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.1056&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.1838&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.2717&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.3705&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.4428&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.5064&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.5797&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.6315&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.6764&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.7243&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.7859&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.8446&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.9042&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;0.9677&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1.0&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The printed values change, ranging from 0 when the position of the potentiometer is on one end to 1 when it&amp;rsquo;s on the other end. Note that these are float values, which may require conversion depending on the application.&lt;/p&gt;
&lt;p&gt;To change the frequency of the blinking LED, you can use the &lt;code&gt;analog_value&lt;/code&gt; to control how long the LED will be kept on or off:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyfirmata&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &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;lineno&quot;&gt; 3 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Arduino&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/dev/ttyACM0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&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;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&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;lineno&quot;&gt; 8 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;analog_input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a:0:i&amp;#39;&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;n&quot;&gt;led&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;d:13:o&amp;#39;&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;lineno&quot;&gt;11 &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;12 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;analog_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;analog_input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;analog_value&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;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;delay&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;analog_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;0.01&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;led&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;        &lt;span class=&quot;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;n&quot;&gt;delay&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;n&quot;&gt;led&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;        &lt;span class=&quot;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;n&quot;&gt;delay&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;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;        &lt;span class=&quot;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;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you calculate &lt;code&gt;delay&lt;/code&gt; as &lt;code&gt;analog_value + 0.01&lt;/code&gt; to avoid having &lt;code&gt;delay&lt;/code&gt; equal to zero. Otherwise, it&amp;rsquo;s common to get an &lt;code&gt;analog_value&lt;/code&gt; of &lt;code&gt;None&lt;/code&gt; during the first few iterations. To avoid getting an error when running the program, you use a conditional in line 13 to test whether &lt;code&gt;analog_value&lt;/code&gt; is &lt;code&gt;None&lt;/code&gt;. Then you control the period of the blinking LED.&lt;/p&gt;
&lt;p&gt;Try running the program and changing the position of the potentiometer. You&amp;rsquo;ll notice the frequency of the blinking LED changes:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/analog_input_demo.8a1831c1c606.gif&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/analog_input_demo.8a1831c1c606.gif&quot; width=&quot;400&quot; height=&quot;292&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_input_demo.8a1831c1c606.gif&amp;amp;w=100&amp;amp;sig=50ca19a634a7141af0c59161783c11a09d75d477 100w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_input_demo.8a1831c1c606.gif&amp;amp;w=200&amp;amp;sig=37bada143fcb3e1545e2258e703d4616d9d6a98c 200w, https://files.realpython.com/media/analog_input_demo.8a1831c1c606.gif 400w&quot; sizes=&quot;75vw&quot; alt=&quot;Led controlled by an analog input&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;By now, you&amp;rsquo;ve seen how to use digital inputs, digital outputs, and analog inputs on your circuits. In the next section, you&amp;rsquo;ll see how to use analog outputs.&lt;/p&gt;
&lt;h3 id=&quot;using-analog-outputs&quot;&gt;Using Analog Outputs&lt;/h3&gt;
&lt;p&gt;In some cases, it&amp;rsquo;s necessary to have an &lt;strong&gt;analog output&lt;/strong&gt; to drive a device that requires an analog signal. Arduino doesn&amp;rsquo;t include a real analog output, one where the voltage could be set to any value in a certain range. However, Arduino does include several &lt;a href=&quot;https://en.wikipedia.org/wiki/Pulse-width_modulation&quot;&gt;&lt;strong&gt;Pulse Width Modulation&lt;/strong&gt;&lt;/a&gt; (PWM) outputs.&lt;/p&gt;
&lt;p&gt;PWM is a modulation technique in which a digital output is used to generate a signal with variable power. To do this, it uses a digital signal of constant frequency, in which the &lt;a href=&quot;https://en.wikipedia.org/wiki/Duty_cycle&quot;&gt;&lt;strong&gt;duty cycle&lt;/strong&gt;&lt;/a&gt; is changed according to the desired power. The duty cycle represents the fraction of the period in which the signal is set to &lt;strong&gt;high&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Not all Arduino digital pins can be used as PWM outputs. The ones that can be are identified by a tilde (&lt;code&gt;~&lt;/code&gt;):&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/arduino_pwm.e5057a13e704.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/arduino_pwm.e5057a13e704.png&quot; width=&quot;795&quot; height=&quot;596&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_pwm.e5057a13e704.png&amp;amp;w=198&amp;amp;sig=7f419027879df29b724a42d763b95cf1d815d1ca 198w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/arduino_pwm.e5057a13e704.png&amp;amp;w=397&amp;amp;sig=d4f7f7425600dc98e99102bf5566561f1c6ca38e 397w, https://files.realpython.com/media/arduino_pwm.e5057a13e704.png 795w&quot; sizes=&quot;75vw&quot; alt=&quot;Arduino Uno PWM ports&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Several devices are designed to be driven by PWM signals, including some motors. It&amp;rsquo;s even possible to obtain a real analog signal from the PWM signal if you use analog filters. In the previous example, you used a digital output to turn an LED light on or off. In this section, you&amp;rsquo;ll use PWM to control the brightness of an LED, according to the value of an analog input given by a potentiometer.&lt;/p&gt;
&lt;p&gt;When a PWM signal is applied to an LED, its brightness varies according to the duty cycle of the PWM signal. You&amp;rsquo;re going to use the following circuit:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/analog_output.6ea6cfee6f56.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/analog_output.6ea6cfee6f56.png&quot; width=&quot;969&quot; height=&quot;1007&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_output.6ea6cfee6f56.png&amp;amp;w=242&amp;amp;sig=65680f7be124c259a18dfb3c15bf5a5b2d101062 242w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_output.6ea6cfee6f56.png&amp;amp;w=484&amp;amp;sig=4c49907e869252f75bad073aec1af3ac4dde89a9 484w, https://files.realpython.com/media/analog_output.6ea6cfee6f56.png 969w&quot; sizes=&quot;75vw&quot; alt=&quot;Circuit for analog output&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This circuit is identical to the one used in the previous section to test the analog input, except for one difference. Since it&amp;rsquo;s not possible to use PWM with pin 13, the digital output pin used for the LED is pin 11.&lt;/p&gt;
&lt;p&gt;You can use a breadboard to assemble the circuit as follows:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/analog_output_2.f8d946a95317.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/analog_output_2.f8d946a95317.png&quot; width=&quot;882&quot; height=&quot;1322&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_output_2.f8d946a95317.png&amp;amp;w=220&amp;amp;sig=dd6986056be14cb33b70430a17704c51e9934393 220w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_output_2.f8d946a95317.png&amp;amp;w=441&amp;amp;sig=775787132b997b288f28e01d0592298e79dbfd01 441w, https://files.realpython.com/media/analog_output_2.f8d946a95317.png 882w&quot; sizes=&quot;75vw&quot; alt=&quot;Circuit for analog output on breadboard&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With the circuit assembled, you can control the LED using PWM with the following 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;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyfirmata&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &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;lineno&quot;&gt; 3 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Arduino&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/dev/ttyACM0&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&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;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;analog_input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;a:0:i&amp;#39;&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;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;led&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;d:11:p&amp;#39;&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;lineno&quot;&gt;12 &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;13 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;analog_value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;analog_input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;analog_value&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;lineno&quot;&gt;15 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;        &lt;span class=&quot;n&quot;&gt;led&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;analog_value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;16 &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;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;There are a few differences from the programs you&amp;rsquo;ve used previously:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;In line 10&lt;/strong&gt;, you set &lt;code&gt;led&lt;/code&gt; to PWM mode by passing the argument &lt;code&gt;&#39;d:11:p&#39;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;In line 15&lt;/strong&gt;, you call &lt;code&gt;led.write()&lt;/code&gt; with &lt;code&gt;analog_value&lt;/code&gt; as an argument. This is a value between 0 and 1, read from the analog input.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here you can see the LED behavior when the potentiometer is moved:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/analog_output.ba983178383a.gif&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/analog_output.ba983178383a.gif&quot; width=&quot;350&quot; height=&quot;373&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_output.ba983178383a.gif&amp;amp;w=87&amp;amp;sig=9df5bb449773f0f99686e5431743047c3ca6055d 87w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/analog_output.ba983178383a.gif&amp;amp;w=175&amp;amp;sig=00492ea441b72be4940be3dfd91b4ffd027161c3 175w, https://files.realpython.com/media/analog_output.ba983178383a.gif 350w&quot; sizes=&quot;75vw&quot; alt=&quot;PWM output on oscilloscope&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;To show the changes in the duty cycle, an oscilloscope is plugged into pin 11. When the potentiometer is in its zero position, you can see the LED is turned off, as pin 11 has 0V on its output. As you turn the potentiometer, the LED gets brighter as the PWM duty cycle increases. When you turn the potentiometer all the way, the duty cycle reaches 100%. The LED is turned on continuously at maximum brightness.&lt;/p&gt;
&lt;p&gt;With this example, you&amp;rsquo;ve covered the basics of using an Arduino and its digital and analog inputs and outputs. In the next section, you&amp;rsquo;ll see an application for using Arduino with Python to drive events on the PC.&lt;/p&gt;
&lt;h3 id=&quot;using-a-sensor-to-trigger-a-notification&quot;&gt;Using a Sensor to Trigger a Notification&lt;/h3&gt;
&lt;p&gt;Firmata is a nice way to get started with Arduino with Python, but the need for a PC or other device to run the application can be costly, and this approach may not be practical in some cases. However, when it&amp;rsquo;s necessary to collect data and send it to a PC using external sensors, Arduino and Firmata make a good combination.&lt;/p&gt;
&lt;p&gt;In this section, you&amp;rsquo;ll use a push button connected to your Arduino to mimic a &lt;strong&gt;digital sensor&lt;/strong&gt; and trigger a notification on your machine. For a more practical application, you can think of the push button as a door sensor that will trigger an alarm notification, for example.&lt;/p&gt;
&lt;p&gt;To display the notification on the PC, you&amp;rsquo;re going to use &lt;a href=&quot;https://wiki.python.org/moin/TkInter&quot;&gt;Tkinter&lt;/a&gt;, the standard Python &lt;a href=&quot;https://en.wikipedia.org/wiki/Graphical_user_interface&quot;&gt;GUI&lt;/a&gt; toolkit. This will show a message box when you press the button. For an in-depth intro to Tkinter, check out the library&amp;rsquo;s &lt;a href=&quot;https://wiki.python.org/moin/TkInter&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll need to assemble the same circuit that you used in the &lt;a href=&quot;#reading-digital-inputs&quot;&gt;digital input&lt;/a&gt; example:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/digital_input.5691a8f1d4fe.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/digital_input.5691a8f1d4fe.png&quot; width=&quot;1131&quot; height=&quot;1001&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/digital_input.5691a8f1d4fe.png&amp;amp;w=282&amp;amp;sig=d5aaf38db8d228fafaa6e58657080798504de61c 282w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/digital_input.5691a8f1d4fe.png&amp;amp;w=565&amp;amp;sig=3258209e9fc5b483c2cd48c43f3ddda830aa67ce 565w, https://files.realpython.com/media/digital_input.5691a8f1d4fe.png 1131w&quot; sizes=&quot;75vw&quot; alt=&quot;Circuit for digital input&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After you assemble the circuit, use the following program to trigger the notifications:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyfirmata&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &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;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tkinter&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;tkinter&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;messagebox&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;n&quot;&gt;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tkinter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Tk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;withdraw&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;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Arduino&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/dev/ttyACM0&amp;#39;&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;lineno&quot;&gt;11 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&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;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digital_input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;d:10:i&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;led&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;d:13:o&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &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;18 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digital_input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;19 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sw&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&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;20 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;led&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;mi&quot;&gt;1&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;n&quot;&gt;messagebox&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;showinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Notification&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Button was pressed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;update&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;led&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;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;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;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This program is similar to the one used in the &lt;a href=&quot;#reading-digital-inputs&quot;&gt;digital input&lt;/a&gt; example, with a few changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lines 3 and 4&lt;/strong&gt; import libraries needed to set up Tkinter.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 6&lt;/strong&gt; creates Tkinter&amp;rsquo;s main window.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 7&lt;/strong&gt; tells Tkinter not to show the main window on the screen. For this example, you only need to see the message box.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 17&lt;/strong&gt; starts the &lt;code&gt;while&lt;/code&gt; loop:&lt;ol&gt;
&lt;li&gt;When you press the button, the LED will turn on and &lt;code&gt;messagebox.showinfo()&lt;/code&gt; displays a message box.&lt;/li&gt;
&lt;li&gt;The loop pauses until the user presses &lt;em&gt;OK&lt;/em&gt;. This way, the LED remains on as long as the message is on the screen.&lt;/li&gt;
&lt;li&gt;After the user presses &lt;em&gt;OK&lt;/em&gt;, &lt;code&gt;root.update()&lt;/code&gt; clears the message box from the screen and the LED is turned off.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To extend the notification example, you could even use the push button to send an email when pressed:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;pyfirmata&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 2 &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;lineno&quot;&gt; 3 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;smtplib&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;ssl&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;send_email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;465&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# For SSL&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 8 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;smtp_server&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;smtp.gmail.com&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 9 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sender_email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;lt;your email address&amp;gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;receiver_email&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;lt;destination email address&amp;gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;&amp;lt;password&amp;gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;12 &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;s2&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Subject: Arduino Notification&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; The switch was turned on.&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;13 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ssl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_default_context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smtplib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SMTP_SSL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;smtp_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;context&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;server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Sending email&amp;quot;&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;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender_email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;password&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sendmail&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sender_email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;receiver_email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;message&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;lineno&quot;&gt;20 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Arduino&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;/dev/ttyACM0&amp;#39;&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;lineno&quot;&gt;22 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyfirmata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;util&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Iterator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;board&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;it&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digital_input&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;board&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_pin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;d:10:i&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27 &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;28 &lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;sw&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digital_input&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29 &lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sw&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&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;30 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;send_email&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31 &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;mf&quot;&gt;0.1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can learn more about &lt;code&gt;send_email()&lt;/code&gt; in &lt;a href=&quot;https://realpython.com/python-send-email/&quot;&gt;Sending Emails With Python&lt;/a&gt;. Here, you configure the function with email server credentials, which will be used to send the email.&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 use a Gmail account to send the emails, then you need to enable the &lt;em&gt;Allow less secure apps&lt;/em&gt; option. For more information on how to do this, check out &lt;a href=&quot;https://realpython.com/python-send-email/&quot;&gt;Sending Emails With Python&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;With these example applications, you&amp;rsquo;ve seen how to use Firmata to interact with more complex Python applications. Firmata lets you use any sensor attached to the Arduino to obtain data for your application. Then you can process the data and make decisions within the main application. You can even use Firmata to send data to Arduino outputs, controlling switches or PWM devices.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re interested in using Firmata to interact with more complex applications, then try out some of these projects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A temperature monitor to alert you when the temperature gets too high or low&lt;/li&gt;
&lt;li&gt;An analog light sensor that can sense when a light bulb is burned out&lt;/li&gt;
&lt;li&gt;A water sensor that can automatically turn on the sprinklers when the ground is too dry&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Microcontroller platforms are on the rise, thanks to the growing popularity of the Maker Movement and the Internet of Things. Platforms like &lt;strong&gt;Arduino&lt;/strong&gt; are receiving a lot of attention in particular, as they allow developers just like you to use their skills and dive into electronic projects.&lt;/p&gt;
&lt;p&gt;You learned how to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Develop applications with Arduino and Python&lt;/li&gt;
&lt;li&gt;Use the Firmata protocol&lt;/li&gt;
&lt;li&gt;Control analog and digital inputs and outputs&lt;/li&gt;
&lt;li&gt;Integrate sensors with higher-level Python applications&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You also saw how Firmata may be a very interesting alternative for projects that demand a PC and depend on sensor data. Plus, it&amp;rsquo;s an easy way to get started with Arduino if you already know Python!&lt;/p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further Reading&lt;/h2&gt;
&lt;p&gt;Now that you know the basics of controlling Arduino with Python, you can start working on more complex applications. There are several tutorials that can help you develop integrated projects. Here are a few ideas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;REST APIs:&lt;/strong&gt; These are widely used to integrate different applications. You could use REST with Arduino to build APIs that get information from sensors and send commands to actuators. To learn about REST APIs, check out &lt;a href=&quot;https://realpython.com/flask-connexion-rest-api/&quot;&gt;Python REST APIs With Flask, Connexion, and SQLAlchemy&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Alternate GUIs:&lt;/strong&gt; In this tutorial, you used Tkinter to build a graphical application. However, there are other graphical libraries for desktop applications. To see an alternative, check out &lt;a href=&quot;https://realpython.com/python-gui-with-wxpython/&quot;&gt;How to Build a Python GUI Application With wxPython&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Threading:&lt;/strong&gt; The infinite &lt;code&gt;while&lt;/code&gt; loop that you used in this tutorial is a very common feature of Arduino applications. However, using a thread to run the main loop will allow you to execute other tasks concurrently. To learn how to use threads, 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;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Face Detection:&lt;/strong&gt; It&amp;rsquo;s common for IoT apps to integrate machine learning and computer vision algorithms. With these, you could build an alarm that triggers a notification when it detects faces on a camera, for example. To learn more about facial recognition systems, check out &lt;a href=&quot;https://realpython.com/traditional-face-detection-python/&quot;&gt;Traditional Face Detection With Python&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Lastly, there are other ways of using Python in microcontrollers besides Firmata and Arduino:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;pySerial:&lt;/strong&gt; Arduino Uno cannot run Python directly, but you could design your own Arduino sketch and use &lt;a href=&quot;https://github.com/pyserial/pyserial&quot;&gt;pySerial&lt;/a&gt; to establish a serial connection. Then you can control Arduino with Python using your own protocol.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;MicroPython:&lt;/strong&gt; If you&amp;rsquo;re interested in running Python directly on a microcontroller, then check out the &lt;a href=&quot;https://micropython.org/&quot;&gt;MicroPython&lt;/a&gt; project. It provides an efficient implementation of Python to be executed on some microcontrollers such as the &lt;a href=&quot;https://en.wikipedia.org/wiki/ESP8266&quot;&gt;ESP8266&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/ESP32&quot;&gt;ESP32&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SBCs:&lt;/strong&gt; Another option is to use a &lt;a href=&quot;https://en.wikipedia.org/wiki/Single-board_computer&quot;&gt;single board computer (SBC)&lt;/a&gt; such as a &lt;a href=&quot;https://www.raspberrypi.org/&quot;&gt;Raspberry Pi&lt;/a&gt; to run Python. SBCs are complete, Arduino-sized computers that can run a Linux-based operating system, allowing you to use vanilla Python. As most SBCs provide &lt;a href=&quot;https://en.wikipedia.org/wiki/General-purpose_input/output&quot;&gt;General-purpose input and output pins&lt;/a&gt;, you can use it to replace an Arduino on most applications.&lt;/p&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 sleep(): How to Add Time Delays to Your Code</title>
      <id>https://realpython.com/python-sleep/</id>
      <link href="https://realpython.com/python-sleep/"/>
      <updated>2019-10-16T14:00:00+00:00</updated>
      <summary>In this tutorial, you&#39;ll learn how to add time delays to your Python programs. You&#39;ll use decorators and the built-in time module to add Python sleep() calls to your code. Then, you&#39;ll discover how time delays work with threads, asynchronous functions, and graphical user interfaces.</summary>
      <content type="html">
        &lt;p&gt;Have you ever needed to make your Python program wait for something? Most of the time, you&amp;rsquo;d want your code to execute as quickly as possible. But there are times when letting your code sleep for a while is actually in your best interest.&lt;/p&gt;
&lt;p&gt;For example, you might use a Python &lt;code&gt;sleep()&lt;/code&gt; call to simulate a delay in your program. Perhaps you need to wait for a file to upload or download, or for a graphic to load or be drawn to the screen. You might even need to pause between calls to a web API, or between queries to a database. Adding Python &lt;strong&gt;&lt;code&gt;sleep()&lt;/code&gt;&lt;/strong&gt; calls to your program can help in each of these cases, and many more!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this tutorial, you&amp;rsquo;ll learn how to add Python &lt;code&gt;sleep()&lt;/code&gt; calls with:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;time.sleep()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Decorators&lt;/li&gt;
&lt;li&gt;Threads&lt;/li&gt;
&lt;li&gt;Async IO&lt;/li&gt;
&lt;li&gt;Graphical User Interfaces&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article is intended for intermediate developers who are looking to grow their knowledge of Python. If that sounds like you, then 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-power-of-decorators-get-free&quot; data-focus=&quot;false&quot;&gt;Get our free &quot;The Power of Python Decorators&quot; guide&lt;/a&gt; that shows you 3 advanced decorator patterns and techniques you can use to write to cleaner and more Pythonic programs.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;adding-a-python-sleep-call-with-timesleep&quot;&gt;Adding a Python &lt;code&gt;sleep()&lt;/code&gt; Call With &lt;code&gt;time.sleep()&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Python has built-in support for putting your program to sleep. The &lt;code&gt;time&lt;/code&gt; module has a function &lt;a href=&quot;https://docs.python.org/3/library/time.html#time.sleep&quot;&gt;&lt;code&gt;sleep()&lt;/code&gt;&lt;/a&gt; that you can use to suspend execution of the calling thread for however many seconds you specify.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example of how to use &lt;code&gt;time.sleep()&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;time&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;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;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# Sleep for 3 seconds&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you run this code in your console, then you should experience a delay before you can enter a new statement in the REPL.&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 3.5, the core developers changed the behavior of &lt;code&gt;time.sleep()&lt;/code&gt; slightly. The new Python &lt;code&gt;sleep()&lt;/code&gt; system call will last at least the number of seconds you&amp;rsquo;ve specified, even if the sleep is interrupted by a signal. This does not apply if the signal itself raises an exception, however.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can test how long the sleep lasts by using Python&amp;rsquo;s &lt;a href=&quot;https://docs.python.org/3/library/timeit.html&quot;&gt;&lt;code&gt;timeit&lt;/code&gt;&lt;/a&gt; module:&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 -m timeit -n &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;import time; time.sleep(3)&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3 loops, best of 3: 3 sec per loop&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you run the &lt;code&gt;timeit&lt;/code&gt; module with the &lt;code&gt;-n&lt;/code&gt; parameter, which tells &lt;code&gt;timeit&lt;/code&gt; how many times to run the statement that follows. You can see that &lt;code&gt;timeit&lt;/code&gt; ran the statement 3 times and that the best run time was 3 seconds, which is what was expected.&lt;/p&gt;
&lt;p&gt;The default number of times that &lt;code&gt;timeit&lt;/code&gt; will run your code is one million. If you were to run the above code with the default &lt;code&gt;-n&lt;/code&gt;, then at 3 seconds per iteration, your terminal would hang for approximately 34 days! The &lt;code&gt;timeit&lt;/code&gt; module has several other command line options that you can check out in its &lt;a href=&quot;https://docs.python.org/3/library/timeit.html#timeit-command-line-interface&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s create something a bit more realistic. A system administrator needs to know when one of their websites goes down. You want to be able to check the website&amp;rsquo;s status code regularly, but you can&amp;rsquo;t query the web server constantly or it will affect performance. One way to do this check is to use a Python &lt;code&gt;sleep()&lt;/code&gt; system call:&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;time&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;urllib.request&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;urllib.error&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;uptime_bot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&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;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;conn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;urlopen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&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;n&quot;&gt;urllib&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HTTPError&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;# Email admin / log&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;HTTPError: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{e.code}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; for &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{url}&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;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;URLError&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;# Email admin / log&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;URLError: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{e.code}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; for &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{url}&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;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Website is up&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;{url}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; is up&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;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&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;s1&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://www.google.com/py&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;uptime_bot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here you create &lt;code&gt;uptime_bot()&lt;/code&gt;, which takes a URL as its argument. The function then attempts to open that URL with &lt;code&gt;urllib&lt;/code&gt;. If there&amp;rsquo;s an &lt;code&gt;HTTPError&lt;/code&gt; or &lt;code&gt;URLError&lt;/code&gt;, then the program catches it and prints out the error. (In a live environment, you would log the error and probably send out an email to the webmaster or system administrator.)&lt;/p&gt;
&lt;p&gt;If no errors occur, then your code prints out that all is well. Regardless of what happens, your program will sleep for 60 seconds. This means that you only access the website once every minute. The URL used in this example is bad, so it will output the following to your console once every minute:&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;HTTPError: 404 for http://www.google.com/py&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Go ahead and update the code to use a known good URL, like &lt;a href=&quot;http://www.google.com&quot;&gt;&lt;code&gt;http://www.google.com&lt;/code&gt;&lt;/a&gt;. Then you can re-run it to see it work successfully. You can also try to update the code to send an email or log the errors. For more information on how to do this, check out &lt;a href=&quot;https://realpython.com/python-send-email/&quot;&gt;Sending Emails With Python&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/python-logging/&quot;&gt;Logging in Python&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;adding-a-python-sleep-call-with-decorators&quot;&gt;Adding a Python &lt;code&gt;sleep()&lt;/code&gt; Call With Decorators&lt;/h2&gt;
&lt;p&gt;There are times when you need to retry a function that has failed. One popular use case for this is when you need to retry a file download because the server was busy. You usually won&amp;rsquo;t want to make a request to the server too often, so adding a Python &lt;code&gt;sleep()&lt;/code&gt; call between each request is desirable.&lt;/p&gt;
&lt;p&gt;Another use case that I&amp;rsquo;ve personally experienced is where I need to check the state of a user interface during an automated test. The user interface might load faster or slower than usual, depending on the computer I&amp;rsquo;m running the test on. This can change what&amp;rsquo;s on the screen at the moment my program is verifying something.&lt;/p&gt;
&lt;p&gt;In this case, I can tell the program to sleep for a moment and then recheck things a second or two later. This can mean the difference between a passing and failing test.&lt;/p&gt;
&lt;p&gt;You can use a &lt;strong&gt;decorator&lt;/strong&gt; to add a Python &lt;code&gt;sleep()&lt;/code&gt; system call in either of these cases. If you&amp;rsquo;re not familiar with decorators, or if you&amp;rsquo;d like to brush up on them, then check out &lt;a href=&quot;https://realpython.com/primer-on-python-decorators/&quot;&gt;Primer on Python Decorators&lt;/a&gt;. Let&amp;rsquo;s look at 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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;time&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;urllib.request&lt;/span&gt;
&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;urllib.error&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;retry&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;the_real_decorator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&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;wrapper&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;n&quot;&gt;retries&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;retries&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;retry&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;value&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;function&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;n&quot;&gt;value&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;p&quot;&gt;:&lt;/span&gt;
                        &lt;span class=&quot;k&quot;&gt;return&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;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Sleeping for &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{timeout}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; seconds&amp;#39;&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;n&quot;&gt;timeout&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;retries&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;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wrapper&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;the_real_decorator&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;sleep()&lt;/code&gt; is your decorator. It accepts a &lt;code&gt;timeout&lt;/code&gt; value and the number of times it should &lt;code&gt;retry&lt;/code&gt;, which defaults to 3. Inside &lt;code&gt;sleep()&lt;/code&gt; is another function, &lt;code&gt;the_real_decorator()&lt;/code&gt;, which accepts the decorated function.&lt;/p&gt;
&lt;p&gt;Finally, the innermost function &lt;code&gt;wrapper()&lt;/code&gt; accepts the arguments and keyword arguments that you pass to the decorated function. This is where the magic happens! You use a &lt;a href=&quot;https://realpython.com/courses/mastering-while-loops/&quot;&gt;&lt;code&gt;while&lt;/code&gt;&lt;/a&gt; loop to retry calling the function. If there&amp;rsquo;s an exception, then you call &lt;code&gt;time.sleep()&lt;/code&gt;, increment the &lt;code&gt;retries&lt;/code&gt; counter, and try running the function again.&lt;/p&gt;
&lt;p&gt;Now rewrite &lt;code&gt;uptime_bot()&lt;/code&gt; to use your new decorator:&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;nd&quot;&gt;@sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;uptime_bot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&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;conn&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;urlopen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&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;n&quot;&gt;urllib&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HTTPError&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;# Email admin / log&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;HTTPError: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{e.code}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; for &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{url}&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;c1&quot;&gt;# Re-raise the exception for the decorator&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HTTPError&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;URLError&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;# Email admin / log&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;URLError: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{e.code}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; for &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{url}&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;c1&quot;&gt;# Re-raise the exception for the decorator&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urllib&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;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;URLError&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;c1&quot;&gt;# Website is up&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;{url}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; is up&amp;#39;&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;s1&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;url&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;http://www.google.com/py&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;uptime_bot&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you decorate &lt;code&gt;uptime_bot()&lt;/code&gt; with a &lt;code&gt;sleep()&lt;/code&gt; of 3 seconds. You&amp;rsquo;ve also removed the original &lt;code&gt;while&lt;/code&gt; loop, as well as the old call to &lt;code&gt;sleep(60)&lt;/code&gt;. The decorator now takes care of this.&lt;/p&gt;
&lt;p&gt;One other change you&amp;rsquo;ve made is to add a &lt;code&gt;raise&lt;/code&gt; inside of the exception handling blocks. This is so that the decorator will work properly. You could write the decorator to handle these errors, but since these exceptions only apply to &lt;code&gt;urllib&lt;/code&gt;, you might be better off keeping the decorator the way it is. That way, it will work with a wider variety of functions.&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&amp;rsquo;d like to brush up on exception handling in Python, then check out &lt;a href=&quot;https://realpython.com/python-exceptions/&quot;&gt;Python Exceptions: An Introduction&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;There are a few improvements that you could make to your decorator. If it runs out of retries and still fails, then you could have it re-raise the last error. The decorator will also wait 3 seconds after the last failure, which might be something you don&amp;rsquo;t want to happen. Feel free to try these out as an exercise!&lt;/p&gt;
&lt;h2 id=&quot;adding-a-python-sleep-call-with-threads&quot;&gt;Adding a Python &lt;code&gt;sleep()&lt;/code&gt; Call With Threads&lt;/h2&gt;
&lt;p&gt;There are also times when you might want to add a Python &lt;code&gt;sleep()&lt;/code&gt; call to a &lt;strong&gt;thread&lt;/strong&gt;. Perhaps you&amp;rsquo;re running a migration script against a database with millions of records in production. You don&amp;rsquo;t want to cause any downtime, but you also don&amp;rsquo;t want to wait longer than necessary to finish the migration, so you decide to use threads.&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; Threads are a method of doing &lt;a href=&quot;https://realpython.com/python-concurrency/&quot;&gt;concurrency&lt;/a&gt; in Python. You can run multiple threads at once to increase your application&amp;rsquo;s throughput. If you&amp;rsquo;re not familiar with threads in Python, then 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;To prevent customers from noticing any kind of slowdown, each thread needs to run for a short period and then sleep. There are two ways to do this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use &lt;code&gt;time.sleep()&lt;/code&gt; as before.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Event.wait()&lt;/code&gt; from the &lt;code&gt;threading&lt;/code&gt; module.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s start by looking at &lt;code&gt;time.sleep()&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;using-timesleep&quot;&gt;Using &lt;code&gt;time.sleep()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The Python &lt;a href=&quot;https://docs.python.org/3/howto/logging-cookbook.html#logging-from-multiple-threads&quot;&gt;Logging Cookbook&lt;/a&gt; shows a nice example that uses &lt;code&gt;time.sleep()&lt;/code&gt;. Python&amp;rsquo;s &lt;code&gt;logging&lt;/code&gt; module is thread-safe, so it&amp;rsquo;s a bit more useful than &lt;code&gt;print()&lt;/code&gt; statements for this exercise. The following code is based on this 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;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;threading&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;worker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arg&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;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;stop&amp;quot;&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;s2&quot;&gt;&amp;quot;worker thread checking in&amp;quot;&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;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;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;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;DEBUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%(relativeCreated)6d&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%(threadName)s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%(message)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;info&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;stop&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread&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;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worker&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;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;n&quot;&gt;thread_two&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;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worker&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;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;n&quot;&gt;thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread_two&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&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;k&quot;&gt;try&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;s2&quot;&gt;&amp;quot;Checking in from main thread&amp;quot;&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;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;mf&quot;&gt;0.75&lt;/span&gt;&lt;span class=&quot;p&quot;&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;KeyboardInterrupt&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;s2&quot;&gt;&amp;quot;stop&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;kc&quot;&gt;True&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;s1&quot;&gt;&amp;#39;Stopping&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread&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;thread_two&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;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;Here, you use Python&amp;rsquo;s &lt;code&gt;threading&lt;/code&gt; module to create two threads. You also create a logging object that will log the &lt;code&gt;threadName&lt;/code&gt; to stdout. Next, you start both threads and initiate a loop to log from the main thread every so often. You use &lt;code&gt;KeyboardInterrupt&lt;/code&gt; to catch the user pressing &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;Try running the code above in your terminal. You should see output similar to 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; 0 Thread-1 worker thread checking in&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; 1 Thread-2 worker thread checking in&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; 1 MainThread Checking in from main thread&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;752 MainThread Checking in from main thread&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1001 Thread-1 worker thread checking in&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1001 Thread-2 worker thread checking in&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;1502 MainThread Checking in from main thread&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2003 Thread-1 worker thread checking in&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2003 Thread-2 worker thread checking in&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;2253 MainThread Checking in from main thread&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3005 Thread-1 worker thread checking in&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3005 MainThread Checking in from main thread&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3005 Thread-2 worker thread checking in&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As each thread runs and then sleeps, the logging output is printed to the console. Now that you&amp;rsquo;ve tried an example, you&amp;rsquo;ll be able to use these concepts in your own code.&lt;/p&gt;
&lt;h3 id=&quot;using-eventwait&quot;&gt;Using &lt;code&gt;Event.wait()&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;threading&lt;/code&gt; module provides an &lt;code&gt;Event()&lt;/code&gt; that you can use like &lt;code&gt;time.sleep()&lt;/code&gt;. However, &lt;code&gt;Event()&lt;/code&gt; has the added benefit of being more responsive. The reason for this is that when the event is set, the program will break out of the loop immediately. With &lt;code&gt;time.sleep()&lt;/code&gt;, your code will need to wait for the Python &lt;code&gt;sleep()&lt;/code&gt; call to finish before the thread can exit.&lt;/p&gt;
&lt;p&gt;The reason you&amp;rsquo;d want to use &lt;code&gt;wait()&lt;/code&gt; here is because &lt;code&gt;wait()&lt;/code&gt; is &lt;strong&gt;non-blocking&lt;/strong&gt;, whereas &lt;code&gt;time.sleep()&lt;/code&gt; is &lt;strong&gt;blocking&lt;/strong&gt;. What this means is that when you use &lt;code&gt;time.sleep()&lt;/code&gt;, you&amp;rsquo;ll block the main thread from continuing to run while it waits for the &lt;code&gt;sleep()&lt;/code&gt; call to end. &lt;code&gt;wait()&lt;/code&gt; solves this problem. You can read more about how all this works in Python&amp;rsquo;s &lt;a href=&quot;https://docs.python.org/3/library/threading.html#event-objects&quot;&gt;threading documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how you add a Python &lt;code&gt;sleep()&lt;/code&gt; call with &lt;code&gt;Event.wait()&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;logging&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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;worker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&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;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isSet&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;s2&quot;&gt;&amp;quot;worker thread checking in&amp;quot;&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;event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;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;DEBUG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%(relativeCreated)6d&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%(threadName)s&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%(message)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;hll&quot;&gt;    &lt;span class=&quot;n&quot;&gt;event&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;Event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread&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;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worker&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread_two&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;Thread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;target&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;worker&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;thread_two&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&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;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isSet&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;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;s2&quot;&gt;&amp;quot;Checking in from main thread&amp;quot;&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;event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wait&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;0.75&lt;/span&gt;&lt;span class=&quot;p&quot;&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;KeyboardInterrupt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;

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

&lt;p&gt;In this example, you create &lt;code&gt;threading.Event()&lt;/code&gt; and pass it to &lt;code&gt;worker()&lt;/code&gt;. (Recall that in the previous example, you instead passed a dictionary.) Next, you set up your loops to check whether or not &lt;code&gt;event&lt;/code&gt; is set. If it&amp;rsquo;s not, then your code prints a message and waits a bit before checking again. To set the event, you can press &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt;. Once the event is set, &lt;code&gt;worker()&lt;/code&gt; will return and the loop will break, ending the program.&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&amp;rsquo;d like to learn more about dictionaries, then check out &lt;a href=&quot;https://realpython.com/courses/dictionaries-python/&quot;&gt;Dictionaries in Python&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Take a closer look at the code block above. How would you pass in a different sleep time to each worker thread? Can you figure it out? Feel free to tackle this exercise on your own!&lt;/p&gt;
&lt;h2 id=&quot;adding-a-python-sleep-call-with-async-io&quot;&gt;Adding a Python &lt;code&gt;sleep()&lt;/code&gt; Call With Async IO&lt;/h2&gt;
&lt;p&gt;Asynchronous capabilities were added to Python in the 3.4 release, and this feature set has been aggressively expanding ever since. &lt;strong&gt;Asynchronous programming&lt;/strong&gt; is a type of parallel programming that allows you to run multiple tasks at once. When a task finishes, it will notify the main thread.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;asyncio&lt;/code&gt; is a module that lets you add a Python &lt;code&gt;sleep()&lt;/code&gt; call asynchronously. If you&amp;rsquo;re unfamiliar with Python&amp;rsquo;s implementation of asynchronous programming, then check out &lt;a href=&quot;https://realpython.com/async-io-python/&quot;&gt;Async IO in Python: A Complete Walkthrough&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/learning-paths/python-concurrency-parallel-programming/&quot;&gt;Python Concurrency &amp;amp; Parallel Programming&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s an example from Python&amp;rsquo;s own &lt;a href=&quot;https://docs.python.org/3/library/asyncio.html&quot;&gt;documentation&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;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;asyncio&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello ...&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;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asyncio&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;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;... World!&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Python 3.7+&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;asyncio&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;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you run &lt;code&gt;main()&lt;/code&gt; and have it sleep for one second between two &lt;code&gt;print()&lt;/code&gt; calls.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a more compelling example from the &lt;a href=&quot;https://docs.python.org/3/library/asyncio-task.html&quot;&gt;Coroutines and Tasks&lt;/a&gt; portion of the &lt;code&gt;asyncio&lt;/code&gt; documentation:&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;asyncio&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;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;text&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;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asyncio&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;n&quot;&gt;sleep&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;():&lt;/span&gt;
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Started: {time.strftime(&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%X&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;#39;)}&amp;quot;&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;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&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;First&amp;#39;&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;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&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;Second&amp;#39;&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;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;output&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;Third&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Ended: {time.strftime(&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%X&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;#39;)}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Python 3.7+&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;asyncio&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;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this code, you create a worker called &lt;code&gt;output()&lt;/code&gt; that takes in the number of seconds to &lt;code&gt;sleep&lt;/code&gt; and the &lt;code&gt;text&lt;/code&gt; to print out. Then, you use Python&amp;rsquo;s &lt;code&gt;await&lt;/code&gt; keyword to wait for the &lt;code&gt;output()&lt;/code&gt; code to run. &lt;code&gt;await&lt;/code&gt; is required here because &lt;code&gt;output()&lt;/code&gt; has been marked as an &lt;code&gt;async&lt;/code&gt; function, so you can&amp;rsquo;t call it like you would a normal function.&lt;/p&gt;
&lt;p&gt;When you run this code, your program will execute &lt;code&gt;await&lt;/code&gt; 3 times. The code will wait for 1, 2, and 3 seconds, for a total wait time of 6 seconds. You can also rewrite the code so that the tasks run in parallel:&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;asyncio&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;k&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;output&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;p&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;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sleep&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;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;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asyncio&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;1&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;s1&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{text}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; counter: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{sleep}&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt; seconds&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;sleep&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;async&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;task_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asyncio&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;task_2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asyncio&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Second&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;n&quot;&gt;task_3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;asyncio&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;create_task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Third&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;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;Started: {time.strftime(&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%X&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;#39;)}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;task_1&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;task_2&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;task_3&lt;/span&gt;                                 
    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Ended: {time.strftime(&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;%X&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;#39;)}&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;s1&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;asyncio&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;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;Now you&amp;rsquo;re using the concept of &lt;strong&gt;tasks&lt;/strong&gt;, which you can make with &lt;code&gt;create_task()&lt;/code&gt;.  When you use tasks in &lt;code&gt;asyncio&lt;/code&gt;, Python will run the tasks asynchronously. So, when you run the code above, it should finish in 3 seconds total instead of 6.&lt;/p&gt;
&lt;h2 id=&quot;adding-a-python-sleep-call-with-guis&quot;&gt;Adding a Python &lt;code&gt;sleep()&lt;/code&gt; Call With GUIs&lt;/h2&gt;
&lt;p&gt;Command-line applications aren&amp;rsquo;t the only place where you might need to add Python &lt;code&gt;sleep()&lt;/code&gt; calls. When you create a &lt;strong&gt;Graphical User Interface (GUI)&lt;/strong&gt;, you&amp;rsquo;ll occasionally need to add delays. For example, you might create an FTP application to download millions of files, but you need to add a &lt;code&gt;sleep()&lt;/code&gt; call between batches so you don&amp;rsquo;t bog down the server.&lt;/p&gt;
&lt;p&gt;GUI code will run all its processing and drawing in a main thread called the &lt;strong&gt;event loop&lt;/strong&gt;. If you use &lt;code&gt;time.sleep()&lt;/code&gt; inside of GUI code, then you&amp;rsquo;ll block its event loop. From the user&amp;rsquo;s perspective, the application could appear to freeze. The user won&amp;rsquo;t be able to interact with your application while it&amp;rsquo;s sleeping with this method. (On Windows, you might even get an alert about how your application is now unresponsive.)&lt;/p&gt;
&lt;p&gt;Fortunately, there are other methods you can use besides &lt;code&gt;time.sleep()&lt;/code&gt;. In the next few sections, you&amp;rsquo;ll learn how to add Python &lt;code&gt;sleep()&lt;/code&gt; calls in both Tkinter and wxPython.&lt;/p&gt;
&lt;h3 id=&quot;sleeping-in-tkinter&quot;&gt;Sleeping in Tkinter&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.python.org/3/library/tk.html&quot;&gt;&lt;code&gt;tkinter&lt;/code&gt;&lt;/a&gt; is a part of the Python standard library. It may not be available to you if you&amp;rsquo;re using a pre-installed version of Python on Linux or Mac. If you get an &lt;code&gt;ImportError&lt;/code&gt;, then you&amp;rsquo;ll need to look into how to add it to your system. But if you &lt;a href=&quot;https://realpython.com/courses/installing-python-windows-macos-linux/&quot;&gt;install Python yourself&lt;/a&gt;, then &lt;code&gt;tkinter&lt;/code&gt; should already be available.&lt;/p&gt;
&lt;p&gt;You&amp;rsquo;ll start by looking at an example that uses &lt;code&gt;time.sleep()&lt;/code&gt;. Run this code to see what happens when you add a Python &lt;code&gt;sleep()&lt;/code&gt; call the wrong way:&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;tkinter&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyApp&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;parent&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;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;bp&quot;&gt;self&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;geometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;400x400&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;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tkinter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&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;frame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pack&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tkinter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Button&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;s2&quot;&gt;&amp;quot;click me&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;command&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;delayed&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pack&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;delayed&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;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;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&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;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tkinter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Tk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyApp&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;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;mainloop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once you&amp;rsquo;ve run the code, press the button in your GUI. The button will stick down for three seconds as it waits for &lt;code&gt;sleep()&lt;/code&gt; to finish. If the application had other buttons, then you wouldn&amp;rsquo;t be able to click them. You can&amp;rsquo;t close the application while it&amp;rsquo;s sleeping, either, since it can&amp;rsquo;t respond to the close event.&lt;/p&gt;
&lt;p&gt;To get &lt;code&gt;tkinter&lt;/code&gt; to sleep properly, you&amp;rsquo;ll need to use &lt;code&gt;after()&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;tkinter&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyApp&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;parent&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;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;bp&quot;&gt;self&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;geometry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;400x400&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;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tkinter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Frame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parent&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;frame&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pack&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;root&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;after&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3000&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;delayed&lt;/span&gt;&lt;span class=&quot;p&quot;&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;delayed&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;s1&quot;&gt;&amp;#39;I was delayed&amp;#39;&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;root&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;tkinter&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Tk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyApp&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;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;mainloop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here you create an application that is 400 pixels wide by 400 pixels tall. It has no widgets on it. All it will do is show a frame. Then, you call &lt;code&gt;self.root.after()&lt;/code&gt; where &lt;code&gt;self.root&lt;/code&gt; is a reference to the &lt;code&gt;Tk()&lt;/code&gt; object. &lt;code&gt;after()&lt;/code&gt; takes two arguments:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The number of milliseconds to sleep&lt;/li&gt;
&lt;li&gt;The method to call when the sleep is finished&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In this case, your application will print a string to stdout after 3 seconds. You can think of &lt;code&gt;after()&lt;/code&gt; as the &lt;code&gt;tkinter&lt;/code&gt; version of &lt;code&gt;time.sleep()&lt;/code&gt;, but it also adds the ability to call a function after the sleep has finished.&lt;/p&gt;
&lt;p&gt;You could use this functionality to improve user experience. By adding a Python &lt;code&gt;sleep()&lt;/code&gt; call, you can make the application appear to load faster and then start some longer-running process after it&amp;rsquo;s up. That way, the user won&amp;rsquo;t have to wait for the application to open.&lt;/p&gt;
&lt;h3 id=&quot;sleeping-in-wxpython&quot;&gt;Sleeping in wxPython&lt;/h3&gt;
&lt;p&gt;There are two major differences between wxPython and Tkinter:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;wxPython has many more widgets.&lt;/li&gt;
&lt;li&gt;wxPython aims to look and feel native on all platforms.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The wxPython framework is not included with Python, so you&amp;rsquo;ll need to install it yourself. If you&amp;rsquo;re not familiar with wxPython, then check out &lt;a href=&quot;https://realpython.com/python-gui-with-wxpython/&quot;&gt;How to Build a Python GUI Application With wxPython&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In wxPython, you can use &lt;code&gt;wx.CallLater()&lt;/code&gt; to add a Python &lt;code&gt;sleep()&lt;/code&gt; call:&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;wx&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;MyFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;wx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Frame&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;nb&quot;&gt;super&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;parent&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;n&quot;&gt;title&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s1&quot;&gt;&amp;#39;Hello World&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;wx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CallLater&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;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delayed&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;Show&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;delayed&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;s1&quot;&gt;&amp;#39;I was delayed&amp;#39;&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;s1&quot;&gt;&amp;#39;__main__&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;wx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;App&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;frame&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MyFrame&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;app&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MainLoop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you subclass &lt;code&gt;wx.Frame&lt;/code&gt; directly and then call &lt;code&gt;wx.CallLater()&lt;/code&gt;. This function takes the same parameters as Tkinter&amp;rsquo;s &lt;code&gt;after()&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The number of milliseconds to sleep&lt;/li&gt;
&lt;li&gt;The method to call when the sleep is finished&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When you run this code, you should see a small blank window appear without any widgets. After 4 seconds, you&amp;rsquo;ll see the string &lt;code&gt;&#39;I was delayed&#39;&lt;/code&gt; printed to stdout.&lt;/p&gt;
&lt;p&gt;One of the benefits of using &lt;code&gt;wx.CallLater()&lt;/code&gt; is that it&amp;rsquo;s thread-safe. You can use this method from within a thread to call a function that&amp;rsquo;s in the main wxPython application.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;With this tutorial, you&amp;rsquo;ve gained a valuable new technique to add to your Python toolbox! You know how to add delays to pace your applications and prevent them from using up system resources. You can even use Python &lt;code&gt;sleep()&lt;/code&gt; calls to help your GUI code redraw more effectively. This will make the user experience much better for your customers!&lt;/p&gt;
&lt;p&gt;To recap, you&amp;rsquo;ve learned how to add Python &lt;code&gt;sleep()&lt;/code&gt; calls with the following tools:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;time.sleep()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Decorators&lt;/li&gt;
&lt;li&gt;Threads&lt;/li&gt;
&lt;li&gt;&lt;code&gt;asyncio&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Tkinter&lt;/li&gt;
&lt;li&gt;wxPython&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you can take what you&amp;rsquo;ve learned and start putting your code to sleep!&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>The Python range() Function</title>
      <id>https://realpython.com/courses/python-range-function/</id>
      <link href="https://realpython.com/courses/python-range-function/"/>
      <updated>2019-10-15T14:00:00+00:00</updated>
      <summary>In this step-by-step course, you&#39;ll master the Python range() function, learn how its implementation differs in Python 3 vs 2, and see how you can use it to write faster and more Pythonic code.</summary>
      <content type="html">
        &lt;p&gt;Python&amp;rsquo;s built-in &lt;strong&gt;&lt;code&gt;range&lt;/code&gt;&lt;/strong&gt; function is handy when you need to perform an action a specific number of times. As an experienced Pythonista, you&amp;rsquo;ve most likely used it before. But what does it do?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;By the end of this course, you&amp;rsquo;ll:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Understand how the Python &lt;code&gt;range&lt;/code&gt; function works&lt;/li&gt;
&lt;li&gt;Know how the implementations differ in Python 2 and Python 3&lt;/li&gt;
&lt;li&gt;Have seen a number of hands-on &lt;code&gt;range()&lt;/code&gt; examples&lt;/li&gt;
&lt;li&gt;Be equipped to work around some of its limitations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Let&amp;rsquo;s get cracking!&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>Cool New Features in Python 3.8</title>
      <id>https://realpython.com/python38-new-features/</id>
      <link href="https://realpython.com/python38-new-features/"/>
      <updated>2019-10-14T14:00:00+00:00</updated>
      <summary>What does Python 3.8 bring to the table? Learn about some of the biggest changes and see you how you can best make use of them.</summary>
      <content type="html">
        &lt;p&gt;The &lt;a href=&quot;https://www.python.org/downloads/release/python-380/&quot;&gt;newest version of Python is released&lt;/a&gt;! Python 3.8 has been available in beta versions since the summer, but on &lt;a href=&quot;https://www.python.org/dev/peps/pep-0569/&quot;&gt;October 14th, 2019&lt;/a&gt; the first official version is ready. Now, we can all start playing with the new features and benefit from the latest improvements.&lt;/p&gt;
&lt;p&gt;What does Python 3.8 bring to the table? The &lt;a href=&quot;https://docs.python.org/3.8/whatsnew/3.8.html&quot;&gt;documentation&lt;/a&gt; gives a good overview of the new features. However, this article will go more in depth on some of the biggest changes, and show you how you can take advantage of Python 3.8.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this article, you&amp;rsquo;ll learn about:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using assignment expressions to simplify some code constructs&lt;/li&gt;
&lt;li&gt;Enforcing positional-only arguments in your own functions&lt;/li&gt;
&lt;li&gt;Specifying more precise type hints&lt;/li&gt;
&lt;li&gt;Using f-strings for simpler debugging&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With a few exceptions, Python 3.8 contains many small improvements over the earlier versions. Towards the end of the article, you&amp;rsquo;ll see many of these less attention-grabbing changes, as well as a discussion about some of the optimizations that make Python 3.8 faster than its predecessors. Finally, you&amp;rsquo;ll get some advice about upgrading to the new version.&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;the-walrus-in-the-room-assignment-expressions&quot;&gt;The Walrus in the Room: Assignment Expressions&lt;/h2&gt;
&lt;p&gt;The biggest change in Python 3.8 is the introduction of &lt;strong&gt;assignment expressions&lt;/strong&gt;. They are written using a new notation (&lt;code&gt;:=&lt;/code&gt;). This operator is often called the &lt;strong&gt;walrus operator&lt;/strong&gt; as it resembles the eyes and tusks of a walrus on its side.&lt;/p&gt;
&lt;p&gt;Assignment expressions allow you to assign and return a value in the same expression. For example, if you want to assign to a variable and print its value, then you typically 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;n&quot;&gt;walrus&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;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;walrus&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;In Python 3.8, you&amp;rsquo;re allowed to combine these two statements into one, using the walrus operator:&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;n&quot;&gt;walrus&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;True&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;The assignment expression allows you to assign &lt;code&gt;True&lt;/code&gt; to &lt;code&gt;walrus&lt;/code&gt;, and immediately print the value. But keep in mind that the walrus operator does &lt;em&gt;not&lt;/em&gt; do anything that isn&amp;rsquo;t possible without it. It only makes certain constructs more convenient, and can sometimes communicate the intent of your code more clearly.&lt;/p&gt;
&lt;p&gt;One pattern that shows some of the strengths of the walrus operator is &lt;code&gt;while&lt;/code&gt; loops where you need to initialize and update a variable. For example, the following code asks the user for input until they type &lt;code&gt;quit&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;inputs&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;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&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;Write something: &amp;quot;&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;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;quit&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inputs&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;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;current&lt;/span&gt; &lt;span class=&quot;o&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;Write something: &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 is less than ideal. You&amp;rsquo;re repeating the &lt;code&gt;input()&lt;/code&gt; statement, and somehow you need to add &lt;code&gt;current&lt;/code&gt; to the list &lt;em&gt;before&lt;/em&gt; asking the user for it. A better solution is to set up an infinite &lt;code&gt;while&lt;/code&gt; loop, and use &lt;code&gt;break&lt;/code&gt; to stop the loop:&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;inputs&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;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;current&lt;/span&gt; &lt;span class=&quot;o&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;Write something: &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;current&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;quit&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inputs&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;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This code is equivalent to the one above, but avoids the repetition and somehow keeps the lines in a more logical order. If you use an assignment expression, you can simplify this loop further:&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;inputs&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;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;current&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;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Write something: &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;s2&quot;&gt;&amp;quot;quit&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;inputs&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;current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This moves the test back to the &lt;code&gt;while&lt;/code&gt; line, where it should be. However, there are now several things happening at that line, so it takes a bit more effort to read it properly. Use your best judgement about when the walrus operator helps make your code more readable.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0572/&quot;&gt;PEP 572&lt;/a&gt; describes all the details of assignment expressions, including some of the rationale for introducing them into the language, as well as &lt;a href=&quot;https://www.python.org/dev/peps/pep-0572/#examples&quot;&gt;several examples&lt;/a&gt; of how the walrus operator can be used.&lt;/p&gt;
&lt;h2 id=&quot;positional-only-arguments&quot;&gt;Positional-Only Arguments&lt;/h2&gt;
&lt;p&gt;The built-in function &lt;code&gt;float()&lt;/code&gt; can be used for converting text strings and numbers to &lt;code&gt;float&lt;/code&gt; objects. Consider the following 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;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3.8&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;help&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;class float(object)&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;go&quot;&gt; |  float(x=0, /)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt; |  &lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; |  Convert a string or number to a floating point number, if possible.&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;[...]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Look closely at the signature of &lt;code&gt;float()&lt;/code&gt;. Notice the slash (&lt;code&gt;/&lt;/code&gt;) after the parameter. What does it mean?&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; For an in-depth discussion on the &lt;code&gt;/&lt;/code&gt; notation, see &lt;a href=&quot;https://www.python.org/dev/peps/pep-0457/&quot;&gt;PEP 457 - Notation for Positional-Only Parameters&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;It turns out that while the one parameter of &lt;code&gt;float()&lt;/code&gt; is called &lt;code&gt;x&lt;/code&gt;, you&amp;rsquo;re not allowed to use its 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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;float&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;s2&quot;&gt;&amp;quot;3.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;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;float() takes no keyword arguments&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When using &lt;code&gt;float()&lt;/code&gt; you&amp;rsquo;re only allowed to specify arguments by position, not by keyword. Before Python 3.8, such &lt;strong&gt;positional-only&lt;/strong&gt; arguments were only possible for built-in functions. There was no easy way to specify that arguments should be positional-only in your own functions:&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;incr&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;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;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;incr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;3.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4.8&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incr&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;mf&quot;&gt;3.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4.8&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;s possible to &lt;a href=&quot;https://github.com/python/cpython/blob/3.7/Lib/collections/__init__.py#L1000&quot;&gt;simulate&lt;/a&gt; positional-only arguments &lt;a href=&quot;https://realpython.com/python-kwargs-and-args/&quot;&gt;using &lt;code&gt;*args&lt;/code&gt;&lt;/a&gt;, but this is less flexible, less readable, and forces you to implement your own argument parsing. In Python 3.8, you can use &lt;code&gt;/&lt;/code&gt; to denote that all arguments before it must be specified by position. You can rewrite &lt;code&gt;incr()&lt;/code&gt; to only accept positional arguments:&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;incr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;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;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;incr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;3.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4.8&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;incr&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;mf&quot;&gt;3.8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;incr() got some positional-only arguments passed as&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           keyword arguments: &amp;#39;x&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By adding &lt;code&gt;/&lt;/code&gt; after &lt;code&gt;x&lt;/code&gt;, you specify that &lt;code&gt;x&lt;/code&gt; is a positional-only argument. You can combine regular arguments with positional-only ones by placing the regular arguments after the slash:&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;greet&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;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hello&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{greeting}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{name}&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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;greet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Łukasz&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Hello, Łukasz&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;greet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Łukasz&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Awesome job&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Awesome job, Łukasz&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;greet&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;s2&quot;&gt;&amp;quot;Łukasz&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;greeting&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Awesome job&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;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;greet() got some positional-only arguments passed as&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           keyword arguments: &amp;#39;name&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In &lt;code&gt;greet()&lt;/code&gt;, the slash is placed between &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;greeting&lt;/code&gt;. This means that &lt;code&gt;name&lt;/code&gt; is a positional-only argument, while &lt;code&gt;greeting&lt;/code&gt; is a regular argument that can be passed either by position or by keyword.&lt;/p&gt;
&lt;p&gt;At first glance, positional-only arguments can seem a bit limiting and contrary to Python&amp;rsquo;s mantra about the importance of readability. You will probably find that there are not a lot of occasions where positional-only arguments improve your code. &lt;/p&gt;
&lt;p&gt;However, in the right circumstances, positional-only arguments can give you some flexibility when you&amp;rsquo;re designing functions. First, positional-only arguments make sense when you have arguments that have a natural order but  are hard to give good, descriptive names to.&lt;/p&gt;
&lt;p&gt;Another possible benefit of using positional-only arguments is that you can more easily refactor your functions. In particular, you can change the name of your parameters without worrying that other code depends on those names.&lt;/p&gt;
&lt;p&gt;Positional-only arguments nicely complement &lt;strong&gt;keyword-only&lt;/strong&gt; arguments. In any version of Python 3, you can specify keyword-only arguments using the star (&lt;code&gt;*&lt;/code&gt;). Any argument &lt;em&gt;after&lt;/em&gt; &lt;code&gt;*&lt;/code&gt; must be specified using a keyword:&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;to_fahrenheit&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;n&quot;&gt;celsius&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;mi&quot;&gt;32&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;celsius&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&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;... &lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_fahrenheit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;to_fahrenheit() takes 0 positional arguments but 1 was given&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_fahrenheit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;celsius&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;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;104.0&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;celsius&lt;/code&gt; is a keyword-only argument, so Python raises an error if you try to specify it based on position, without the keyword.&lt;/p&gt;
&lt;p&gt;You can combine positional-only, regular, and keyword-only arguments, by specifying them in this order separated by &lt;code&gt;/&lt;/code&gt; and &lt;code&gt;*&lt;/code&gt;. In the following example, &lt;code&gt;text&lt;/code&gt; is a positional-only argument, &lt;code&gt;border&lt;/code&gt; is a regular argument with a default value, and &lt;code&gt;width&lt;/code&gt; is a keyword-only argument with a default 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;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;headline&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;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;n&quot;&gt;border&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;o&quot;&gt;*&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;mi&quot;&gt;50&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot; &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{text}&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;center&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;border&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since &lt;code&gt;text&lt;/code&gt; is positional-only, you can&amp;rsquo;t use the keyword &lt;code&gt;text&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;headline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Positional-only Arguments&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;♦♦♦♦♦♦♦♦♦♦♦ Positional-only Arguments ♦♦♦♦♦♦♦♦♦♦♦♦&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;headline&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;s2&quot;&gt;&amp;quot;This doesn&amp;#39;t work!&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;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;headline() got some positional-only arguments passed as&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           keyword arguments: &amp;#39;text&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;border&lt;/code&gt;, on the other hand, can be specified both with and without the keyword:&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;headline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Python 3.8&amp;quot;&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;=================== Python 3.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;n&quot;&gt;headline&lt;/span&gt;&lt;span class=&quot;p&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;border&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;go&quot;&gt;&amp;#39;:::::::::::::::::: Real Python :::::::::::::::::::&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Finally, &lt;code&gt;width&lt;/code&gt; must be specified using the keyword:&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;headline&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;🐍&amp;quot;&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;mi&quot;&gt;38&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍 Python 🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍🐍&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;headline&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;🐍&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;38&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gt&quot;&gt;Traceback (most recent call last):&lt;/span&gt;
  File &lt;span class=&quot;nb&quot;&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;, line &lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;, in &lt;span class=&quot;n&quot;&gt;&amp;lt;module&amp;gt;&lt;/span&gt;
&lt;span class=&quot;gr&quot;&gt;TypeError&lt;/span&gt;: &lt;span class=&quot;n&quot;&gt;headline() takes from 1 to 2 positional arguments&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;           but 3 were given&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can read more about positional-only arguments in &lt;a href=&quot;https://www.python.org/dev/peps/pep-0570/&quot;&gt;PEP 570&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;more-precise-types&quot;&gt;More Precise Types&lt;/h2&gt;
&lt;p&gt;Python&amp;rsquo;s typing system is quite mature at this point. However, in Python 3.8, some new features have been added to &lt;code&gt;typing&lt;/code&gt; to allow more precise typing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Literal types&lt;/li&gt;
&lt;li&gt;Typed dictionaries&lt;/li&gt;
&lt;li&gt;Final objects&lt;/li&gt;
&lt;li&gt;Protocols&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Python supports optional &lt;strong&gt;type hints&lt;/strong&gt;, typically as annotations on your 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;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;double&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;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&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;float&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;number&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you say that &lt;code&gt;number&lt;/code&gt; should be a &lt;code&gt;float&lt;/code&gt; and the &lt;code&gt;double()&lt;/code&gt; function should return a &lt;code&gt;float&lt;/code&gt;, as well. However, Python treats these annotations as &lt;em&gt;hints&lt;/em&gt;. They are not enforced at runtime:&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;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;3.14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;6.28&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;double&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;I&amp;#39;m not a float&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;quot;I&amp;#39;m not a floatI&amp;#39;m not a float&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;double()&lt;/code&gt; happily accepts &lt;code&gt;&quot;I&#39;m not a float&quot;&lt;/code&gt; as an argument, even though that&amp;rsquo;s not a &lt;code&gt;float&lt;/code&gt;. There are &lt;a href=&quot;https://realpython.com/python-type-checking/#using-types-at-runtime&quot;&gt;libraries that can use types at runtime&lt;/a&gt;, but that is not the main use case for Python&amp;rsquo;s type system.&lt;/p&gt;
&lt;p&gt;Instead, type hints allow &lt;a href=&quot;https://realpython.com/python-type-checking/#other-static-type-checkers&quot;&gt;static type checkers&lt;/a&gt; to do type checking of your Python code, without actually running your scripts. This is reminiscent of compilers catching type errors in other languages like &lt;a href=&quot;https://www.java.com&quot;&gt;Java&lt;/a&gt;, &lt;a href=&quot;https://www.rust-lang.org/&quot;&gt;Rust&lt;/a&gt;, and &lt;a href=&quot;https://crystal-lang.org/&quot;&gt;Crystal&lt;/a&gt;. Additionally, type hints act as documentation of your code, making it easier to read, as well as &lt;a href=&quot;https://realpython.com/python-type-checking/#pros-and-cons&quot;&gt;improving auto-complete in your IDE&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; There are several static type checkers available, including &lt;a href=&quot;https://github.com/Microsoft/pyright&quot;&gt;Pyright&lt;/a&gt;, &lt;a href=&quot;https://google.github.io/pytype/&quot;&gt;Pytype&lt;/a&gt;, and &lt;a href=&quot;https://pyre-check.org/&quot;&gt;Pyre&lt;/a&gt;. In this article, you&amp;rsquo;ll use &lt;a href=&quot;http://mypy-lang.org/&quot;&gt;Mypy&lt;/a&gt;. You can install Mypy from &lt;a href=&quot;https://pypi.org/project/mypy/&quot;&gt;PyPI&lt;/a&gt; using &lt;a href=&quot;https://realpython.com/what-is-pip/&quot;&gt;&lt;code&gt;pip&lt;/code&gt;&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; python -m pip install mypy
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In some sense, Mypy is the reference implementation of a type checker for Python, and is being &lt;a href=&quot;http://mypy-lang.org/about.html&quot;&gt;developed at Dropbox&lt;/a&gt; under the lead of Jukka Lehtasalo. Python&amp;rsquo;s creator, Guido van Rossum, is part of the Mypy team.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;You can find more information about type hints in Python in the &lt;a href=&quot;https://www.python.org/dev/peps/pep-0484/&quot;&gt;original PEP 484&lt;/a&gt;, as well as in &lt;a href=&quot;https://realpython.com/python-type-checking/&quot;&gt;Python Type Checking (Guide)&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are four new PEPs about type checking that have been accepted and included in Python 3.8. You&amp;rsquo;ll see short examples from each of these.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.python.org/dev/peps/pep-0586/&quot;&gt;PEP 586&lt;/a&gt; introduce the &lt;strong&gt;&lt;a href=&quot;https://docs.python.org/3.8/library/typing.html#typing.Literal&quot;&gt;&lt;code&gt;Literal&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; type. &lt;code&gt;Literal&lt;/code&gt; is a bit special in that it represents one or several specific values. One use case of &lt;code&gt;Literal&lt;/code&gt; is to be able to precisely add types, when string arguments are used to describe specific behavior. Consider the following 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;c1&quot;&gt;# draw_line.py&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;draw_line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;direction&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;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;direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;horizontal&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;c1&quot;&gt;# Draw horizontal line&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;vertical&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;c1&quot;&gt;# Draw vertical line&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;ValueError&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;invalid direction &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{direction!r}&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;hll&quot;&gt;&lt;span class=&quot;n&quot;&gt;draw_line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;up&amp;quot;&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 program will pass the static type checker, even though &lt;code&gt;&quot;up&quot;&lt;/code&gt; is an invalid direction. The type checker only checks that &lt;code&gt;&quot;up&quot;&lt;/code&gt; is a string. In this case, it would be more precise to say that &lt;code&gt;direction&lt;/code&gt; must be either the literal string &lt;code&gt;&quot;horizontal&quot;&lt;/code&gt; or the literal string &lt;code&gt;&quot;vertical&quot;&lt;/code&gt;. Using &lt;code&gt;Literal&lt;/code&gt;, you can do exactly 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;c1&quot;&gt;# draw_line.py&lt;/span&gt;

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

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;draw_line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;direction&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;horizontal&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;vertical&amp;quot;&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;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;direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;horizontal&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;c1&quot;&gt;# Draw horizontal line&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;direction&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;vertical&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;c1&quot;&gt;# Draw vertical line&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;ValueError&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;invalid direction &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{direction!r}&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;draw_line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;up&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;By exposing the allowed values of &lt;code&gt;direction&lt;/code&gt; to the type checker, you can now be warned about the error:&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; mypy draw_line.py 
&lt;span class=&quot;go&quot;&gt;draw_line.py:15: error:&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    Argument 1 to &amp;quot;draw_line&amp;quot; has incompatible type &amp;quot;Literal[&amp;#39;up&amp;#39;]&amp;quot;;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    expected &amp;quot;Union[Literal[&amp;#39;horizontal&amp;#39;], Literal[&amp;#39;vertical&amp;#39;]]&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;Found 1 error in 1 file (checked 1 source file)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The basic syntax is &lt;code&gt;Literal[&amp;lt;literal&amp;gt;]&lt;/code&gt;. For instance, &lt;code&gt;Literal[38]&lt;/code&gt; represents the literal value 38. You can express one of several literal values using &lt;code&gt;Union&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;Union&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;horizontal&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;vertical&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Since this is a fairly common use case, you can (and probably should) use the simpler notation &lt;code&gt;Literal[&quot;horizontal&quot;, &quot;vertical&quot;]&lt;/code&gt; instead. You already used the latter when adding types to &lt;code&gt;draw_line()&lt;/code&gt;. If you look carefully at the output from Mypy above, you can see that it translated the simpler notation to the &lt;code&gt;Union&lt;/code&gt; notation internally.&lt;/p&gt;
&lt;p&gt;There are cases where the type of the return value of a function depends on the input arguments. One example is &lt;code&gt;open()&lt;/code&gt; which may return a text string or a byte array depending on the value of &lt;code&gt;mode&lt;/code&gt;. This can be handled through &lt;a href=&quot;https://mypy.readthedocs.io/en/latest/more_types.html#function-overloading&quot;&gt;overloading&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The following example shows the skeleton of a calculator that can return the answer either as regular numbers (&lt;code&gt;38&lt;/code&gt;), or as &lt;a href=&quot;http://code.activestate.com/recipes/81611-roman-numerals/&quot;&gt;roman numerals&lt;/a&gt; (&lt;code&gt;XXXVIII&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;# calculator.py&lt;/span&gt;

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

&lt;span class=&quot;n&quot;&gt;ARABIC_TO_ROMAN&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;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;M&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;mi&quot;&gt;900&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CM&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;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;D&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;mi&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CD&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;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;C&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;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;XC&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;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;L&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;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;XL&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;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;X&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;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;IX&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;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;V&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;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;IV&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;I&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;_convert_to_roman_numeral&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;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;str&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;Convert number to a roman numeral string&amp;quot;&amp;quot;&amp;quot;&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;nb&quot;&gt;list&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;arabic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;roman&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ARABIC_TO_ROMAN&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;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;nb&quot;&gt;divmod&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arabic&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;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;roman&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;p&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;result&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&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_1&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;num_2&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;to_roman&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&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;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Union&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;nb&quot;&gt;int&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;Add two numbers&amp;quot;&amp;quot;&amp;quot;&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;num_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_2&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_roman&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;_convert_to_roman_numeral&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;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;result&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The code has the correct type hints: the result of &lt;code&gt;add()&lt;/code&gt; will be either &lt;code&gt;str&lt;/code&gt; or &lt;code&gt;int&lt;/code&gt;. However, often this code will be called with a literal &lt;code&gt;True&lt;/code&gt; or &lt;code&gt;False&lt;/code&gt; as the value of &lt;code&gt;to_roman&lt;/code&gt; in which case you would like the type checker to infer exactly whether &lt;code&gt;str&lt;/code&gt; or &lt;code&gt;int&lt;/code&gt; is returned. This can be done using &lt;code&gt;Literal&lt;/code&gt; together with &lt;code&gt;@overload&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;# calculator.py&lt;/span&gt;

&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;overload&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Union&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;ARABIC_TO_ROMAN&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;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;M&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;mi&quot;&gt;900&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CM&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;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;D&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;mi&quot;&gt;400&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;CD&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;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;C&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;mi&quot;&gt;90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;XC&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;mi&quot;&gt;50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;L&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;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;XL&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;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;X&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;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;IX&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;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;V&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;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;IV&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;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;I&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;_convert_to_roman_numeral&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;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;str&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;Convert number to a roman numeral string&amp;quot;&amp;quot;&amp;quot;&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;nb&quot;&gt;list&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;arabic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;roman&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ARABIC_TO_ROMAN&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;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;nb&quot;&gt;divmod&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;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;arabic&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;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;roman&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;p&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;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@overload&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_1&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;num_2&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;to_roman&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&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;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;o&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nd&quot;&gt;@overload&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_1&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;num_2&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;to_roman&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Literal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;False&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;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;o&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_1&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;num_2&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;to_roman&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;bool&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;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Union&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;nb&quot;&gt;int&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;Add two numbers&amp;quot;&amp;quot;&amp;quot;&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;num_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;num_2&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_roman&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;_convert_to_roman_numeral&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;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;result&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The added &lt;code&gt;@overload&lt;/code&gt; signatures will help your type checker infer &lt;code&gt;str&lt;/code&gt; or &lt;code&gt;int&lt;/code&gt; depending on the literal values of &lt;code&gt;to_roman&lt;/code&gt;. Note that the ellipses (&lt;code&gt;...&lt;/code&gt;) are a literal part of the code. They stand in for the function body in the overloaded signatures.&lt;/p&gt;
&lt;p&gt;As a complement to &lt;code&gt;Literal&lt;/code&gt;, &lt;a href=&quot;https://www.python.org/dev/peps/pep-0591/&quot;&gt;PEP 591&lt;/a&gt; introduces &lt;strong&gt;&lt;a href=&quot;https://docs.python.org/3.8/library/typing.html#typing.Final&quot;&gt;&lt;code&gt;Final&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;. This qualifier specifies that a variable or attribute should not be reassigned, redefined, or overridden. The following is a typing error:&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;typing&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Final&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;Final&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;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;mi&quot;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Mypy will highlight the line &lt;code&gt;ID += 1&lt;/code&gt;, and note that you &lt;code&gt;Cannot assign to final name &quot;ID&quot;&lt;/code&gt;. This gives you a way to ensure that constants in your code never change their value.&lt;/p&gt;
&lt;p&gt;Additionally, there is also a &lt;strong&gt;&lt;a href=&quot;https://docs.python.org/3.8/library/typing.html#typing.final&quot;&gt;&lt;code&gt;@final&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt; decorator that can be applied to classes and methods. Classes &lt;a href=&quot;https://realpython.com/courses/python-decorators-101/&quot;&gt;decorated&lt;/a&gt; with &lt;code&gt;@final&lt;/code&gt; can&amp;rsquo;t be subclassed, while &lt;code&gt;@final&lt;/code&gt; methods can&amp;rsquo;t be overridden by subclasses:&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;typing&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;final&lt;/span&gt;

&lt;span class=&quot;nd&quot;&gt;@final&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Base&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;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Sub&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;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Mypy will flag this example with the error message &lt;code&gt;Cannot inherit from final class &quot;Base&quot;&lt;/code&gt;. To learn more about &lt;code&gt;Final&lt;/code&gt; and &lt;code&gt;@final&lt;/code&gt;, see &lt;a href=&quot;https://www.python.org/dev/peps/pep-0591/&quot;&gt;PEP 591&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The third PEP allowing for more specific type hints is &lt;a href=&quot;https://www.python.org/dev/peps/pep-0589/&quot;&gt;PEP 589&lt;/a&gt;, which introduces &lt;strong&gt;&lt;a href=&quot;https://docs.python.org/3.8/library/typing.html#typing.TypedDict&quot;&gt;&lt;code&gt;TypedDict&lt;/code&gt;&lt;/a&gt;&lt;/strong&gt;. This can be used to specify types for keys and values in a dictionary using a notation that is similar to the typed &lt;a href=&quot;https://docs.python.org/library/typing.html#typing.NamedTuple&quot;&gt;&lt;code&gt;NamedTuple&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Traditionally, dictionaries have been annotated using &lt;a href=&quot;https://docs.python.org/library/typing.html#typing.Dict&quot;&gt;&lt;code&gt;Dict&lt;/code&gt;&lt;/a&gt;. The issue is that this only allowed one type for the keys and one type for the values, often leading to annotations like &lt;code&gt;Dict[str, Any]&lt;/code&gt;. As an example, consider a dictionary that registers information about Python versions:&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;py38&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;version&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;release_year&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2019&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The value corresponding to &lt;code&gt;version&lt;/code&gt; is a string, while &lt;code&gt;release_year&lt;/code&gt; is an integer. This can&amp;rsquo;t be precisely represented using &lt;code&gt;Dict&lt;/code&gt;. With the new &lt;code&gt;TypedDict&lt;/code&gt;, you can do the following:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;TypedDict&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;PythonVersion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TypedDict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;version&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;n&quot;&gt;release_year&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;n&quot;&gt;py38&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PythonVersion&lt;/span&gt;&lt;span class=&quot;p&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;s2&quot;&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;release_year&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2019&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The type checker will then be able to infer that &lt;code&gt;py38[&quot;version&quot;]&lt;/code&gt; has type &lt;code&gt;str&lt;/code&gt;, while &lt;code&gt;py38[&quot;release_year&quot;]&lt;/code&gt; is an &lt;code&gt;int&lt;/code&gt;. At runtime, a &lt;code&gt;TypedDict&lt;/code&gt; is a regular &lt;code&gt;dict&lt;/code&gt;, and type hints are ignored as usual. You can also use &lt;code&gt;TypedDict&lt;/code&gt; purely as an annotation:&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;py38&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PythonVersion&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;version&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;release_year&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2019&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Mypy will let you know if any of your values has the wrong type, or if you use a key that has not been declared. See &lt;a href=&quot;https://www.python.org/dev/peps/pep-0589/&quot;&gt;PEP 589&lt;/a&gt; for more examples.&lt;/p&gt;
&lt;p&gt;Mypy has supported &lt;a href=&quot;https://realpython.com/python-type-checking/#duck-types-and-protocols&quot;&gt;&lt;strong&gt;Protocols&lt;/strong&gt;&lt;/a&gt; for a while already. However, the &lt;a href=&quot;https://mail.python.org/archives/list/typing-sig@python.org/message/FDO4KFYWYQEP3U2HVVBEBR3SXPHQSHYR/&quot;&gt;official acceptance&lt;/a&gt; only happened in May 2019.&lt;/p&gt;
&lt;p&gt;Protocols are a way of formalizing Python&amp;rsquo;s support for duck typing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck. (&lt;a href=&quot;https://en.wikipedia.org/wiki/Duck_test#History&quot;&gt;Source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Duck typing allows you to, for example, read &lt;code&gt;.name&lt;/code&gt; on any object that has a &lt;code&gt;.name&lt;/code&gt; attribute, without really caring about the type of the object. It may seem counter-intuitive for the typing system to support this. Through &lt;a href=&quot;https://en.wikipedia.org/wiki/Structural_type_system&quot;&gt;structural subtyping&lt;/a&gt;, it&amp;rsquo;s still possible to make sense of duck typing.&lt;/p&gt;
&lt;p&gt;You can for instance define a protocol called &lt;code&gt;Named&lt;/code&gt; that can identify all objects with a &lt;code&gt;.name&lt;/code&gt; 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;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;typing&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Protocol&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Named&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Protocol&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;nb&quot;&gt;str&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;greet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Named&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;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;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Hi &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{obj.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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, &lt;code&gt;greet()&lt;/code&gt; takes any object, as long as it defines a &lt;code&gt;.name&lt;/code&gt; attribute. See &lt;a href=&quot;https://www.python.org/dev/peps/pep-0544/&quot;&gt;PEP 544&lt;/a&gt; and &lt;a href=&quot;https://mypy.readthedocs.io/en/latest/protocols.html&quot;&gt;the Mypy documentation&lt;/a&gt; for more information about protocols. &lt;/p&gt;
&lt;h2 id=&quot;simpler-debugging-with-f-strings&quot;&gt;Simpler Debugging With f-Strings&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://realpython.com/python-f-strings/&quot;&gt;f-strings&lt;/a&gt; were introduced in Python 3.6, and have become very popular. They might be the most common reason for Python libraries only being supported on version 3.6 and later. An f-string is a formatted string literal. You can recognize it by the leading &lt;code&gt;f&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;style&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;formatted&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;This is a &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{style}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; string&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;This is a formatted string&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you use f-strings, you can enclose variables and even expressions inside curly braces. They will then be evaluated at runtime and included in the string. You can have several expressions in one f-string:&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;math&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.6&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;A circle with radius &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{r}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt; has area {math.pi * r * r:.2f}&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;A circle with radius 3.6 has area 40.72&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the last expression, &lt;code&gt;{math.pi * r * r:.2f}&lt;/code&gt;, you also use a format specifier. Format specifiers are separated from the expressions with a colon. &lt;/p&gt;
&lt;p&gt;&lt;code&gt;.2f&lt;/code&gt; means that the area is formatted as a floating point number with 2 decimals. The format specifiers are the same as for &lt;a href=&quot;https://docs.python.org/library/stdtypes.html#str.format&quot;&gt;&lt;code&gt;.format()&lt;/code&gt;&lt;/a&gt;. See the &lt;a href=&quot;https://docs.python.org/library/string.html#format-specification-mini-language&quot;&gt;official documentation&lt;/a&gt; for a full list of allowed format specifiers.&lt;/p&gt;
&lt;p&gt;In Python 3.8, you can use assignment expressions inside f-strings. Just make sure to surround the assignment expression with parentheses:&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;math&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.8&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Diameter {(diam := 2 * r)} gives circumference {math.pi * diam:.2f}&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;Diameter 7.6 gives circumference 23.88&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;However, the real f-news in Python 3.8 is the new debugging specifier. You can now add &lt;code&gt;=&lt;/code&gt; at the end of an expression, and it will print both the expression and its 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;n&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.8&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;{python=}&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;python=3.8&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is a short-hand, that typically will be most useful when working interactively or adding print statements to debug your script. In earlier versions of Python, you needed to spell out the variable or expression twice to get the same information:&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;python&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mf&quot;&gt;3.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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;python=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{python}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;python=3.7&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can add spaces around &lt;code&gt;=&lt;/code&gt;, and use format specifiers as usual:&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;name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Eric&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;{name = }&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;quot;name = &amp;#39;Eric&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;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;{name = :&amp;gt;10}&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;name =       Eric&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;&amp;gt;10&lt;/code&gt; format specifier says that &lt;code&gt;name&lt;/code&gt; should be right-aligned within a 10 character string. &lt;code&gt;=&lt;/code&gt; works for more complex expressions 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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;{name.upper()[::-1] = }&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;quot;name.upper()[::-1] = &amp;#39;CIRE&amp;#39;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;For more information about f-strings, see &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;h2 id=&quot;the-python-steering-council&quot;&gt;The Python Steering Council&lt;/h2&gt;
&lt;p&gt;Technically, &lt;a href=&quot;https://www.python.org/dev/peps/pep-0013/&quot;&gt;Python&amp;rsquo;s &lt;strong&gt;governance&lt;/strong&gt;&lt;/a&gt; is not a language feature. However, Python 3.8 is the first version of Python not developed under the &lt;strong&gt;benevolent dictatorship&lt;/strong&gt; of &lt;a href=&quot;https://gvanrossum.github.io/&quot;&gt;Guido van Rossum&lt;/a&gt;. The Python language is now governed by a &lt;strong&gt;steering council&lt;/strong&gt; consisting of five core developers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/pumpichank&quot;&gt;Barry Warsaw&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/brettsky&quot;&gt;Brett Cannon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/WillingCarol&quot;&gt;Carol Willing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/gvanrossum&quot;&gt;Guido van Rossum&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twitter.com/ncoghlan_dev&quot;&gt;Nick Coghlan&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The road to the new governance model for Python was an interesting study in self-organization. Guido van Rossum created Python in the early 1990s, and has been affectionally dubbed Python&amp;rsquo;s &lt;a href=&quot;https://en.wikipedia.org/wiki/Benevolent_dictator_for_life&quot;&gt;&lt;strong&gt;Benevolent Dictator for Life&lt;/strong&gt; (BDFL)&lt;/a&gt;. Through the years, more and more decisions about the Python language were made through &lt;a href=&quot;https://www.python.org/dev/peps/pep-0001/&quot;&gt;&lt;strong&gt;Python Enhancement Proposals&lt;/strong&gt; (PEPs)&lt;/a&gt;. Still, Guido officially had the last word on any new language feature.&lt;/p&gt;
&lt;p&gt;After a long and drawn out discussion about &lt;a href=&quot;#the-walrus-in-the-room-assignment-expressions&quot;&gt;assignment expressions&lt;/a&gt;, Guido &lt;a href=&quot;https://mail.python.org/pipermail/python-committers/2018-July/005664.html&quot;&gt;announced&lt;/a&gt; in July 2018 that he was retiring from his role as BDFL (&lt;a href=&quot;https://www.python.org/dev/peps/pep-0401/&quot;&gt;for real this time&lt;/a&gt;). He purposefully did not name a successor. Instead, he asked the team of core developers to figure out how Python should be governed going forward.&lt;/p&gt;
&lt;p&gt;Luckily, the PEP process was already well established, so it was natural to use PEPs to discuss and decide on a new governance model. Through the fall of 2018, &lt;a href=&quot;https://www.python.org/dev/peps/pep-8000/&quot;&gt;several models&lt;/a&gt; were proposed, including &lt;a href=&quot;https://www.python.org/dev/peps/pep-8010/&quot;&gt;electing a new BDFL&lt;/a&gt; (renamed the Gracious Umpire Influencing Decisions Officer: the GUIDO), or moving to a &lt;a href=&quot;https://www.python.org/dev/peps/pep-8012/&quot;&gt;community model&lt;/a&gt; based on consensus and voting, without centralized leadership. In December 2018, the &lt;a href=&quot;https://www.python.org/dev/peps/pep-8016/&quot;&gt;steering council model&lt;/a&gt; was chosen after a vote among the core developers. &lt;/p&gt;
&lt;figure class=&quot;figure mx-auto d-block&quot;&gt;&lt;a href=&quot;https://files.realpython.com/media/steering_council.1aae31a91dad.jpg&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block &quot; src=&quot;https://files.realpython.com/media/steering_council.1aae31a91dad.jpg&quot; width=&quot;1200&quot; height=&quot;600&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/steering_council.1aae31a91dad.jpg&amp;amp;w=300&amp;amp;sig=f85bfa33a09b628d0005974d9126309e16ccae1a 300w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/steering_council.1aae31a91dad.jpg&amp;amp;w=600&amp;amp;sig=cb7a693fe0e6d8724ad591bc54fe1c3b388014f6 600w, https://files.realpython.com/media/steering_council.1aae31a91dad.jpg 1200w&quot; sizes=&quot;75vw&quot; alt=&quot;The Python Steering Council at PyCon 2019&quot;/&gt;&lt;/a&gt;&lt;figcaption class=&quot;figure-caption text-center&quot;&gt;The Python Steering Council at PyCon 2019. From left to right: Barry Warsaw, Brett Cannon, Carol Willing, Guido van Rossum, and Nick Coghlan (Image: Geir Arne Hjelle)&lt;/figcaption&gt;&lt;/figure&gt;

&lt;p&gt;The steering council consists of five members of the Python community, as listed above. There will be an election for a new steering council after every major release of Python. In other words, there will be an election following the release of Python 3.8.&lt;/p&gt;
&lt;p&gt;Although it&amp;rsquo;s an open election, it&amp;rsquo;s expected that most, if not all, of the inaugural steering council will be reelected. The steering council has &lt;a href=&quot;https://www.python.org/dev/peps/pep-0013/#mandate&quot;&gt;broad powers&lt;/a&gt; to make decisions about the Python language, but should strive to exercise those powers as little as possible.&lt;/p&gt;
&lt;p&gt;You can read all about the new governance model in &lt;a href=&quot;https://www.python.org/dev/peps/pep-0013/&quot;&gt;PEP 13&lt;/a&gt;, while the process of deciding on the new model is described in &lt;a href=&quot;https://www.python.org/dev/peps/pep-8000/&quot;&gt;PEP 8000&lt;/a&gt;. For more information, see the &lt;a href=&quot;https://pyvideo.org/pycon-us-2019/python-steering-council-keynote-pycon-2019.html&quot;&gt;PyCon 2019 Keynote&lt;/a&gt;, and listen to Brett Cannon on &lt;a href=&quot;https://talkpython.fm/episodes/show/209/inside-python-s-new-governance-model&quot;&gt;Talk Python To Me&lt;/a&gt; and on &lt;a href=&quot;https://changelog.com/podcast/348&quot;&gt;The Changelog podcast&lt;/a&gt;. You can follow updates from the steering council on &lt;a href=&quot;https://github.com/python/steering-council&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;other-pretty-cool-features&quot;&gt;Other Pretty Cool Features&lt;/h2&gt;
&lt;p&gt;So far, you&amp;rsquo;ve seen the headline news regarding what&amp;rsquo;s new in Python 3.8. However, there are many other changes that are also pretty cool. In this section, you&amp;rsquo;ll get a quick look at some of them.&lt;/p&gt;
&lt;h3 id=&quot;importlibmetadata&quot;&gt;&lt;code&gt;importlib.metadata&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;There is one new module available in the standard library in Python 3.8: &lt;a href=&quot;https://importlib-metadata.readthedocs.io&quot;&gt;&lt;code&gt;importlib.metadata&lt;/code&gt;&lt;/a&gt;. Through this module, you can access information about installed packages in your Python installation. Together with its companion module, &lt;a href=&quot;https://realpython.com/python37-new-features/#importing-data-files-with-importlibresources&quot;&gt;&lt;code&gt;importlib.resources&lt;/code&gt;&lt;/a&gt;, &lt;code&gt;importlib.metadata&lt;/code&gt; improves on the functionality of the older &lt;a href=&quot;https://setuptools.readthedocs.io/en/latest/pkg_resources.html&quot;&gt;&lt;code&gt;pkg_resources&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As an example, you can get some information about &lt;code&gt;pip&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;importlib&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metadata&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pip&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;19.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;pip_metadata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pip&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;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pip_metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;Metadata-Version&amp;#39;, &amp;#39;Name&amp;#39;, &amp;#39;Version&amp;#39;, &amp;#39;Summary&amp;#39;, &amp;#39;Home-page&amp;#39;, &amp;#39;Author&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; &amp;#39;Author-email&amp;#39;, &amp;#39;License&amp;#39;, &amp;#39;Keywords&amp;#39;, &amp;#39;Platform&amp;#39;, &amp;#39;Classifier&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;#39;Classifier&amp;#39;, &amp;#39;Classifier&amp;#39;, &amp;#39;Classifier&amp;#39;, &amp;#39;Classifier&amp;#39;, &amp;#39;Classifier&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;#39;Classifier&amp;#39;, &amp;#39;Classifier&amp;#39;, &amp;#39;Classifier&amp;#39;, &amp;#39;Classifier&amp;#39;, &amp;#39;Classifier&amp;#39;,&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;  &amp;#39;Classifier&amp;#39;, &amp;#39;Classifier&amp;#39;, &amp;#39;Requires-Python&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;pip_metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Home-page&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;#39;https://pip.pypa.io/&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;pip_metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Requires-Python&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;gt;=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=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;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;pip&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;668&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The currently installed version of &lt;code&gt;pip&lt;/code&gt; is 19.2.3. &lt;code&gt;metadata()&lt;/code&gt; gives access to most of the information that you can see on &lt;a href=&quot;https://pypi.org/project/pip/&quot;&gt;PyPI&lt;/a&gt;. You can for instance see that this version of &lt;code&gt;pip&lt;/code&gt; requires either Python 2.7, or Python 3.5 or higher. With &lt;code&gt;files()&lt;/code&gt;, you get a listing of all files that make up the &lt;code&gt;pip&lt;/code&gt; package. In this case, there are almost 700 files.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;files()&lt;/code&gt; returns a list of &lt;a href=&quot;https://realpython.com/python-pathlib/&quot;&gt;&lt;code&gt;Path&lt;/code&gt;&lt;/a&gt; objects. These give you a convenient way of looking into the source code of a package, using &lt;code&gt;read_text()&lt;/code&gt;. The following example prints out &lt;code&gt;__init__.py&lt;/code&gt; from the &lt;a href=&quot;https://pypi.org/project/realpython-reader/&quot;&gt;&lt;code&gt;realpython-reader&lt;/code&gt;&lt;/a&gt; package:&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;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;files&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;realpython-reader&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;p&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;suffix&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;.py&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[PackagePath(&amp;#39;reader/__init__.py&amp;#39;), PackagePath(&amp;#39;reader/__main__.py&amp;#39;),&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt; PackagePath(&amp;#39;reader/feed.py&amp;#39;), PackagePath(&amp;#39;reader/viewer.py&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;init_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&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;c1&quot;&gt;# Underscore access last returned value in the REPL&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;init_path&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;read_text&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;go&quot;&gt;&amp;quot;&amp;quot;&amp;quot;Real Python feed reader&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;Import the `feed` module to work with the Real Python feed:&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;    &amp;gt;&amp;gt;&amp;gt; from reader import feed&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    &amp;gt;&amp;gt;&amp;gt; feed.get_titles()&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;    [&amp;#39;Logging in Python&amp;#39;, &amp;#39;The Best Python Books&amp;#39;, ...]&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;See https://github.com/realpython/reader/ for more information&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

&lt;span class=&quot;go&quot;&gt;# Version of realpython-reader package&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;__version__ = &amp;quot;1.0.0&amp;quot;&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also access package dependencies:&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;metadata&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;requires&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;realpython-reader&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[&amp;#39;feedparser&amp;#39;, &amp;#39;html2text&amp;#39;, &amp;#39;importlib-resources&amp;#39;, &amp;#39;typing&amp;#39;]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;requires()&lt;/code&gt; lists the dependencies of a package. You can see that &lt;code&gt;realpython-reader&lt;/code&gt; for instance uses &lt;a href=&quot;https://pypi.org/project/feedparser/&quot;&gt;&lt;code&gt;feedparser&lt;/code&gt;&lt;/a&gt; in the background to read and parse a feed of articles.&lt;/p&gt;
&lt;p&gt;There is a backport of &lt;code&gt;importlib.metadata&lt;/code&gt; &lt;a href=&quot;https://pypi.org/project/importlib-metadata/&quot;&gt;available on PyPI&lt;/a&gt; that works on earlier versions of Python. You can install it using &lt;code&gt;pip&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 -m pip install importlib-metadata
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can fall back on using the PyPI backport in your code 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;k&quot;&gt;try&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;importlib&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;ne&quot;&gt;ImportError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;importlib_metadata&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;metadata&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;...&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;See the &lt;a href=&quot;https://importlib-metadata.readthedocs.io&quot;&gt;documentation&lt;/a&gt; for more information about &lt;code&gt;importlib.metadata&lt;/code&gt;&lt;/p&gt;
&lt;h3 id=&quot;new-and-improved-math-and-statistics-functions&quot;&gt;New and Improved &lt;code&gt;math&lt;/code&gt; and &lt;code&gt;statistics&lt;/code&gt; Functions&lt;/h3&gt;
&lt;p&gt;Python 3.8 brings many improvements to existing standard library packages and modules. &lt;code&gt;math&lt;/code&gt; in the standard library has a few new functions. &lt;code&gt;math.prod()&lt;/code&gt; works similarly to the built-in &lt;code&gt;sum()&lt;/code&gt;, but for multiplicative products:&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;math&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;prod&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;8&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;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;784&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;2&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;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;784&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The two statements are equivalent. &lt;code&gt;prod()&lt;/code&gt; will be easier to use when you already have the factors stored in an iterable.&lt;/p&gt;
&lt;p&gt;Another new function is &lt;code&gt;math.isqrt()&lt;/code&gt;. You can use &lt;code&gt;isqrt()&lt;/code&gt; to find the integer part of &lt;a href=&quot;https://realpython.com/python-square-root-function/&quot;&gt;square roots&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;math&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;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;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3.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;math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&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;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sqrt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3.872983346207417&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The square root of 9 is 3. You can see that &lt;code&gt;isqrt()&lt;/code&gt; returns an integer result, while &lt;code&gt;math.sqrt()&lt;/code&gt; always returns a &lt;code&gt;float&lt;/code&gt;. The square root of 15 is almost 3.9. Note that &lt;code&gt;isqrt()&lt;/code&gt; &lt;a href=&quot;https://realpython.com/python-rounding/#truncation&quot;&gt;truncates&lt;/a&gt; the answer down to the next integer, in this case 3.&lt;/p&gt;
&lt;p&gt;Finally, you can now more easily work with &lt;em&gt;n&lt;/em&gt;-dimensional points and vectors in the standard library. You can find the distance between two points with &lt;code&gt;math.dist()&lt;/code&gt;, and the length of a vector with &lt;code&gt;math.hypot()&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;math&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;point_1&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;16&lt;/span&gt;&lt;span class=&quot;p&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;mi&quot;&gt;20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;point_2&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;15&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;point_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;point_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;14.142135623730951&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hypot&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;point_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;35.79106033634656&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;math&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hypot&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;point_2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;22.02271554554524&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This makes it easier to work with points and vectors using the standard library. However, if you will be doing many calculations on points or vectors, you should check out &lt;a href=&quot;https://realpython.com/numpy-array-programming/&quot;&gt;NumPy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;statistics&lt;/code&gt; module also has several new functions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3.8/library/statistics.html#statistics.fmean&quot;&gt;&lt;code&gt;statistics.fmean()&lt;/code&gt;&lt;/a&gt; calculates the mean of &lt;code&gt;float&lt;/code&gt; numbers.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3.8/library/statistics.html#statistics.geometric_mean&quot;&gt;&lt;code&gt;statistics.geometric_mean()&lt;/code&gt;&lt;/a&gt; calculates the geometric mean of &lt;code&gt;float&lt;/code&gt; numbers.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3.8/library/statistics.html#statistics.multimode&quot;&gt;&lt;code&gt;statistics.multimode()&lt;/code&gt;&lt;/a&gt; finds the most frequently occurring values in a sequence.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3.8/library/statistics.html#statistics.quantiles&quot;&gt;&lt;code&gt;statistics.quantiles()&lt;/code&gt;&lt;/a&gt; calculates cut points for dividing data into &lt;em&gt;n&lt;/em&gt; continuous intervals with equal probability.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following example shows the functions in use:&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;statistics&lt;/span&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;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;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;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;statistics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fmean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;4.25&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;statistics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;geometric_mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;3.013668912157617&lt;/span&gt;

&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;statistics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;multimode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[9, 2, 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;statistics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quantiles&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;n&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 class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;[1.25, 2.5, 8.5]&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In Python 3.8, there is a new &lt;a href=&quot;https://docs.python.org/3.8/library/statistics.html#statistics.NormalDist&quot;&gt;&lt;code&gt;statistics.NormalDist&lt;/code&gt;&lt;/a&gt; class that makes it more convenient to &lt;a href=&quot;https://docs.python.org/3.8/library/statistics.html#normaldist-examples-and-recipes&quot;&gt;work with the Gaussian normal distribution&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;To see an example of using &lt;code&gt;NormalDist&lt;/code&gt;, you can try to compare the speed of the new &lt;code&gt;statistics.fmean()&lt;/code&gt; and the traditional &lt;code&gt;statistics.mean()&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;random&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;statistics&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;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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;# Create 10,000 random numbers&lt;/span&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;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;random&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;_&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;10_000&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Measure the time it takes to run mean() and fmean()&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t_mean&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;timeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;statistics.mean(data)&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;100&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;gp&quot;&gt;... &lt;/span&gt;          &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&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;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)]&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t_fmean&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;timeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;statistics.fmean(data)&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;100&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;gp&quot;&gt;... &lt;/span&gt;           &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&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;30&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Create NormalDist objects based on the sampled timings&lt;/span&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_mean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;statistics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NormalDist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_samples&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t_mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&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_fmean&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;statistics&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NormalDist&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;from_samples&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;t_fmean&lt;/span&gt;&lt;span class=&quot;p&quot;&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;# Look at sample mean and standard deviation&lt;/span&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_mean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_mean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdev&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(0.825690647733245, 0.07788573997674526)&lt;/span&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_fmean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mean&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;n_fmean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stdev&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;(0.010488564966666065, 0.0008572332785645231)&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;# Calculate the lower 1 percentile of mean&lt;/span&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_mean&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;quantiles&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;100&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;0.6445013221202459&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this example, you use &lt;a href=&quot;https://docs.python.org/library/timeit.html&quot;&gt;&lt;code&gt;timeit&lt;/code&gt;&lt;/a&gt; to measure the execution time of &lt;code&gt;mean()&lt;/code&gt; and &lt;code&gt;fmean()&lt;/code&gt;. To get reliable results, you let &lt;code&gt;timeit&lt;/code&gt; execute each function 100 times, and collect 30 such time samples for each function. Based on these samples, you create two &lt;code&gt;NormalDist&lt;/code&gt; objects. Note that if you run the code yourself, it might take up to a minute to collect the different time samples.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;NormalDist&lt;/code&gt; has many convenient attributes and methods. See the &lt;a href=&quot;https://docs.python.org/3.8/library/statistics.html#normaldist-objects&quot;&gt;documentation&lt;/a&gt; for a complete list. Inspecting &lt;code&gt;.mean&lt;/code&gt; and &lt;code&gt;.stdev&lt;/code&gt;, you see that the old &lt;code&gt;statistics.mean()&lt;/code&gt; runs in 0.826 ± 0.078 seconds, while the new &lt;code&gt;statistics.fmean()&lt;/code&gt; spends 0.0105 ± 0.0009 seconds. In other words, &lt;code&gt;fmean()&lt;/code&gt; is about 80 times faster for these data.&lt;/p&gt;
&lt;p&gt;If you need more advanced statistics in Python than the standard library offers, check out &lt;a href=&quot;https://www.statsmodels.org/&quot;&gt;&lt;code&gt;statsmodels&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://docs.scipy.org/doc/scipy/reference/tutorial/stats.html&quot;&gt;&lt;code&gt;scipy.stats&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;warnings-about-dangerous-syntax&quot;&gt;Warnings About Dangerous Syntax&lt;/h3&gt;
&lt;p&gt;Python has a &lt;a href=&quot;https://docs.python.org/3/library/exceptions.html#SyntaxWarning&quot;&gt;&lt;code&gt;SyntaxWarning&lt;/code&gt;&lt;/a&gt; which can warn about dubious syntax that is typically not a &lt;code&gt;SyntaxError&lt;/code&gt;. Python 3.8 adds a few new ones that can help you during coding and debugging.&lt;/p&gt;
&lt;p&gt;The difference between &lt;code&gt;is&lt;/code&gt; and &lt;code&gt;==&lt;/code&gt; can be confusing. The latter checks for equal values, while &lt;code&gt;is&lt;/code&gt; is &lt;code&gt;True&lt;/code&gt; only when objects are the same. Python 3.8 will try to warn you about cases when you should use &lt;code&gt;==&lt;/code&gt; instead of &lt;code&gt;is&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;# Python 3.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;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;3.7&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;version&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;3.7&amp;quot;&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;c1&quot;&gt;# Python 3.8&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;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;s2&quot;&gt;&amp;quot;3.8&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;version&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;go&quot;&gt;&amp;lt;stdin&amp;gt;:1: SyntaxWarning: &amp;quot;is&amp;quot; with a literal. Did you mean &amp;quot;==&amp;quot;?&lt;/span&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;n&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;3.8&amp;quot;&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;True&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It&amp;rsquo;s easy to miss a comma when you&amp;rsquo;re writing out a long list, especially when formatting it vertically. Forgetting a comma in a list of tuples will give a confusing error message about tuples not being callable. Python 3.8 additionally emits a warning that points toward the real issue:&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;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;... &lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;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;... &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;go&quot;&gt;&amp;lt;stdin&amp;gt;:2: SyntaxWarning: &amp;#39;tuple&amp;#39; object is not callable; perhaps&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;go&quot;&gt;           you missed a comma?&lt;/span&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;2&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;tuple&amp;#39; object is not callable&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The warning correctly identifies the missing comma as the real culprit.&lt;/p&gt;
&lt;h3 id=&quot;optimizations&quot;&gt;Optimizations&lt;/h3&gt;
&lt;p&gt;There are several optimizations made for Python 3.8. Some that make code run faster. Others reduce the memory footprint. For example, looking up fields in a &lt;a href=&quot;https://docs.python.org/library/collections.html#collections.namedtuple&quot;&gt;&lt;code&gt;namedtuple&lt;/code&gt;&lt;/a&gt; is significantly faster in Python 3.8 compared with Python 3.7:&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;collections&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;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;gp&quot;&gt;&amp;gt;&amp;gt;&amp;gt; &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;collections&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;namedtuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Person&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;name twitter&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;raymond&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Person&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;Raymond&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;@raymondh&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;c1&quot;&gt;# Python 3.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;timeit&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;raymond.twitter&amp;quot;&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;go&quot;&gt;0.05876131607996285&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.8&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;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;raymond.twitter&amp;quot;&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;go&quot;&gt;0.0377705999400132&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can see that looking up &lt;code&gt;.twitter&lt;/code&gt; on the &lt;code&gt;namedtuple&lt;/code&gt; is 30-40% faster in Python 3.8. Lists save some space when they are initialized from iterables with a known length. This can save memory:&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;sys&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.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;sys&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;getsizeof&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;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20191014&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;181719232&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.8&lt;/span&gt;
&lt;span class=&quot;gp&quot;&gt;&amp;gt;&amp;gt;&amp;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;getsizeof&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;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;20191014&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;go&quot;&gt;161528168&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In this case, the list uses about 11% less memory in Python 3.8 compared with Python 3.7.&lt;/p&gt;
&lt;p&gt;Other optimizations include better performance in &lt;a href=&quot;https://docs.python.org/library/subprocess.html&quot;&gt;&lt;code&gt;subprocess&lt;/code&gt;&lt;/a&gt;, faster file copying with &lt;a href=&quot;https://docs.python.org/library/shutil.html&quot;&gt;&lt;code&gt;shutil&lt;/code&gt;&lt;/a&gt;, improved default performance in &lt;a href=&quot;https://docs.python.org/library/pickle.html&quot;&gt;&lt;code&gt;pickle&lt;/code&gt;&lt;/a&gt;, and faster &lt;a href=&quot;https://docs.python.org/library/operator.html#operator.itemgetter&quot;&gt;&lt;code&gt;operator.itemgetter&lt;/code&gt;&lt;/a&gt; operations. See the &lt;a href=&quot;https://docs.python.org/3.8/whatsnew/3.8.html#optimizations&quot;&gt;official documentation&lt;/a&gt; for a complete list of optimizations.&lt;/p&gt;
&lt;h2 id=&quot;so-should-you-upgrade-to-python-38&quot;&gt;So, Should You Upgrade to Python 3.8?&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s start with the simple answer. If you want to try out any of the new features you have seen here, then you do need to be able to use Python 3.8. Tools like &lt;a href=&quot;https://realpython.com/intro-to-pyenv/&quot;&gt;&lt;code&gt;pyenv&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/python-windows-machine-learning-setup/#introducing-anaconda-and-conda&quot;&gt;Anaconda&lt;/a&gt; make it easy to have several versions of Python installed side by side. Alternatively, you can run the &lt;a href=&quot;https://hub.docker.com/_/python/&quot;&gt;official Python 3.8 Docker container&lt;/a&gt;. There is no downside to trying out Python 3.8 for yourself.&lt;/p&gt;
&lt;p&gt;Now, for the more complicated questions. Should you upgrade your production environment to Python 3.8? Should you make your own project dependent on Python 3.8 to take advantage of the new features?&lt;/p&gt;
&lt;p&gt;You should have very few issues running Python 3.7 code in Python 3.8. Upgrading your environment to run Python 3.8 is therefore quite safe, and you would be able to take advantage of the &lt;a href=&quot;#optimizations&quot;&gt;optimizations&lt;/a&gt; made in the new version. Different beta-versions of Python 3.8 have already been available for months, so hopefully most bugs are already squashed. However, if you want to be conservative, you might hold out until the first maintenance release (Python 3.8.1) is available.&lt;/p&gt;
&lt;p&gt;Once you&amp;rsquo;ve upgraded your environment, you can start to experiment with features that are only in Python 3.8, such as &lt;a href=&quot;#the-walrus-in-the-room-assignment-expressions&quot;&gt;assignment expressions&lt;/a&gt; and &lt;a href=&quot;#positional-only-arguments&quot;&gt;positional-only arguments&lt;/a&gt;. However, you should be conscious about whether other people depend on your code, as this will force them to upgrade their environment as well. Popular libraries will probably mostly support at least Python 3.6 for quite a while longer.&lt;/p&gt;
&lt;p&gt;See &lt;a href=&quot;https://docs.python.org/3.8/whatsnew/3.8.html#porting-to-python-3-8&quot;&gt;Porting to Python 3.8&lt;/a&gt; for more information about preparing your code for Python 3.8.&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>Emacs: The Best Python Editor?</title>
      <id>https://realpython.com/emacs-the-best-python-editor/</id>
      <link href="https://realpython.com/emacs-the-best-python-editor/"/>
      <updated>2019-10-09T17:41:47+00:00</updated>
      <summary>In this step-by-step tutorial, you&#39;ll learn about using Emacs for Python development. You&#39;ll install and configure Emacs on your selected platform, then write Python code to explore its capabilities. Finally, you&#39;ll run, test, and debug Python code in the Emacs environment.</summary>
      <content type="html">
        &lt;p&gt;Finding the right code editor for Python development can be tricky. Many developers explore numerous editors as they grow and learn. To choose the right code editor, you have to start by knowing which features are important to you. Then, you can try to find editors that have those features. One of the most feature-rich editors available is &lt;a href=&quot;https://www.gnu.org/software/emacs/&quot;&gt;Emacs&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Emacs started in the mid-1970s as a set of macro extensions for a different code editor. It was adopted into the &lt;a href=&quot;https://en.wikipedia.org/wiki/GNU_Project&quot;&gt;GNU project&lt;/a&gt; by Richard Stallman in the early 1980s, and GNU Emacs has been continuously maintained and developed ever since. To this day, GNU Emacs and the XEmacs variant are available on every major platform, and GNU Emacs continues to be a combatant in the &lt;a href=&quot;https://en.wikipedia.org/wiki/Editor_war&quot;&gt;Editor Wars&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;In this tutorial, you&amp;rsquo;ll learn about using Emacs for Python development, including how to:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install Emacs on your selected platform&lt;/li&gt;
&lt;li&gt;Set up an Emacs initialization file to configure Emacs&lt;/li&gt;
&lt;li&gt;Build a basic Python configuration for Emacs&lt;/li&gt;
&lt;li&gt;Write Python code to explore Emacs capabilities&lt;/li&gt;
&lt;li&gt;Run and Test Python code in the Emacs environment&lt;/li&gt;
&lt;li&gt;Debug Python code using integrated Emacs tools&lt;/li&gt;
&lt;li&gt;Add source control functionality using Git&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For this tutorial, you&amp;rsquo;ll use GNU Emacs 25 or later, although most of the techniques shown will work on older versions (and XEmacs) as well. You should have some experience developing in Python, and your machine should have a Python distribution already &lt;a href=&quot;https://realpython.com/installing-python/&quot;&gt;installed&lt;/a&gt; and ready to go.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Updates:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;10/09/2019:&lt;/em&gt; Major update adding new code samples, updated package availability and info, basic tutorial, Jupyter walk-through, debugging walk-through, testing walk-through, and updated visuals.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;11/03/2015:&lt;/em&gt; Initial tutorial published.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can download all the files referenced in this tutorial at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/emacs/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-emacs&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to learn about Emacs for Python in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;h2 id=&quot;installation-and-basics&quot;&gt;Installation and Basics&lt;/h2&gt;
&lt;p&gt;Before you can explore Emacs and all it has to offer a Python developer, you need to install it and learn some of the basics.&lt;/p&gt;
&lt;h3 id=&quot;installation&quot;&gt;Installation&lt;/h3&gt;
&lt;p&gt;When you install Emacs, you have to consider your platform. This &lt;a href=&quot;http://ergoemacs.org/emacs/which_emacs.html&quot;&gt;guide&lt;/a&gt;, provided by &lt;a href=&quot;http://ergoemacs.org/&quot;&gt;ErgoEmacs&lt;/a&gt;, provides everything you need to get up and running with a basic Emacs installation on Linux, Mac, or Windows.&lt;/p&gt;
&lt;p&gt;Once the installation has finished, you can start Emacs:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-fresh-launch.2fb60d356a34.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/emacsv2-fresh-launch.2fb60d356a34.png&quot; width=&quot;740&quot; height=&quot;732&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-fresh-launch.2fb60d356a34.png&amp;amp;w=185&amp;amp;sig=11094162fe877c3840d074ba5256a6239d905619 185w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-fresh-launch.2fb60d356a34.png&amp;amp;w=370&amp;amp;sig=543886ac093a4932db4adf95cc9fe4f1e629f833 370w, https://files.realpython.com/media/emacsv2-fresh-launch.2fb60d356a34.png 740w&quot; sizes=&quot;75vw&quot; alt=&quot;Emacs when it first runs&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You should be greeted with the default startup screen.&lt;/p&gt;
&lt;h3 id=&quot;basic-emacs&quot;&gt;Basic Emacs&lt;/h3&gt;
&lt;p&gt;First, let&amp;rsquo;s go through a quick example to cover some basic Emacs for Python development. You&amp;rsquo;ll see how to edit a program using vanilla Emacs, and how much Python support is built into the program. With Emacs open, use the following steps to create a quick Python program:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-f&quot;&gt;F&lt;/kbd&gt;&lt;/span&gt; to open a new file.&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;sieve.py&lt;/code&gt; to name the file.&lt;/li&gt;
&lt;li&gt;Hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Emacs may ask you to confirm your choice. If so, then hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt; again.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Now type the following code:&lt;/p&gt;
&lt;div class=&quot;highlight python&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt; 1 &lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MAX_PRIME&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&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;sieve&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;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;MAX_PRIME&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;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;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_PRIME&lt;/span&gt;&lt;span class=&quot;p&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;n&quot;&gt;sieve&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;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&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;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;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&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;MAX_PRIME&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;lineno&quot;&gt; 8 &lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;sieve&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;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;/pre&gt;&lt;/div&gt;

&lt;p&gt;You may recognize this code as the &lt;a href=&quot;https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes&quot;&gt;Sieve of Eratosthenes&lt;/a&gt;, which finds all primes below a given maximum. As you type the code, you&amp;rsquo;ll notice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Emacs highlights variables and constants differently from Python keywords.&lt;/li&gt;
&lt;li&gt;Emacs indents lines following &lt;a href=&quot;https://realpython.com/courses/python-for-loop/&quot;&gt;&lt;code&gt;for&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://realpython.com/courses/python-conditional-statements/&quot;&gt;&lt;code&gt;if&lt;/code&gt;&lt;/a&gt; statements automatically.&lt;/li&gt;
&lt;li&gt;Emacs changes the indentation to appropriate locations when you hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-tab&quot;&gt;Tab&lt;/kbd&gt;&lt;/span&gt; on an indented line.&lt;/li&gt;
&lt;li&gt;Emacs highlights the opening bracket or parenthesis whenever you type a closing bracket or parenthesis.&lt;/li&gt;
&lt;li&gt;Emacs responds as expected to the arrow keys, as well as the &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt;, &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-backspace&quot;&gt;Backspace&lt;/kbd&gt;&lt;/span&gt;, &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-delete&quot;&gt;Del&lt;/kbd&gt;&lt;/span&gt;, &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-home&quot;&gt;Home&lt;/kbd&gt;&lt;/span&gt;, &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-end&quot;&gt;End&lt;/kbd&gt;&lt;/span&gt;, and &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-tab&quot;&gt;Tab&lt;/kbd&gt;&lt;/span&gt; keys.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are some odd key mappings in Emacs, however. If you try to paste code into Emacs, for instance, then you may find the standard &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-v&quot;&gt;V&lt;/kbd&gt;&lt;/span&gt; keystroke doesn&amp;rsquo;t work.&lt;/p&gt;
&lt;p&gt;The easiest way to learn which keys do what in Emacs is to follow the built-in tutorial. You can access it by positioning the cursor over the words &lt;em&gt;Emacs Tutorial&lt;/em&gt; on the Emacs start screen and pressing &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt;, or by typing &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-h&quot;&gt;H&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-t&quot;&gt;T&lt;/kbd&gt;&lt;/span&gt; at any time thereafter. You&amp;rsquo;ll be greeted with the following passage:&lt;/p&gt;
&lt;div class=&quot;highlight text&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Emacs commands generally involve the CONTROL key (sometimes labeled
CTRL or CTL) or the META key (sometimes labeled EDIT or ALT).  Rather than
write that in full each time, we&amp;#39;ll use the following abbreviations:

 C-&amp;lt;chr&amp;gt;  means hold the CONTROL key while typing the character &amp;lt;chr&amp;gt;
          Thus, C-f would be: hold the CONTROL key and type f.
 M-&amp;lt;chr&amp;gt;  means hold the META or EDIT or ALT key down while typing &amp;lt;chr&amp;gt;.
          If there is no META, EDIT or ALT key, instead press and release the
          ESC key and then type &amp;lt;chr&amp;gt;.  We write &amp;lt;ESC&amp;gt; for the ESC key.

Important Note: to end the Emacs session, type C-x C-c.  (Two characters.)
To quit a partially entered command, type C-g.
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you scan the text from the passage, you&amp;rsquo;ll see that Emacs keystrokes are shown in the Emacs documentation using the notation &lt;code&gt;C-x C-s&lt;/code&gt;. This is the command to save the contents of the current buffer. This notation indicates that the &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;/span&gt; and &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; keys are pressed at the same time, followed by the &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;/span&gt; and &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-s&quot;&gt;S&lt;/kbd&gt;&lt;/span&gt; keys.&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 tutorial, Emacs keystrokes are shown as &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-s&quot;&gt;S&lt;/kbd&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;Emacs uses some terminology that can be traced back to its text-based UNIX roots. Since these terms have different meanings now, it&amp;rsquo;s a good idea to review them, as you&amp;rsquo;ll be reading about them as the tutorial progresses:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The window you see when you start Emacs is referred to as a &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Frames.html#Frames&quot;&gt;&lt;strong&gt;frame&lt;/strong&gt;&lt;/a&gt;. You can open as many Emacs frames as you wish, on as many monitors as you wish, and Emacs will track them all.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The panes within each Emacs frame are referred to as &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Windows.html#Windows&quot;&gt;&lt;strong&gt;windows&lt;/strong&gt;&lt;/a&gt;. Emacs frames initially contain a single window, but you can open multiple windows in each frame, either manually or by running special commands.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Within each window, the contents displayed are called a &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_node/elisp/Buffers.html&quot;&gt;&lt;strong&gt;buffer&lt;/strong&gt;&lt;/a&gt;. Buffers can contain the contents of files, the output of commands, the lists of menu options, or other items. Buffers are where you interact with Emacs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;When Emacs needs your input, it asks in a special one-line area at the bottom of the currently active frame called the &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/elisp/Minibuffers.html#Minibuffers&quot;&gt;&lt;strong&gt;mini-buffer&lt;/strong&gt;&lt;/a&gt;. If you ever find yourself there unexpectedly, then you can cancel whatever got you there with &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-g&quot;&gt;G&lt;/kbd&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that you&amp;rsquo;ve covered the basics, it&amp;rsquo;s time to start customizing and configuring Emacs for Python development!&lt;/p&gt;
&lt;h3 id=&quot;initialization-file&quot;&gt;Initialization File&lt;/h3&gt;
&lt;p&gt;One of the great benefits of Emacs is its powerful configuration options. The core of Emacs configuration is the &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html&quot;&gt;initialization file&lt;/a&gt;, which is processed every time Emacs is started.&lt;/p&gt;
&lt;p&gt;This file contains commands written in &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/eintr/index.html&quot;&gt;Emacs Lisp&lt;/a&gt;, which is executed every time Emacs is started. Don&amp;rsquo;t worry, though! You don&amp;rsquo;t need to know Lisp to use or customize Emacs. In this tutorial, you&amp;rsquo;ll find everything you need to get started. (After all, this is &lt;em&gt;Real Python&lt;/em&gt;, not &lt;em&gt;Real Lisp&lt;/em&gt;!)&lt;/p&gt;
&lt;p&gt;On start-up, Emacs looks for the initialization file in &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Find-Init.html#Find-Init&quot;&gt;three places&lt;/a&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, it looks in your home user folder for the file &lt;code&gt;.emacs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If it&amp;rsquo;s not there, then Emacs looks in your home user folder for the file &lt;code&gt;emacs.el&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Finally, if neither is found, then it looks in your home folder for &lt;code&gt;.emacs.d/init.el&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The last option, &lt;code&gt;.emacs.d/init.el&lt;/code&gt;, is the current recommended initialization file. However, if you&amp;rsquo;ve previously used and configured Emacs, then you may already have one of the other initialization files present. If so, then continue to use that file as you read this tutorial.&lt;/p&gt;
&lt;p&gt;When you first install Emacs, there is no &lt;code&gt;.emacs.d/init.el&lt;/code&gt;, but you can create this file fairly quickly. With the Emacs window open, follow these steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-f&quot;&gt;F&lt;/kbd&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;~/.emacs.d/init.el&lt;/code&gt; in the mini-buffer.&lt;/li&gt;
&lt;li&gt;Hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Emacs may ask you to confirm your choice. If so, then hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt; again.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Let&amp;rsquo;s take a closer look at what&amp;rsquo;s happening here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;You tell Emacs that you want to find and open a file with the keystrokes &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-f&quot;&gt;F&lt;/kbd&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You tell Emacs what file to open by giving it a path to the file. The path &lt;code&gt;~/.emacs.d/init.el&lt;/code&gt; has three parts:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The leading tilde &lt;code&gt;~&lt;/code&gt; is a shortcut to your home folder. On Linux and Mac machines, this is usually &lt;code&gt;/home/&amp;lt;username&amp;gt;&lt;/code&gt;. On Windows machines, it&amp;rsquo;s the path specified in the &lt;a href=&quot;http://www.gnu.org/software/emacs/manual/html_node/efaq-w32/Location-of-init-file.html#Location-of-init-file&quot;&gt;HOME environment variable&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;The folder &lt;code&gt;.emacs.d&lt;/code&gt; is where Emacs stores all its configuration information. You can use this folder to quickly set up Emacs on a new machine. To do so, copy the contents of this folder to your new machine, and Emacs is good to go!&lt;/li&gt;
&lt;li&gt;The file &lt;code&gt;init.el&lt;/code&gt; is your initialization file.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You tell Emacs, &amp;ldquo;Yes, I do want to create this new file.&amp;rdquo; (This step is required since the file doesn&amp;rsquo;t exist. Normally, Emacs will simply open the file specified.)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After Emacs creates the new file, it opens that file in a new buffer for you to edit. This action doesn&amp;rsquo;t actually create the file yet, though. You must save the blank file using &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-s&quot;&gt;S&lt;/kbd&gt;&lt;/span&gt; to create it on disk.&lt;/p&gt;
&lt;p&gt;Throughout this tutorial, you&amp;rsquo;ll see initialization code snippets that enable different features. Create the initialization file now if you want to follow along! You can also find the complete initialization file at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/emacs/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-emacs&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to learn about Emacs for Python in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;h3 id=&quot;customization-packages&quot;&gt;Customization Packages&lt;/h3&gt;
&lt;p&gt;Now that you have an initialization file, you can add customization options to tailor Emacs for Python development. There are a few ways you can customize Emacs, but the one with the fewest steps is adding &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/emacs/Packages.html&quot;&gt;Emacs packages&lt;/a&gt;. These come from a variety of sources, but the primary package repository is &lt;a href=&quot;https://melpa.org/#/&quot;&gt;MELPA&lt;/a&gt;, or the &lt;strong&gt;Milkypostman&amp;rsquo;s Emacs Lisp Package Archive&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Think of MELPA as &lt;a href=&quot;https://pypi.org/&quot;&gt;PyPI&lt;/a&gt; for Emacs packages. Everything you need and will use in this tutorial can be found there. To begin using it, expand the code block below and copy the configuration code to your &lt;code&gt;init.el&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;card mb-3&quot; id=&quot;collapse_card1594de&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;#collapse1594de&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse1594de&quot;&gt;init.el&lt;/button&gt; &lt;button class=&quot;btn btn-link float-right&quot; data-toggle=&quot;collapse&quot; data-target=&quot;#collapse1594de&quot; aria-expanded=&quot;false&quot; aria-controls=&quot;collapse1594de&quot;&gt;Show/Hide&lt;/button&gt;&lt;/p&gt;&lt;/div&gt;
&lt;div id=&quot;collapse1594de&quot; class=&quot;collapse&quot; data-parent=&quot;#collapse_card1594de&quot;&gt;&lt;div class=&quot;card-body&quot; markdown=&quot;1&quot;&gt;

&lt;div class=&quot;highlight lisp&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;;; .emacs.d/init.el&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;c1&quot;&gt;;; ===================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; MELPA Package Support&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ===================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Enables basic packaging support&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;package&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;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Adds the Melpa archive to the list of available repositories&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;package-archives&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;             &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;melpa&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;http://melpa.org/packages/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&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;lineno&quot;&gt;13 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Initializes the package infrastructure&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; If there are no archived package contents, refresh them&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;package-archive-contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-refresh-contents&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;lineno&quot;&gt;20 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Installs packages&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; myPackages contains a list of package names&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;myPackages&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;better-defaults&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;;; Set up some better Emacs defaults&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;material-theme&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;;; Theme&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &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;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Scans the list in myPackages&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; If the package listed is not already installed, install it&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mapc&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-installed-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-install&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;34 &lt;/span&gt;      &lt;span class=&quot;nv&quot;&gt;myPackages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;35 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;36 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ===================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;37 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Basic Customization&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;38 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ===================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;39 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;40 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inhibit-startup-message&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;;; Hide the startup message&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;41 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load-theme&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;material&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;;; Load material theme&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;42 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global-linum-mode&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;;; Enable line numbers globally&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;43 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;44 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; User-Defined init.el ends here&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

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

&lt;/div&gt;
&lt;p&gt;As you read through the code, you&amp;rsquo;ll see that &lt;code&gt;init.el&lt;/code&gt; is broken into sections. Each section is separated by comment blocks that begin with two semicolons (&lt;code&gt;;;&lt;/code&gt;). The first section is titled &lt;code&gt;MELPA Package Support&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&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;;; .emacs.d/init.el&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;c1&quot;&gt;;; ===================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 4 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; MELPA Package Support&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 5 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ===================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 6 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Enables basic packaging support&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt; 7 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;package&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;lineno&quot;&gt; 9 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Adds the Melpa archive to the list of available repositories&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;10 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;package-archives&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;11 &lt;/span&gt;             &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;melpa&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;http://melpa.org/packages/&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&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;lineno&quot;&gt;13 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Initializes the package infrastructure&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;14 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;15 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;16 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; If there are no archived package contents, refresh them&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;17 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;package-archive-contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;18 &lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-refresh-contents&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This section begins by setting up the packaging infrastructure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 7&lt;/strong&gt; tells Emacs to use packages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 10 and 11&lt;/strong&gt; add the MELPA archive to the list of package sources.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 14&lt;/strong&gt; initializes the packaging system.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 17 and 18&lt;/strong&gt; build the current package content list if it doesn&amp;rsquo;t already exist.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first section continues from line 20:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;20 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Installs packages&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;21 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;;&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;22 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; myPackages contains a list of package names&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;myPackages&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;better-defaults&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;;; Set up some better Emacs defaults&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;material-theme&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;;; Theme&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &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;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Scans the list in myPackages&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; If the package listed is not already installed, install it&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mapc&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;#&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;lambda&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;          &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;unless&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-installed-p&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;33 &lt;/span&gt;            &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;package-install&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;package&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;34 &lt;/span&gt;      &lt;span class=&quot;nv&quot;&gt;myPackages&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At this point, you&amp;rsquo;re all set to programmatically install Emacs packages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Lines 23 to 27&lt;/strong&gt; define a list of package names to install. You&amp;rsquo;ll add more packages as you progress through the tutorial:&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 24&lt;/strong&gt; adds &lt;a href=&quot;http://melpa.org/#/better-defaults&quot;&gt;&lt;code&gt;better-defaults&lt;/code&gt;&lt;/a&gt;. This is a collection of minor changes to the Emacs defaults that make it more user-friendly. It&amp;rsquo;s also a great base for further customization.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 25&lt;/strong&gt; adds the &lt;a href=&quot;http://melpa.org/#/material-theme&quot;&gt;&lt;code&gt;material-theme&lt;/code&gt;&lt;/a&gt; package, which is a nice dark style found in other environments.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lines 31 to 34&lt;/strong&gt; traverse the list and install any packages that are not already installed.&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; You don&amp;rsquo;t need to use the Material theme. There are many different &lt;a href=&quot;http://melpa.org/#/?q=theme&quot;&gt;Emacs themes&lt;/a&gt; available on MELPA for you to choose from. Pick one that suits your style!&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;After you install your packages, you can move on to the section titled &lt;code&gt;Basic Customization&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;36 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ===================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;37 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Basic Customization&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;38 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ===================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;39 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;40 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inhibit-startup-message&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;;; Hide the startup message&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;41 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;load-theme&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;material&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;;; Load material theme&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;42 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;global-linum-mode&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;;; Enable line numbers globally&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;43 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;44 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; User-Defined init.el ends here&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Here, you add a few other customizations:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Line 40&lt;/strong&gt; disables the initial Emacs screen containing the tutorial information. You may want to leave this commented out by using a double semicolon (&lt;code&gt;;;&lt;/code&gt;) until you&amp;rsquo;re more comfortable with Emacs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 41&lt;/strong&gt; loads and activates the Material theme. If you want to install a different theme, then use its name here instead. You can also comment out this line to use the default Emacs theme.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Line 42&lt;/strong&gt; displays line numbers in every buffer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now that you have a complete basic configuration file in place, you can save the file using &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-s&quot;&gt;S&lt;/kbd&gt;&lt;/span&gt;. Then, close and restart Emacs to see the changes.&lt;/p&gt;
&lt;p&gt;The first time Emacs runs with these options, it may take a few seconds to start as it sets up the packaging infrastructure. When that&amp;rsquo;s finished, you&amp;rsquo;ll see that your Emacs window looks a bit different:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-themed.19e8b3055961.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/emacsv2-themed.19e8b3055961.png&quot; width=&quot;951&quot; height=&quot;736&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-themed.19e8b3055961.png&amp;amp;w=237&amp;amp;sig=44786c28c5cd6896c51c9fc652f306baa264b4ec 237w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-themed.19e8b3055961.png&amp;amp;w=475&amp;amp;sig=ab93e8894915e06a865cf5414071b2e0ea732aec 475w, https://files.realpython.com/media/emacsv2-themed.19e8b3055961.png 951w&quot; sizes=&quot;75vw&quot; alt=&quot;Emacs with the Material theme applied&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After the restart, Emacs skipped the initial screen and instead opened the last active file. The Material theme is applied, and line numbers have been added to the buffer.&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 add packages interactively after the packaging infrastructure is set up. Hit &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt;, then type &lt;code&gt;package-show-package-list&lt;/code&gt; to see all the packages available to install in Emacs. As of this writing, there are over 4300 available.&lt;/p&gt;
&lt;p&gt;With the list of packages visible, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Quickly filter the list by package name by hitting &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-f&quot;&gt;F&lt;/kbd&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;View the details of any package by clicking its name.&lt;/li&gt;
&lt;li&gt;Install the package from the package view by clicking the &lt;em&gt;Install&lt;/em&gt; link.&lt;/li&gt;
&lt;li&gt;Close the package list using &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-q&quot;&gt;Q&lt;/kbd&gt;&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id=&quot;emacs-for-python-development-with-elpy&quot;&gt;Emacs for Python Development With &lt;code&gt;elpy&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;Emacs is ready out of the box to edit Python code. The library file &lt;code&gt;python.el&lt;/code&gt; provides &lt;em&gt;python-mode&lt;/em&gt;, which enables basic indentation and syntax highlighting support. However, this built-in package doesn&amp;rsquo;t provide much else. To properly compete with Python-specific &lt;a href=&quot;https://realpython.com/python-ides-code-editors-guide/&quot;&gt;IDEs&lt;/a&gt; (Integrated Development Environments), you&amp;rsquo;ll add more capabilities.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://elpy.readthedocs.org/en/latest/&quot;&gt;&lt;code&gt;elpy&lt;/code&gt;&lt;/a&gt; package (&lt;strong&gt;Emacs Lisp Python Environment&lt;/strong&gt;) provides a near-complete set of &lt;a href=&quot;https://elpy.readthedocs.org/en/latest/ide.html&quot;&gt;Python IDE features&lt;/a&gt;, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Automatic indentation&lt;/li&gt;
&lt;li&gt;Syntax highlighting&lt;/li&gt;
&lt;li&gt;Auto completion&lt;/li&gt;
&lt;li&gt;Syntax checking&lt;/li&gt;
&lt;li&gt;Python REPL integration&lt;/li&gt;
&lt;li&gt;Virtual environment support&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To install and enable &lt;code&gt;elpy&lt;/code&gt;, you add the package to your Emacs configuration. The following change to &lt;code&gt;init.el&lt;/code&gt; will do the trick:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;myPackages&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;better-defaults&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;;; Set up some better Emacs defaults&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;elpy&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;;; Emacs Lisp Python Environment&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;material-theme&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;;; Theme&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once &lt;code&gt;elpy&lt;/code&gt; is installed, you need to enable it. Add the following code just before the end of your &lt;code&gt;init.el&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;45 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;c1&quot;&gt;;; ====================================&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;46 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;c1&quot;&gt;;; Development Setup&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;47 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;c1&quot;&gt;;; ====================================&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;48 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;c1&quot;&gt;;; Enable elpy&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;49 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;elpy-enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;50 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;51 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; User-Defined init.el ends here&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You now have a new section titled &lt;code&gt;Development Setup&lt;/code&gt;. Line 49 enables &lt;code&gt;elpy&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;alert alert-primary&quot; role=&quot;alert&quot;&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Unfortunately, Emacs will only read the contents of the initialization file once when it starts. If you make any changes to it, then the easiest and safest way to load them is to restart Emacs.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;To see the new mode in action, go back to the  &lt;a href=&quot;https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes&quot;&gt;Sieve of Eratosthenes&lt;/a&gt; code you entered &lt;a href=&quot;https://realpython.com/emacs-the-best-python-editor/#basic-emacs&quot;&gt;earlier&lt;/a&gt;. Create a new Python file and retype the Sieve code directly:&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;n&quot;&gt;MAX_PRIME&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;100&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;sieve&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;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;MAX_PRIME&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;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&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;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAX_PRIME&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;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sieve&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;lineno&quot;&gt; 6 &lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&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;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;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;o&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;MAX_PRIME&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;lineno&quot;&gt; 8 &lt;/span&gt;      &lt;span class=&quot;n&quot;&gt;sieve&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;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;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note the intentional syntax error on line 4.&lt;/p&gt;
&lt;p&gt;This is what your Python file would look like in Emacs:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-elpy-in-action2-new.0c6148bf17aa.gif&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-66&quot; src=&quot;https://files.realpython.com/media/emacsv2-elpy-in-action2-new.0c6148bf17aa.gif&quot; width=&quot;734&quot; height=&quot;605&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-in-action2-new.0c6148bf17aa.gif&amp;amp;w=183&amp;amp;sig=ff6ae6eb66333099fb63159fca880b4eb900d19c 183w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-in-action2-new.0c6148bf17aa.gif&amp;amp;w=367&amp;amp;sig=252cffed11ac0f97b72e36a8e9970a0d407b992a 367w, https://files.realpython.com/media/emacsv2-elpy-in-action2-new.0c6148bf17aa.gif 734w&quot; sizes=&quot;75vw&quot; alt=&quot;elpy helping Python code writing in Emacs&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Auto-indentation and keyword highlighting still work as before. However, you should also see an error indicator on line 4:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-elpy-basic-error.bb845d5ed619.png&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-66&quot; src=&quot;https://files.realpython.com/media/emacsv2-elpy-basic-error.bb845d5ed619.png&quot; width=&quot;1094&quot; height=&quot;612&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-basic-error.bb845d5ed619.png&amp;amp;w=273&amp;amp;sig=0887528fd8225c5502a17ec1e47dc204d099c1e9 273w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-basic-error.bb845d5ed619.png&amp;amp;w=547&amp;amp;sig=787c7ad923c6918fcf43caeb74178efd9a99324a 547w, https://files.realpython.com/media/emacsv2-elpy-basic-error.bb845d5ed619.png 1094w&quot; sizes=&quot;75vw&quot; alt=&quot;Error highlighting with elpy in Emacs&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This error indicator pops up in the &lt;code&gt;for&lt;/code&gt; loop when you typed &lt;code&gt;as&lt;/code&gt; instead of &lt;code&gt;in&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Correct that error, then type &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt; while in the Python buffer to run the file without leaving Emacs:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-elpy-execute.cc6b3aa999b0.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/emacsv2-elpy-execute.cc6b3aa999b0.png&quot; width=&quot;1396&quot; height=&quot;1335&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-execute.cc6b3aa999b0.png&amp;amp;w=349&amp;amp;sig=14899c443493a3642d00fa7cb43c1153d6e2eb8f 349w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-execute.cc6b3aa999b0.png&amp;amp;w=698&amp;amp;sig=ed8996cd0e763fb18cb226f03e4d4ca57b38f64a 698w, https://files.realpython.com/media/emacsv2-elpy-execute.cc6b3aa999b0.png 1396w&quot; sizes=&quot;75vw&quot; alt=&quot;Executing Python code in Emacs&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When you use this command, Emacs will do the following:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new buffer named &lt;em&gt;*Python*&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Open your Python interpreter and connect it to that buffer&lt;/li&gt;
&lt;li&gt;Create a new window under your current code window to display the buffer&lt;/li&gt;
&lt;li&gt;Send the code to the interpreter to execute&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can scroll through the &lt;em&gt;*Python*&lt;/em&gt; buffer to see which interpreter was run and how the code was started. You can even type commands at the prompt (&lt;code&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt;) at the bottom.&lt;/p&gt;
&lt;p&gt;Often, you&amp;rsquo;ll want to execute your code in a &lt;a href=&quot;https://realpython.com/python-virtual-environments-a-primer/&quot;&gt;virtual environment&lt;/a&gt; using the interpreter and packages specified for that environment. Fortunately, &lt;code&gt;elpy&lt;/code&gt; includes the &lt;a href=&quot;http://melpa.org/#/pyvenv&quot;&gt;&lt;code&gt;pyvenv&lt;/code&gt;&lt;/a&gt; package, which provides built-in support for virtual environments.&lt;/p&gt;
&lt;p&gt;To use an existing virtual environment in Emacs, type &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;code&gt;pyvenv-workon&lt;/code&gt;. Emacs will ask for the name of the virtual environment to use and activate it. You can deactivate the current virtual environment with &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;code&gt;pyvenv-deactivate&lt;/code&gt;. You can also access this functionality from the Emacs menu, under &lt;em&gt;Virtual Envs&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You can also configure &lt;code&gt;elpy&lt;/code&gt; from within Emacs. Type &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;code&gt;elpy-config&lt;/code&gt; to display the following dialog:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-elpy-config.b7274dfd71da.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/emacsv2-elpy-config.b7274dfd71da.png&quot; width=&quot;1006&quot; height=&quot;786&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-config.b7274dfd71da.png&amp;amp;w=251&amp;amp;sig=62bcee0e1fe328bf904bde3895b1bd663545c0c1 251w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-config.b7274dfd71da.png&amp;amp;w=503&amp;amp;sig=2705f4196d03fafc60133aa7442b6b97b21859b3 503w, https://files.realpython.com/media/emacsv2-elpy-config.b7274dfd71da.png 1006w&quot; sizes=&quot;75vw&quot; alt=&quot;Configuring elpy in Emacs&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You should see valuable debugging information, as well as options to configure &lt;code&gt;elpy&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now you&amp;rsquo;ve put all of the basics of using Emacs with Python in place. Time to put some icing on this cake!&lt;/p&gt;
&lt;h2 id=&quot;additional-python-language-features&quot;&gt;Additional Python Language Features&lt;/h2&gt;
&lt;p&gt;In addition to all of the basic IDE features described above, there are other syntax features you can use with Emacs for Python development. In this tutorial, you&amp;rsquo;ll cover these three:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Syntax checking with &lt;a href=&quot;http://www.flycheck.org/&quot;&gt;&lt;code&gt;flycheck&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Code formatting with &lt;a href=&quot;https://realpython.com/python-pep8/&quot;&gt;PEP 8&lt;/a&gt; and &lt;a href=&quot;https://pypi.org/project/black/&quot;&gt;&lt;code&gt;black&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Integration with Jupyter and IPython&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is not an exhaustive list, however! Feel free to play around with Emacs and Python to see what other syntax features you can discover.&lt;/p&gt;
&lt;h3 id=&quot;syntax-checking&quot;&gt;Syntax Checking&lt;/h3&gt;
&lt;p&gt;By default, &lt;code&gt;elpy&lt;/code&gt; uses a syntax-checking package called &lt;a href=&quot;https://www.gnu.org/software/emacs/manual/html_node/flymake/index.html&quot;&gt;&lt;code&gt;flymake&lt;/code&gt;&lt;/a&gt;. While &lt;code&gt;flymake&lt;/code&gt; is built into Emacs, it only has native support four languages, and it requires significant effort to be able to support new languages.&lt;/p&gt;
&lt;p&gt;Luckily, there is a newer and more complete solution available! The syntax-checking package &lt;a href=&quot;http://www.flycheck.org/&quot;&gt;&lt;code&gt;flycheck&lt;/code&gt;&lt;/a&gt; supports real-time syntax checking in over 50 languages and is designed to be quickly configured for new languages. You can read about the differences between &lt;code&gt;flymake&lt;/code&gt; and &lt;code&gt;flycheck&lt;/code&gt; in the &lt;a href=&quot;https://www.flycheck.org/en/latest/user/flycheck-versus-flymake.html&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;You can quickly switch &lt;code&gt;elpy&lt;/code&gt; to use &lt;code&gt;flycheck&lt;/code&gt; instead of &lt;code&gt;flymake&lt;/code&gt;. First, add &lt;code&gt;flycheck&lt;/code&gt; to your &lt;code&gt;init.el&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;myPackages&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;better-defaults&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;;; Set up some better Emacs defaults&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;elpy&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;;; Emacs Lisp Python Environment&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;flycheck&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;;; On the fly syntax checking&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;material-theme&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;;; Theme&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &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;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;flycheck&lt;/code&gt; will now be installed with the other packages.&lt;/p&gt;
&lt;p&gt;Then, add the following lines in the &lt;code&gt;Development Setup&lt;/code&gt; section:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;46 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ====================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;47 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Development Setup&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;48 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ====================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;49 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Enable elpy&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;50 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;elpy-enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;51 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;52 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;c1&quot;&gt;;; Enable Flycheck&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;53 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;flycheck&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;54 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;elpy-modules&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;delq&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;elpy-module-flymake&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;elpy-modules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;55 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;elpy-mode-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;flycheck-mode&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;This will enable &lt;code&gt;flycheck&lt;/code&gt; when Emacs runs your initialization file. Now you&amp;rsquo;ll see real-time syntax feedback whenever you use Emacs for Python code editing:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-elpy-flycheck.283989e48c0f.gif&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-66&quot; src=&quot;https://files.realpython.com/media/emacsv2-elpy-flycheck.283989e48c0f.gif&quot; width=&quot;677&quot; height=&quot;537&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-flycheck.283989e48c0f.gif&amp;amp;w=169&amp;amp;sig=cbb7d3d2c348b518d68d1c6aeb067e5c6b3b7cc4 169w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-flycheck.283989e48c0f.gif&amp;amp;w=338&amp;amp;sig=d34d1bdcea780dc11bf97551f7a547a60fbe245c 338w, https://files.realpython.com/media/emacsv2-elpy-flycheck.283989e48c0f.gif 677w&quot; sizes=&quot;75vw&quot; alt=&quot;Flycheck syntax checking in elpy&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Notice the syntax reminder for &lt;a href=&quot;https://realpython.com/python-range/&quot;&gt;&lt;code&gt;range()&lt;/code&gt;&lt;/a&gt;, which appears at the bottom of the window as you type.&lt;/p&gt;
&lt;h3 id=&quot;code-formatting&quot;&gt;Code Formatting&lt;/h3&gt;
&lt;p&gt;Love it or hate it, &lt;a href=&quot;https://www.python.org/dev/peps/pep-0008/&quot;&gt;PEP 8&lt;/a&gt; is here to stay. If you want to follow all or some of the standards, then you&amp;rsquo;ll probably want an automated way to do so. Two popular solutions are &lt;a href=&quot;https://pypi.python.org/pypi/autopep8/&quot;&gt;&lt;code&gt;autopep8&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://pypi.org/project/black/&quot;&gt;&lt;code&gt;black&lt;/code&gt;&lt;/a&gt;. These code formatting tools must be installed in your Python environment before they can be used. To learn more about how to install an auto-formatter, check out &lt;a href=&quot;https://realpython.com/python-pep8/#autoformatters&quot;&gt;How to Write Beautiful Python Code With PEP 8&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once the auto-formatter is available, you can install the proper Emacs package to enable it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://melpa.org/#/py-autopep8&quot;&gt;&lt;strong&gt;&lt;code&gt;py-autopep8&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; connects &lt;code&gt;autopep8&lt;/code&gt; to Emacs.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://melpa.org/#/blacken&quot;&gt;&lt;strong&gt;&lt;code&gt;blacken&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; enables &lt;code&gt;black&lt;/code&gt; to run from within Emacs.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You only need to install one of these in Emacs. To do so, add one of the following highlighted lines to your &lt;code&gt;init.el&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;myPackages&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;better-defaults&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;;; Set up some better Emacs defaults&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;elpy&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;;; Emacs Lisp Python Environment&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;flycheck&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;;; On the fly syntax checking&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;py-autopep8&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;;; Run autopep8 on save&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;blacken&lt;/span&gt;                         &lt;span class=&quot;c1&quot;&gt;;; Black formatting on save&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;29 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;material-theme&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;;; Theme&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31 &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 using &lt;code&gt;black&lt;/code&gt;, then you&amp;rsquo;re done! &lt;code&gt;elpy&lt;/code&gt; recognizes the &lt;code&gt;blacken&lt;/code&gt; package and will enable it automatically.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using &lt;code&gt;autopep8&lt;/code&gt;, however, then you&amp;rsquo;ll need to enable the formatter in the &lt;code&gt;Development Setup&lt;/code&gt; section:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;48 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ====================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;49 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Development Setup&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;50 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ====================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;51 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Enable elpy&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;52 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;elpy-enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;53 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;54 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Enable Flycheck&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;55 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;flycheck&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;56 &lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;elpy-modules&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;delq&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;elpy-module-flymake&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;elpy-modules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;57 &lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;elpy-mode-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;flycheck-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;58 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;59 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;c1&quot;&gt;;; Enable autopep8&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;60 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;py-autopep8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;61 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;elpy-mode-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;py-autopep8-enable-on-save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;62 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;63 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; User-Defined init.el ends here&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, every time you save your Python code, the buffer is automatically formatted and saved, and the contents reloaded. You can see how this works with some badly formatted Sieve code and the &lt;code&gt;black&lt;/code&gt; formatter:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-elpy-autopep8-cropped.2200a001b675.gif&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-66&quot; src=&quot;https://files.realpython.com/media/emacsv2-elpy-autopep8-cropped.2200a001b675.gif&quot; width=&quot;674&quot; height=&quot;579&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-autopep8-cropped.2200a001b675.gif&amp;amp;w=168&amp;amp;sig=8f8523bd2925231935b3089e8cea7960d8dfad62 168w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-autopep8-cropped.2200a001b675.gif&amp;amp;w=337&amp;amp;sig=bd64927bda1707aed94d1ded344a30765b2b1621 337w, https://files.realpython.com/media/emacsv2-elpy-autopep8-cropped.2200a001b675.gif 674w&quot; sizes=&quot;75vw&quot; alt=&quot;Autopep running in Emacs&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can see that after the file is saved, it&amp;rsquo;s reloaded in the buffer with the proper &lt;code&gt;black&lt;/code&gt; formatting applied.&lt;/p&gt;
&lt;h3 id=&quot;integration-with-jupyter-and-ipython&quot;&gt;Integration With Jupyter and IPython&lt;/h3&gt;
&lt;p&gt;Emacs can also work with Jupyter Notebooks and the IPython REPL. If you don&amp;rsquo;t already have Jupyter installed, then check out &lt;a href=&quot;https://realpython.com/jupyter-notebook-introduction/&quot;&gt;Jupyter Notebook: An Introduction&lt;/a&gt;. Once Jupyter is ready to go, add the following lines to your &lt;code&gt;init.el&lt;/code&gt; after the call to enable &lt;code&gt;elpy&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;48 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ====================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;49 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Development Setup&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;50 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; ====================================&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;51 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Enable elpy&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;52 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;elpy-enable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;53 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;54 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;c1&quot;&gt;;; Use IPython for REPL&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;55 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;python-shell-interpreter&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;jupyter&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;56 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;      &lt;span class=&quot;nv&quot;&gt;python-shell-interpreter-args&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;console --simple-prompt&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;57 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;      &lt;span class=&quot;nv&quot;&gt;python-shell-prompt-detect-failure-warning&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;58 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-to-list&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;python-shell-completion-native-disabled-interpreters&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;59 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;             &lt;span class=&quot;s&quot;&gt;&amp;quot;jupyter&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;60 &lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;61 &lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;;; Enable Flycheck&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;62 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;when&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;require&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;flycheck&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;63 &lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;setq&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;elpy-modules&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;delq&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;elpy-module-flymake&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;elpy-modules&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;64 &lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;elpy-mode-hook&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;&amp;#39;flycheck-mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will update Emacs to use IPython rather than the standard Python REPL. Now when you run your code with &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt;, you&amp;rsquo;ll see the IPython REPL:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-elpy-ipython.0ffd4ab8d398.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/emacsv2-elpy-ipython.0ffd4ab8d398.png&quot; width=&quot;940&quot; height=&quot;670&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-ipython.0ffd4ab8d398.png&amp;amp;w=235&amp;amp;sig=0dc05620ef10647dd53ae003622674c98cfb23ca 235w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-ipython.0ffd4ab8d398.png&amp;amp;w=470&amp;amp;sig=2f53391a309ddc787ea086fd7956faa190d32060 470w, https://files.realpython.com/media/emacsv2-elpy-ipython.0ffd4ab8d398.png 940w&quot; sizes=&quot;75vw&quot; alt=&quot;IPython running in Emacs&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;While this is pretty useful on its own, the real magic is in the Jupyter Notebook integration. As always, you need to add a bit of configuration to enable everything. The &lt;a href=&quot;http://melpa.org/#/ein&quot;&gt;&lt;code&gt;ein&lt;/code&gt;&lt;/a&gt; package enables an IPython Notebook client in Emacs. You can add it to your &lt;code&gt;init.el&lt;/code&gt; like so:&lt;/p&gt;
&lt;div class=&quot;highlight lisp&quot;&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;23 &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;defvar&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;myPackages&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;24 &lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;better-defaults&lt;/span&gt;                 &lt;span class=&quot;c1&quot;&gt;;; Set up some better Emacs defaults&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;25 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;elpy&lt;/span&gt;                            &lt;span class=&quot;c1&quot;&gt;;; Emacs Lisp Python Environment&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;26 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;flycheck&lt;/span&gt;                        &lt;span class=&quot;c1&quot;&gt;;; On the fly syntax checking&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;27 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;py-autopep8&lt;/span&gt;                     &lt;span class=&quot;c1&quot;&gt;;; Run autopep8 on save&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;28 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;blacken&lt;/span&gt;                         &lt;span class=&quot;c1&quot;&gt;;; Black formatting on save&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;29 &lt;/span&gt;&lt;span class=&quot;hll&quot;&gt;    &lt;span class=&quot;nv&quot;&gt;ein&lt;/span&gt;                             &lt;span class=&quot;c1&quot;&gt;;; Emacs IPython Notebook&lt;/span&gt;
&lt;/span&gt;&lt;span class=&quot;lineno&quot;&gt;30 &lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;material-theme&lt;/span&gt;                  &lt;span class=&quot;c1&quot;&gt;;; Theme&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;31 &lt;/span&gt;    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;lineno&quot;&gt;32 &lt;/span&gt;  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can now start a Jupyter server and work with Notebooks from within Emacs.&lt;/p&gt;
&lt;p&gt;To start the server, use the command &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;code&gt;ein:jupyter-server-start&lt;/code&gt;. Then provide a folder in which to run the server. You&amp;rsquo;ll see a new buffer showing the Jupyter Notebooks available in the folder selected:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-jupyter-notebook-list.0806e3866ca5.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/emacsv2-jupyter-notebook-list.0806e3866ca5.png&quot; width=&quot;1024&quot; height=&quot;640&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-jupyter-notebook-list.0806e3866ca5.png&amp;amp;w=256&amp;amp;sig=f37876e0d15ccc331de7fcca2684088f909f8ba9 256w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-jupyter-notebook-list.0806e3866ca5.png&amp;amp;w=512&amp;amp;sig=a2d1ffbd4b9abdf80104164faf11ca109541156a 512w, https://files.realpython.com/media/emacsv2-jupyter-notebook-list.0806e3866ca5.png 1024w&quot; sizes=&quot;75vw&quot; alt=&quot;List of Jupyter notebooks available in Emacs using ein&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;From here you can create a new Notebook with a selected kernel by clicking &lt;em&gt;New Notebook&lt;/em&gt;, or open an existing Notebook from the list at the bottom by clicking &lt;em&gt;Open&lt;/em&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-jupyter-open-notebook.4498d339bb47.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/emacsv2-jupyter-open-notebook.4498d339bb47.png&quot; width=&quot;1396&quot; height=&quot;1211&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-jupyter-open-notebook.4498d339bb47.png&amp;amp;w=349&amp;amp;sig=58bfca477e69ba409ac677bbb0cb318c8f2c0803 349w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-jupyter-open-notebook.4498d339bb47.png&amp;amp;w=698&amp;amp;sig=4fe7f43972bd4bf0dffb4c1071e4adea9c9ecb4a 698w, https://files.realpython.com/media/emacsv2-jupyter-open-notebook.4498d339bb47.png 1396w&quot; sizes=&quot;75vw&quot; alt=&quot;Opening an existing Jupyter notebook in Emacs using ein&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can complete the exact same task by typing &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-f&quot;&gt;F&lt;/kbd&gt;&lt;/span&gt;, and then typing &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-z&quot;&gt;Z&lt;/kbd&gt;&lt;/span&gt;. This will open the Jupyter Notebook directly in Emacs as a file.&lt;/p&gt;
&lt;p&gt;With a Notebook open, you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Move around the Notebook cells using the arrow keys&lt;/li&gt;
&lt;li&gt;Add a new cell above the current cell using &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-a&quot;&gt;A&lt;/kbd&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Add a new cell below the current cell using &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-b&quot;&gt;B&lt;/kbd&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Execute new cells using either &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt; or &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-enter&quot;&gt;Enter&lt;/kbd&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&amp;rsquo;s an example of how to move around a Notebook, add a new cell, and execute it:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-ein-add-new-cell-cropped.416eb37ae530.gif&quot; target=&quot;_blank&quot;&gt;&lt;img class=&quot;img-fluid mx-auto d-block border w-66&quot; src=&quot;https://files.realpython.com/media/emacsv2-ein-add-new-cell-cropped.416eb37ae530.gif&quot; width=&quot;731&quot; height=&quot;605&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-ein-add-new-cell-cropped.416eb37ae530.gif&amp;amp;w=182&amp;amp;sig=500b652ed35f295a2886a2d348fb33412ff8802c 182w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-ein-add-new-cell-cropped.416eb37ae530.gif&amp;amp;w=365&amp;amp;sig=aba6fd60e6f4c1dab66ae8c0197adcd0bfbbf925 365w, https://files.realpython.com/media/emacsv2-ein-add-new-cell-cropped.416eb37ae530.gif 731w&quot; sizes=&quot;75vw&quot; alt=&quot;Adding a new cell to a Jupyter notebook in Emacs using ein&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You can save your work using &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-s&quot;&gt;S&lt;/kbd&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p&gt;When you&amp;rsquo;re done working in your notebook, you can close it using &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-shift&quot;&gt;Shift&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-3&quot;&gt;3&lt;/kbd&gt;&lt;/span&gt;. You can stop the Jupyter server completely by hitting &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-alt&quot;&gt;Alt&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;code&gt;ein:jupyter-server-stop&lt;/code&gt;. Emacs will ask you if you want to kill the server and close all open Notebooks.&lt;/p&gt;
&lt;p&gt;Of course, this is just the tip of the Jupyter iceberg! You can explore everything the &lt;code&gt;ein&lt;/code&gt; package can do in the &lt;a href=&quot;https://tkf.github.io/emacs-ipython-notebook/&quot;&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;testing-support&quot;&gt;Testing Support&lt;/h2&gt;
&lt;p&gt;Do you write perfect code that has no side-effects and performs well under all conditions? Of course&amp;hellip; not! If this sounds like you, though, then you&amp;rsquo;re free to skip ahead a bit. But for most developers, testing code is a requirement.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;elpy&lt;/code&gt; provides extensive support for running &lt;a href=&quot;https://elpy.readthedocs.io/en/latest/ide.html#testing&quot;&gt;tests&lt;/a&gt;, including support for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.python.org/3/library/unittest.html&quot;&gt;&lt;code&gt;unittest&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://nose.readthedocs.io/en/latest/&quot;&gt;&lt;code&gt;nose&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.pytest.org/en/latest/&quot;&gt;&lt;code&gt;pytest&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://pypi.org/project/green/&quot;&gt;&lt;code&gt;green&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://twistedmatrix.com/trac/wiki/TwistedTrial&quot;&gt;Twisted&amp;rsquo;s &lt;code&gt;trial&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://realpython.com/python-testing/#how-to-use-the-django-test-runner&quot;&gt;Django&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To demonstrate the testing capabilities, the code for this tutorial includes a version of Edsger Dijkstra&amp;rsquo;s &lt;a href=&quot;https://en.wikipedia.org/wiki/Shunting-yard_algorithm&quot;&gt;shunting yard algorithm&lt;/a&gt;. This algorithm parses mathematical equations that are written using infix notation. You can download the code at the link below:&lt;/p&gt;
&lt;div class=&quot;alert alert-warning&quot; role=&quot;alert&quot;&gt;&lt;p&gt;&lt;strong&gt;Download Code:&lt;/strong&gt; &lt;a href=&quot;https://realpython.com/bonus/emacs/&quot; class=&quot;alert-link&quot; data-toggle=&quot;modal&quot; data-target=&quot;#modal-emacs&quot; data-focus=&quot;false&quot;&gt;Click here to download the code you&#39;ll use&lt;/a&gt; to learn about Emacs for Python in this tutorial.&lt;/p&gt;&lt;/div&gt;

&lt;p&gt;To start, let&amp;rsquo;s get a more complete picture of the project by viewing the project folder. You can open a folder in Emacs using &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-d&quot;&gt;D&lt;/kbd&gt;&lt;/span&gt;. Next, you&amp;rsquo;ll display two windows in the same frame by splitting the frame vertically with &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-x&quot;&gt;X&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-3&quot;&gt;3&lt;/kbd&gt;&lt;/span&gt;. Finally, you navigate to the test file in the left window, and click on it to open it in the right window:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-pyeval-split.ac6c0b9e67ce.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/emacsv2-pyeval-split.ac6c0b9e67ce.png&quot; width=&quot;1006&quot; height=&quot;780&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-pyeval-split.ac6c0b9e67ce.png&amp;amp;w=251&amp;amp;sig=a4f5d258aead7640125b708f689b0d99d1af87a1 251w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-pyeval-split.ac6c0b9e67ce.png&amp;amp;w=503&amp;amp;sig=f52946b5e19ddfe08df11a3d98194577189f37e2 503w, https://files.realpython.com/media/emacsv2-pyeval-split.ac6c0b9e67ce.png 1006w&quot; sizes=&quot;75vw&quot; alt=&quot;Split window view for PyEval under Emacs&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The test file &lt;code&gt;expr_test.py&lt;/code&gt; is a basic &lt;code&gt;unittest&lt;/code&gt; file that contains a single test case with six tests. To run the test case, type &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-t&quot;&gt;T&lt;/kbd&gt;&lt;/span&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://files.realpython.com/media/emacsv2-elpy-test-run.65dbd0ae9344.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/emacsv2-elpy-test-run.65dbd0ae9344.png&quot; width=&quot;1006&quot; height=&quot;780&quot; srcset=&quot;https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-test-run.65dbd0ae9344.png&amp;amp;w=251&amp;amp;sig=9e4a76dd820e47889137563afd4bbb084d972dd6 251w, https://robocrop.realpython.net/?url=https%3A//files.realpython.com/media/emacsv2-elpy-test-run.65dbd0ae9344.png&amp;amp;w=503&amp;amp;sig=67a2910d16efb523494b0e1c6842831909118016 503w, https://files.realpython.com/media/emacsv2-elpy-test-run.65dbd0ae9344.png 1006w&quot; sizes=&quot;75vw&quot; alt=&quot;Results of a Python unittest run in Emacs&quot;/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The results are displayed in the left window. Notice how all six tests were run. You can run a single test in a test file by putting the cursor in that test before typing &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-c&quot;&gt;C&lt;/kbd&gt;&lt;/span&gt; &lt;span class=&quot;keys&quot;&gt;&lt;kbd class=&quot;key-control&quot;&gt;Ctrl&lt;/kbd&gt;&lt;span&gt;+&lt;/span&gt;&lt;kbd class=&quot;key-t&quot;&gt;T&lt;/kbd&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;h2 id=&quot;debugging-support&quot;&gt;Debugging Support&lt;/h2&gt;
&lt;p&gt;When tests fail, you&amp;rsquo;ll need to delve into the code to figure out why. The built-in &lt;em&gt;python-mode&lt;/em&gt; allows you to use Emacs for Python code debugging with &lt;code&gt;pdb